diff options
Diffstat (limited to 'src')
50 files changed, 1722 insertions, 1108 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 8064e42..0a9d155 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -19,11 +19,8 @@ CLEANFILES = transmission-remote-gtk.desktop desktopdir = $(datadir)/applications desktop_DATA = transmission-remote-gtk.desktop -schemadir = @GCONF_SCHEMA_FILE_DIR@ -schema_DATA = transmission-remote-gtk.schemas - bin_PROGRAMS = transmission-remote-gtk -INCLUDES = --pedantic -Wall -I.. -O2 -DTRGLICENSE=\""$(trglicense)"\" -DTRGLOCALEDIR=\""$(trglocaledir)"\" $(jsonglib_CFLAGS) $(gthread_CFLAGS) $(gtk_CFLAGS) $(gconf_CFLAGS) $(gio_CFLAGS) $(unique_CFLAGS) $(notify_CFLAGS) $(libproxy_CFLAGS) -std=gnu99 +INCLUDES = --pedantic -Wall -I.. -DTRGLICENSE=\""$(trglicense)"\" -DTRGLOCALEDIR=\""$(trglocaledir)"\" $(jsonglib_CFLAGS) $(gthread_CFLAGS) $(gtk_CFLAGS) $(gio_CFLAGS) $(unique_CFLAGS) $(notify_CFLAGS) $(libproxy_CFLAGS) -std=gnu99 transmission_remote_gtk_SOURCES = main.c \ requests.c \ @@ -57,8 +54,8 @@ transmission_remote_gtk_SOURCES = main.c \ trg-trackers-tree-view.c \ trg-trackers-model.c \ trg-torrent-props-dialog.c \ - trg-json-widgets.c \ trg-torrent-add-url-dialog.c \ + trg-json-widgets.c \ trg-cell-renderer-speed.c \ trg-cell-renderer-size.c \ trg-cell-renderer-ratio.c \ @@ -74,14 +71,11 @@ transmission_remote_gtk_SOURCES = main.c \ trg-torrent-add-dialog.c \ trg-file-parser.c \ bencode.c \ - trg-preferences.c \ + trg-prefs.c \ trg-destination-combo.c \ $(NULL) -transmission_remote_gtk_LDFLAGS = -lm -lcurl $(jsonglib_LIBS) $(gtk_LIBS) $(gthread_LIBS) $(GEOIP_LIBS) $(gconf_LIBS) $(gio_LIBS) $(unique_LIBS) $(notify_LIBS) $(libproxy_LIBS) - -install-data-local: install-icons update-icon-cache - GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) gconftool-2 --makefile-install-rule $(srcdir)/$(schema_DATA) +transmission_remote_gtk_LDFLAGS = -lm -lcurl $(jsonglib_LIBS) $(gtk_LIBS) $(gthread_LIBS) $(GEOIP_LIBS) $(gio_LIBS) $(unique_LIBS) $(notify_LIBS) $(libproxy_LIBS) gtk_update_icon_cache = gtk-update-icon-cache -f -t diff --git a/src/dispatch.c b/src/dispatch.c index d58517c..5bf42c1 100644 --- a/src/dispatch.c +++ b/src/dispatch.c @@ -28,9 +28,9 @@ #include "json.h" static void dispatch_async_threadfunc(struct DispatchAsyncData *task, - trg_client * client); + TrgClient * client); -JsonObject *dispatch(trg_client * client, JsonNode * req, int *status) +JsonObject *dispatch(TrgClient * client, JsonNode * req, int *status) { gchar *serialized; struct http_response *response; @@ -75,7 +75,7 @@ JsonObject *dispatch(trg_client * client, JsonNode * req, int *status) } static void dispatch_async_threadfunc(struct DispatchAsyncData *task, - trg_client * client) + TrgClient * client) { int status; JsonObject *result = dispatch(client, task->req, &status); @@ -84,13 +84,13 @@ static void dispatch_async_threadfunc(struct DispatchAsyncData *task, g_free(task); } -GThreadPool *dispatch_init_pool(trg_client * client) +GThreadPool *dispatch_init_pool(TrgClient * client) { return g_thread_pool_new((GFunc) dispatch_async_threadfunc, client, DISPATCH_POOL_SIZE, FALSE, NULL); } -gboolean dispatch_async(trg_client * client, JsonNode * req, +gboolean dispatch_async(TrgClient * client, JsonNode * req, void (*callback) (JsonObject *, int, gpointer), gpointer data) { @@ -101,7 +101,7 @@ gboolean dispatch_async(trg_client * client, JsonNode * req, args->data = data; args->req = req; - g_thread_pool_push(client->pool, args, &error); + trg_client_thread_pool_push(client, args, &error); if (error) { g_printf("thread creation error: %s\n", error->message); g_error_free(error); diff --git a/src/dispatch.h b/src/dispatch.h index 2520e10..6734f33 100644 --- a/src/dispatch.h +++ b/src/dispatch.h @@ -33,10 +33,10 @@ struct DispatchAsyncData { void (*callback) (JsonObject *, int, gpointer); }; -JsonObject *dispatch(trg_client * client, JsonNode * req, int *status); -gboolean dispatch_async(trg_client * client, JsonNode * req, +JsonObject *dispatch(TrgClient * client, JsonNode * req, int *status); +gboolean dispatch_async(TrgClient * client, JsonNode * req, void (*callback) (JsonObject *, int, gpointer), gpointer data); -GThreadPool *dispatch_init_pool(trg_client * client); +GThreadPool *dispatch_init_pool(TrgClient * client); #endif /* DISPATCH_H_ */ @@ -33,7 +33,7 @@ #include "config.h" #endif -static struct http_response *trg_http_perform_inner(trg_client * client, +static struct http_response *trg_http_perform_inner(TrgClient * client, gchar * req, gboolean recurse); @@ -51,7 +51,7 @@ void http_response_free(struct http_response *response) g_free(response); } -static struct http_response *trg_http_perform_inner(trg_client * tc, +static struct http_response *trg_http_perform_inner(TrgClient * tc, gchar * req, gboolean recurse) { @@ -59,6 +59,7 @@ static struct http_response *trg_http_perform_inner(trg_client * tc, long httpCode; struct http_response *response; struct curl_slist *headers = NULL; + gchar *proxy, *session_id; response = g_new(struct http_response, 1); response->size = 0; @@ -68,9 +69,9 @@ static struct http_response *trg_http_perform_inner(trg_client * tc, handle = curl_easy_init(); curl_easy_setopt(handle, CURLOPT_USERAGENT, PACKAGE_NAME); - curl_easy_setopt(handle, CURLOPT_PASSWORD, tc->password); - curl_easy_setopt(handle, CURLOPT_USERNAME, tc->username); - curl_easy_setopt(handle, CURLOPT_URL, tc->url); + curl_easy_setopt(handle, CURLOPT_PASSWORD, trg_client_get_password(tc)); + curl_easy_setopt(handle, CURLOPT_USERNAME, trg_client_get_username(tc)); + curl_easy_setopt(handle, CURLOPT_URL, trg_client_get_url(tc)); curl_easy_setopt(handle, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, &http_receive_callback); @@ -79,16 +80,19 @@ static struct http_response *trg_http_perform_inner(trg_client * tc, curl_easy_setopt(handle, CURLOPT_WRITEHEADER, (void *) tc); curl_easy_setopt(handle, CURLOPT_POSTFIELDS, req); - if (tc->ssl) + + if (trg_client_get_ssl(tc)) curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0); - if (tc->proxy) { + proxy = trg_client_get_proxy(tc); + if (proxy) { curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); - curl_easy_setopt(handle, CURLOPT_PROXY, tc->proxy); + curl_easy_setopt(handle, CURLOPT_PROXY, proxy); } - if (tc->session_id) { - headers = curl_slist_append(headers, tc->session_id); + session_id = trg_client_get_session_id(tc); + if (session_id) { + headers = curl_slist_append(headers, session_id); curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers); } @@ -97,7 +101,7 @@ static struct http_response *trg_http_perform_inner(trg_client * tc, curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &httpCode); curl_easy_cleanup(handle); - if (headers != NULL) + if (headers) curl_slist_free_all(headers); if (response->status == CURLE_OK) { @@ -112,7 +116,7 @@ static struct http_response *trg_http_perform_inner(trg_client * tc, return response; } -struct http_response *trg_http_perform(trg_client * tc, gchar * req) +struct http_response *trg_http_perform(TrgClient * tc, gchar * req) { return trg_http_perform_inner(tc, req, TRUE); } @@ -136,18 +140,22 @@ static size_t header_callback(void *ptr, size_t size, size_t nmemb, void *data) { char *header = (char *) (ptr); - trg_client *client = (trg_client *) data; + TrgClient *tc = TRG_CLIENT(data); + gchar *session_id; if (g_str_has_prefix(header, "X-Transmission-Session-Id: ")) { char *nl; - if (client->session_id) - g_free(client->session_id); + session_id = trg_client_get_session_id(tc); + if (session_id) + g_free(session_id); - client->session_id = g_strdup(header); - nl = strrchr(client->session_id, '\r'); + session_id = g_strdup(header); + nl = strrchr(session_id, '\r'); if (nl) *nl = '\0'; + + trg_client_set_session_id(tc, session_id); } return (nmemb * size); @@ -38,6 +38,6 @@ struct http_response { }; void http_response_free(struct http_response *response); -struct http_response *trg_http_perform(trg_client * client, gchar * req); +struct http_response *trg_http_perform(TrgClient * client, gchar * req); #endif /* HTTP_H_ */ @@ -80,7 +80,7 @@ int main(int argc, char *argv[]) int returnValue = EXIT_SUCCESS; UniqueApp *app = NULL; TrgMainWindow *window; - trg_client *client; + TrgClient *client; gboolean withUnique; g_type_init(); @@ -88,6 +88,7 @@ int main(int argc, char *argv[]) gdk_threads_init(); gtk_init(&argc, &argv); + g_set_application_name (PACKAGE_NAME); setlocale(LC_ALL, ""); bindtextdomain(GETTEXT_PACKAGE, TRGLOCALEDIR); bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); @@ -126,7 +127,7 @@ int main(int argc, char *argv[]) if (response != UNIQUE_RESPONSE_OK) returnValue = EXIT_FAILURE; } else { - client = trg_init_client(); + client = trg_client_new(); curl_global_init(CURL_GLOBAL_ALL); diff --git a/src/torrent.h b/src/torrent.h index c5e2e10..85d9632 100644 --- a/src/torrent.h +++ b/src/torrent.h @@ -24,15 +24,15 @@ #define TORRENT_FLAG_ERROR (1 << 0) /* 0x01 */ #define TORRENT_FLAG_COMPLETE (1 << 1) /* 0x02 */ -#define TORRENT_FLAG_INCOMPLETE (1 << 2) /* 0x02 */ -#define TORRENT_FLAG_SEEDING (1 << 3) /* 0x04 */ -#define TORRENT_FLAG_CHECKING (1 << 4) /* 0x08 */ -#define TORRENT_FLAG_WAITING_CHECK (1 << 5) /* 0x16 */ -#define TORRENT_FLAG_DOWNLOADING (1 << 6) /* 0x32 */ -#define TORRENT_FLAG_PAUSED (1 << 7) /* 0x64 */ -#define TORRENT_FLAG_ACTIVE (1 << 8) /* 0x128 */ -#define FILTER_FLAG_TRACKER (1 << 9) /* 0x256 */ -#define FILTER_FLAG_DIR (1 << 10) /* 0x512 */ +#define TORRENT_FLAG_INCOMPLETE (1 << 2) /* 0x04 */ +#define TORRENT_FLAG_SEEDING (1 << 3) /* 0x08 */ +#define TORRENT_FLAG_CHECKING (1 << 4) /* 0x16 */ +#define TORRENT_FLAG_WAITING_CHECK (1 << 5) /* 0x32 */ +#define TORRENT_FLAG_DOWNLOADING (1 << 6) /* 0x64 */ +#define TORRENT_FLAG_PAUSED (1 << 7) /* 0x128 */ +#define TORRENT_FLAG_ACTIVE (1 << 8) /* 0x256 */ +#define FILTER_FLAG_TRACKER (1 << 9) /* 0x512 */ +#define FILTER_FLAG_DIR (1 << 10) /* 0x1024 */ gint64 torrent_get_size(JsonObject * t); const gchar *torrent_get_name(JsonObject * t); diff --git a/src/transmission-remote-gtk.schemas b/src/transmission-remote-gtk.schemas deleted file mode 100644 index 7b56d1a..0000000 --- a/src/transmission-remote-gtk.schemas +++ /dev/null @@ -1,291 +0,0 @@ -<gconfschemafile> - <schemalist> - - <schema> - <key>/schemas/apps/transmission-remote-gtk/add-dialog</key> - <applyto>/apps/transmission-remote-gtk/add-dialog</applyto> - <owner>transmission-remote-gtk</owner> - <type>bool</type> - <default>1</default> - - <locale name="C"> - <short>Show add dialog</short> - <long>Show add dialog</long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/transmission-remote-gtk/update-active-only</key> - <applyto>/apps/transmission-remote-gtk/update-active-only</applyto> - <owner>transmission-remote-gtk</owner> - <type>bool</type> - <default>0</default> - - <locale name="C"> - <short>Update Active Only</short> - <long>Update Active Only</long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/transmission-remote-gtk/auto-connect</key> - <applyto>/apps/transmission-remote-gtk/auto-connect</applyto> - <owner>transmission-remote-gtk</owner> - <type>bool</type> - <default>0</default> - - <locale name="C"> - <short>Auto connect</short> - <long>Auto connect</long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/transmission-remote-gtk/system-tray-minimise</key> - <applyto>/apps/transmission-remote-gtk/system-tray-minimise</applyto> - <owner>transmission-remote-gtk</owner> - <type>bool</type> - <default>1</default> - - <locale name="C"> - <short>Minimise to system tray</short> - <long>Minimise to system tray</long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/transmission-remote-gtk/filter-dirs</key> - <applyto>/apps/transmission-remote-gtk/filter-dirs</applyto> - <owner>transmission-remote-gtk</owner> - <type>bool</type> - <default>0</default> - - <locale name="C"> - <short>Filter dirs</short> - <long>Filter dirs</long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/transmission-remote-gtk/filter-trackers</key> - <applyto>/apps/transmission-remote-gtk/filter-trackers</applyto> - <owner>transmission-remote-gtk</owner> - <type>bool</type> - <default>1</default> - - <locale name="C"> - <short>Filter trackers</short> - <long>Filter trackers</long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/transmission-remote-gtk/ssl</key> - <applyto>/apps/transmission-remote-gtk/ssl</applyto> - <owner>transmission-remote-gtk</owner> - <type>bool</type> - <default>0</default> - - <locale name="C"> - <short>SSL</short> - <long>SSL</long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/transmission-remote-gtk/add-notify</key> - <applyto>/apps/transmission-remote-gtk/add-notify</applyto> - <owner>transmission-remote-gtk</owner> - <type>bool</type> - <default>0</default> - - <locale name="C"> - <short>Added notifications</short> - <long>Added notifications</long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/transmission-remote-gtk/complete-notify</key> - <applyto>/apps/transmission-remote-gtk/complete-notify</applyto> - <owner>transmission-remote-gtk</owner> - <type>bool</type> - <default>0</default> - - <locale name="C"> - <short>Complete notifications</short> - <long>Complete notifications</long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/transmission-remote-gtk/system-tray</key> - <applyto>/apps/transmission-remote-gtk/system-tray</applyto> - <owner>transmission-remote-gtk</owner> - <type>bool</type> - <default>1</default> - - <locale name="C"> - <short>Show system tray icon</short> - <long>Show system tray icon while app is running</long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/transmission-remote-gtk/add-options-dialog</key> - <applyto>/apps/transmission-remote-gtk/add-options-dialog</applyto> - <owner>transmission-remote-gtk</owner> - <type>bool</type> - <default>1</default> - - <locale name="C"> - <short>Options dialog</short> - <long>Options dialog</long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/transmission-remote-gtk/start-paused</key> - <applyto>/apps/transmission-remote-gtk/start-paused</applyto> - <owner>transmission-remote-gtk</owner> - <type>bool</type> - <default>0</default> - - <locale name="C"> - <short>Start paused</short> - <long>Start paused</long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/transmission-remote-gtk/show-graph</key> - <applyto>/apps/transmission-remote-gtk/show-graph</applyto> - <owner>transmission-remote-gtk</owner> - <type>bool</type> - <default>0</default> - - <locale name="C"> - <short>Show graph</short> - <long>Show graph</long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/transmission-remote-gtk/update-interval</key> - <applyto>/apps/transmission-remote-gtk/update-interval</applyto> - <owner>transmission-remote-gtk</owner> - <type>int</type> - <default>3</default> - - <locale name="C"> - <short>Update interval seconds</short> - <long>Update interval seconds</long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/transmission-remote-gtk/window-height</key> - <applyto>/apps/transmission-remote-gtk/window-height</applyto> - <owner>transmission-remote-gtk</owner> - <type>int</type> - <default>600</default> - - <locale name="C"> - <short>Window height</short> - <long>Window height</long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/transmission-remote-gtk/graph-span</key> - <applyto>/apps/transmission-remote-gtk/graph-span</applyto> - <owner>transmission-remote-gtk</owner> - <type>int</type> - <default>60</default> - - <locale name="C"> - <short>Graph span</short> - <long>Graph span</long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/transmission-remote-gtk/window-width</key> - <applyto>/apps/transmission-remote-gtk/window-width</applyto> - <owner>transmission-remote-gtk</owner> - <type>int</type> - <default>800</default> - - <locale name="C"> - <short>Window width</short> - <long>Window width</long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/transmission-remote-gtk/port</key> - <applyto>/apps/transmission-remote-gtk/port</applyto> - <owner>transmission-remote-gtk</owner> - <type>int</type> - <default>9091</default> - - <locale name="C"> - <short>Port</short> - <long>Port</long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/transmission-remote-gtk/last-torrent-dir</key> - <applyto>/apps/transmission-remote-gtk/last-torrent-dir</applyto> - <owner>transmission-remote-gtk</owner> - <type>string</type> - <default></default> - - <locale name="C"> - <short>Last torrent directory</short> - <long>Last torrent directory</long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/transmission-remote-gtk/username</key> - <applyto>/apps/transmission-remote-gtk/username</applyto> - <owner>transmission-remote-gtk</owner> - <type>string</type> - <default></default> - - <locale name="C"> - <short>Username</short> - <long>Username</long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/transmission-remote-gtk/password</key> - <applyto>/apps/transmission-remote-gtk/password</applyto> - <owner>transmission-remote-gtk</owner> - <type>string</type> - <default></default> - - <locale name="C"> - <short>Password</short> - <long>Password</long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/transmission-remote-gtk/hostname</key> - <applyto>/apps/transmission-remote-gtk/hostname</applyto> - <owner>transmission-remote-gtk</owner> - <type>string</type> - <default></default> - - <locale name="C"> - <short>Hostname</short> - <long>Hostname</long> - </locale> - </schema> - - </schemalist> -</gconfschemafile> diff --git a/src/trg-client.c b/src/trg-client.c index 3eb6d6d..5de32a9 100644 --- a/src/trg-client.c +++ b/src/trg-client.c @@ -22,113 +22,210 @@ #endif #include <string.h> -#include <glib-object.h> -#include <gconf/gconf-client.h> +#include <glib.h> +#include <glib/gprintf.h> #ifdef HAVE_LIBPROXY #include <proxy.h> #endif -#include "trg-client.h" -#include "trg-preferences.h" +#include "trg-prefs.h" #include "util.h" #include "dispatch.h" +#include "trg-client.h" + +enum { + CLIENT_SIGNAL_PROFILE_CHANGE, + CLIENT_SIGNAL_PROFILE_NEW, + CLIENT_SIGNAL_COUNT +}; + +static guint signals[CLIENT_SIGNAL_COUNT] = { 0 }; + +G_DEFINE_TYPE (TrgClient, trg_client, G_TYPE_OBJECT) + +#define TRG_CLIENT_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRG_TYPE_CLIENT, TrgClientPrivate)) + +typedef struct _TrgClientPrivate TrgClientPrivate; + +struct _TrgClientPrivate { + char *session_id; + gboolean activeOnlyUpdate; + gint failCount; + gint interval; + gint64 updateSerial; + JsonObject *session; + gboolean ssl; + float version; + char *url; + char *username; + char *password; + char *proxy; + GHashTable *torrentTable; + GThreadPool *pool; + GMutex *updateMutex; + TrgPrefs *prefs; +}; + +static void +trg_client_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +trg_client_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} -gboolean trg_client_supports_tracker_edit(trg_client * tc) +static void +trg_client_dispose (GObject *object) { - return tc->session && tc->version >= 2.10; + G_OBJECT_CLASS (trg_client_parent_class)->dispose (object); } -trg_client *trg_init_client() +static void +trg_client_class_init (TrgClientClass *klass) { - trg_client *client = g_new0(trg_client, 1); + GObjectClass *object_class = G_OBJECT_CLASS (klass); - client->gconf = gconf_client_get_default(); - client->updateMutex = g_mutex_new(); - client->activeOnlyUpdate = - gconf_client_get_bool(client->gconf, - TRG_GCONF_KEY_UPDATE_ACTIVE_ONLY, NULL); - client->pool = dispatch_init_pool(client); + g_type_class_add_private (klass, sizeof (TrgClientPrivate)); - return client; + object_class->get_property = trg_client_get_property; + object_class->set_property = trg_client_set_property; + object_class->dispose = trg_client_dispose; + + signals[CLIENT_SIGNAL_PROFILE_CHANGE] = + gtk_signal_new ("client-profile-changed", + GTK_RUN_LAST, + G_TYPE_FROM_CLASS(object_class), + GTK_SIGNAL_OFFSET (TrgClientClass, client_profile_changed), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + + signals[CLIENT_SIGNAL_PROFILE_NEW] = + gtk_signal_new ("client-profile-new", + GTK_RUN_LAST, + G_TYPE_FROM_CLASS(object_class), + GTK_SIGNAL_OFFSET (TrgClientClass, client_profile_new), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); } -#define check_for_error(error) if (error) { g_error_free(error); return TRG_GCONF_SCHEMA_ERROR; } +static void +trg_client_init (TrgClient *self) +{ +} -void trg_client_set_session(trg_client * tc, JsonObject * session) +TrgClient* +trg_client_new (void) { - if (tc->session) - json_object_unref(tc->session); + TrgClient *tc = g_object_new (TRG_TYPE_CLIENT, NULL); + TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc); + TrgPrefs *prefs = priv->prefs = trg_prefs_new(); - session_get_version(session, &tc->version); + trg_prefs_load(prefs); - tc->session = session; + priv->updateMutex = g_mutex_new(); + priv->activeOnlyUpdate = + trg_prefs_get_bool(prefs, + TRG_PREFS_KEY_UPDATE_ACTIVE_ONLY, TRG_PREFS_PROFILE); + priv->pool = dispatch_init_pool(tc); + + return tc; } -int trg_client_populate_with_settings(trg_client * tc, GConfClient * gconf) +gboolean trg_client_supports_tracker_edit(TrgClient * tc) { + TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc); + return priv->session && priv->version >= 2.10; +} + +void trg_client_set_session(TrgClient * tc, JsonObject * session) +{ + TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc); + + if (priv->session) + json_object_unref(priv->session); + + session_get_version(session, &priv->version); + + priv->session = session; +} + +TrgPrefs *trg_client_get_prefs(TrgClient *tc) +{ + TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc); + return priv->prefs; +} + +int trg_client_populate_with_settings(TrgClient * tc) +{ + TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc); + TrgPrefs *prefs = priv->prefs; + gint port; gchar *host; - GError *error = NULL; #ifdef HAVE_LIBPROXY pxProxyFactory *pf = NULL; #endif - g_free(tc->url); - tc->url = NULL; + g_free(priv->url); + priv->url = NULL; - g_free(tc->username); - tc->username = NULL; + g_free(priv->username); + priv->username = NULL; - g_free(tc->password); - tc->password = NULL; + g_free(priv->password); + priv->password = NULL; port = - gconf_client_get_int_or_default(gconf, TRG_GCONF_KEY_PORT, - TRG_PORT_DEFAULT, &error); - check_for_error(error); + trg_prefs_get_int(prefs, TRG_PREFS_KEY_PORT, TRG_PREFS_PROFILE); - host = gconf_client_get_string(gconf, TRG_GCONF_KEY_HOSTNAME, &error); - check_for_error(error); + host = trg_prefs_get_string(prefs, TRG_PREFS_KEY_HOSTNAME, TRG_PREFS_PROFILE); if (!host || strlen(host) < 1) return TRG_NO_HOSTNAME_SET; - tc->ssl = gconf_client_get_bool(gconf, TRG_GCONF_KEY_SSL, &error); - check_for_error(error); + priv->ssl = trg_prefs_get_bool(prefs, TRG_PREFS_KEY_SSL, TRG_PREFS_PROFILE); - tc->url = + priv->url = g_strdup_printf("%s://%s:%d/transmission/rpc", - tc->ssl ? "https" : "http", host, port); + priv->ssl ? "https" : "http", host, port); g_free(host); - tc->interval = - gconf_client_get_int_or_default(gconf, - TRG_GCONF_KEY_UPDATE_INTERVAL, - TRG_INTERVAL_DEFAULT, &error); - check_for_error(error); - if (tc->interval < 1) - tc->interval = TRG_INTERVAL_DEFAULT; + priv->interval = + trg_prefs_get_int(prefs, TRG_PREFS_KEY_UPDATE_INTERVAL, TRG_PREFS_PROFILE); + if (priv->interval < 1) + priv->interval = TRG_INTERVAL_DEFAULT; - tc->username = - gconf_client_get_string(gconf, TRG_GCONF_KEY_USERNAME, &error); - check_for_error(error); + priv->username = + trg_prefs_get_string(prefs, TRG_PREFS_KEY_USERNAME, TRG_PREFS_PROFILE); - tc->password = - gconf_client_get_string(gconf, TRG_GCONF_KEY_PASSWORD, &error); - check_for_error(error); + priv->password = + trg_prefs_get_string(prefs, TRG_PREFS_KEY_PASSWORD, TRG_PREFS_PROFILE); - g_free(tc->proxy); - tc->proxy = NULL; + g_free(priv->proxy); + priv->proxy = NULL; #ifdef HAVE_LIBPROXY if ((pf = px_proxy_factory_new())) { - char **proxies = px_proxy_factory_get_proxies(pf, tc->url); + char **proxies = px_proxy_factory_get_proxies(pf, priv->url); int i; for (i = 0; proxies[i]; i++) { if (g_str_has_prefix(proxies[i], "http")) { - g_free(tc->proxy); - tc->proxy = proxies[i]; + g_free(priv->proxy); + priv->proxy = proxies[i]; } else { g_free(proxies[i]); } @@ -141,3 +238,150 @@ int trg_client_populate_with_settings(trg_client * tc, GConfClient * gconf) return 0; } + +gchar *trg_client_get_password(TrgClient *tc) +{ + TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc); + return priv->password; +} + +gchar *trg_client_get_username(TrgClient *tc) +{ + TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc); + return priv->username; +} + +gchar *trg_client_get_url(TrgClient *tc) +{ + TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc); + return priv->url; +} + +gchar *trg_client_get_session_id(TrgClient *tc) +{ + TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc); + return priv->session_id; +} + +void trg_client_set_session_id(TrgClient *tc, gchar *session_id) +{ + TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc); + priv->session_id = session_id; +} + +void trg_client_status_change(TrgClient *tc, gboolean connected) +{ + TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc); + if (!connected) { + json_object_unref(priv->session); + priv->session = NULL; + } +} + +JsonObject* trg_client_get_session(TrgClient *tc) +{ + TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc); + return priv->session; +} + +void trg_client_thread_pool_push(TrgClient *tc, gpointer data, GError **err) +{ + TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc); + g_thread_pool_push(priv->pool, data, err); +} + +void trg_client_inc_serial(TrgClient *tc) +{ + TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc); + priv->updateSerial++; +} + +gint64 trg_client_get_serial(TrgClient *tc) +{ + TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc); + return priv->updateSerial; +} + +gboolean trg_client_get_ssl(TrgClient *tc) +{ + TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc); + return priv->ssl; +} + +gchar *trg_client_get_proxy(TrgClient *tc) +{ + TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc); + return priv->proxy; +} + +void trg_client_set_torrent_table(TrgClient *tc, GHashTable *table) +{ + TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc); + priv->torrentTable = table; +} + +GHashTable* trg_client_get_torrent_table(TrgClient *tc) +{ + TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc); + return priv->torrentTable; +} + +gboolean trg_client_is_connected(TrgClient *tc) +{ + TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc); + return priv->session != NULL; +} + +void trg_client_updatelock(TrgClient *tc) +{ + TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc); + g_mutex_lock(priv->updateMutex); +} + +gint trg_client_get_failcount(TrgClient *tc) +{ + TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc); + return priv->failCount; +} + +gint trg_client_inc_failcount(TrgClient *tc) +{ + TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc); + return ++(priv->failCount); +} + +void trg_client_reset_failcount(TrgClient *tc) +{ + TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc); + priv->failCount = 0; +} + +void trg_client_updateunlock(TrgClient *tc) +{ + TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc); + g_mutex_unlock(priv->updateMutex); +} + +gboolean trg_client_get_activeonlyupdate(TrgClient *tc) +{ + TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc); + return priv->activeOnlyUpdate; +} + +void trg_client_set_activeonlyupdate(TrgClient *tc, gboolean activeOnlyUpdate) +{ + TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc); + priv->activeOnlyUpdate = activeOnlyUpdate; +} + +gint trg_client_get_interval(TrgClient *tc) +{ + TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc); + return priv->interval; +} + +void trg_client_set_interval(TrgClient *tc, gint interval) +{ + TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc); + priv->interval = interval; +} diff --git a/src/trg-client.h b/src/trg-client.h index 4a587f9..bd21a2e 100644 --- a/src/trg-client.h +++ b/src/trg-client.h @@ -16,48 +16,92 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +/* trg-client.h */ -#ifndef TRG_CLIENT_H_ -#define TRG_CLIENT_H_ +#ifndef _TRG_CLIENT_H_ +#define _TRG_CLIENT_H_ #define TRANSMISSION_MIN_SUPPORTED 2.0 +#define TRG_MAX_RETRIES 3 #define TORRENT_GET_MODE_FIRST 0 #define TORRENT_GET_MODE_ACTIVE 1 #define TORRENT_GET_MODE_INTERACTION 2 #define TORRENT_GET_MODE_UPDATE 3 -#define TRG_GCONF_SCHEMA_ERROR -1 #define TRG_NO_HOSTNAME_SET -2 #include <json-glib/json-glib.h> -#include <gconf/gconf-client.h> +#include <glib-object.h> +#include "trg-prefs.h" #include "session-get.h" +G_BEGIN_DECLS + +#define TRG_TYPE_CLIENT trg_client_get_type() + +#define TRG_CLIENT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), TRG_TYPE_CLIENT, TrgClient)) + +#define TRG_CLIENT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), TRG_TYPE_CLIENT, TrgClientClass)) + +#define TRG_IS_CLIENT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TRG_TYPE_CLIENT)) + +#define TRG_IS_CLIENT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), TRG_TYPE_CLIENT)) + +#define TRG_CLIENT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), TRG_TYPE_CLIENT, TrgClientClass)) + typedef struct { - char *session_id; - gboolean activeOnlyUpdate; - gint failCount; - gint interval; - gint64 updateSerial; - JsonObject *session; - gboolean ssl; - float version; - char *url; - char *username; - char *password; - char *proxy; - GHashTable *torrentTable; - GThreadPool *pool; - GConfClient *gconf; - GMutex *updateMutex; -} trg_client; - -trg_client *trg_init_client(); -int trg_client_populate_with_settings(trg_client * tc, - GConfClient * gconf); -void trg_client_set_session(trg_client * tc, JsonObject * session); -gboolean trg_client_supports_tracker_edit(trg_client * tc); - -#endif /* TRG_CLIENT_H_ */ + GObject parent; +} TrgClient; + +typedef struct { + GObjectClass parent_class; + void (*client_profile_changed) (TrgClient * client, gpointer data); + void (*client_profile_new) (TrgClient * client, gpointer data); +} TrgClientClass; + +GType trg_client_get_type (void); + +TrgClient* trg_client_new (void); +TrgPrefs* trg_client_get_prefs(TrgClient *tc); +int trg_client_populate_with_settings(TrgClient * tc); +void trg_client_set_session(TrgClient * tc, JsonObject * session); +gboolean trg_client_supports_tracker_edit(TrgClient * tc); + +gchar *trg_client_get_password(TrgClient *tc); +gchar *trg_client_get_username(TrgClient *tc); +gchar *trg_client_get_url(TrgClient *tc); +gchar *trg_client_get_session_id(TrgClient *tc); +void trg_client_set_session_id(TrgClient *tc, gchar *session_id); +gboolean trg_client_get_ssl(TrgClient *tc); +gchar *trg_client_get_proxy(TrgClient *tc); +gint64 trg_client_get_serial(TrgClient *tc); +void trg_client_thread_pool_push(TrgClient *tc, gpointer data, GError **err); +void trg_client_set_torrent_table(TrgClient *tc, GHashTable *table); +GHashTable* trg_client_get_torrent_table(TrgClient *tc); +JsonObject* trg_client_get_session(TrgClient *tc); +void trg_client_status_change(TrgClient *tc, gboolean connected); +gboolean trg_client_get_activeonlyupdate(TrgClient *tc); +gboolean trg_client_is_connected(TrgClient *tc); +void trg_client_updateunlock(TrgClient *tc); +void trg_client_updatelock(TrgClient *tc); +gint trg_client_inc_failcount(TrgClient *tc); +gint trg_client_get_failcount(TrgClient *tc); +void trg_client_reset_failcount(TrgClient *tc); +void trg_client_inc_serial(TrgClient *tc); +gint trg_client_get_interval(TrgClient *tc); +void trg_client_set_interval(TrgClient *tc, gint interval); +void trg_client_set_activeonlyupdate(TrgClient *tc, gboolean activeOnlyUpdate); +void trg_client_set_connid(TrgClient *tc, gint connid); +gint trg_client_get_connid(TrgClient *tc); +gint trg_client_new_profile(TrgClient *tc); + +G_END_DECLS + +#endif // _TRG_CLIENT_H_ diff --git a/src/trg-destination-combo.c b/src/trg-destination-combo.c index 9dc4b87..7c7dedd 100644 --- a/src/trg-destination-combo.c +++ b/src/trg-destination-combo.c @@ -32,7 +32,7 @@ G_DEFINE_TYPE(TrgDestinationCombo, trg_destination_combo, typedef struct _TrgDestinationComboPrivate TrgDestinationComboPrivate; struct _TrgDestinationComboPrivate { - trg_client *client; + TrgClient *client; }; enum { @@ -71,6 +71,21 @@ trg_destination_combo_set_property(GObject * object, guint property_id, } } +static gboolean g_slist_str_set_add(GSList ** list, const gchar * string, gint pos) +{ + GSList *li; + for (li = *list; li; li = g_slist_next(li)) + if (!g_strcmp0((gchar *) li->data, string)) + return FALSE; + + if (pos < 0) + *list = g_slist_insert_sorted(*list, (gpointer)string, (GCompareFunc)g_strcmp0); + else + *list = g_slist_insert(*list, (gpointer)string, pos); + + return TRUE; +} + static GObject *trg_destination_combo_constructor(GType type, guint n_construct_properties, @@ -84,10 +99,10 @@ static GObject *trg_destination_combo_constructor(GType type, TrgDestinationComboPrivate *priv = TRG_DESTINATION_COMBO_GET_PRIVATE(object); - trg_client *client = priv->client; + TrgClient *client = priv->client; const gchar *defaultDownDir = - json_object_get_string_member(client->session, SGET_DOWNLOAD_DIR); + json_object_get_string_member(trg_client_get_session(client), SGET_DOWNLOAD_DIR); GtkListStore *comboModel = gtk_list_store_new(1, G_TYPE_STRING); @@ -101,10 +116,8 @@ static GObject *trg_destination_combo_constructor(GType type, GtkTreePath *path; JsonObject *t; - g_slist_str_set_add(&dirs, defaultDownDir); - - g_mutex_lock(client->updateMutex); - torrentItemRefs = g_hash_table_get_values(client->torrentTable); + trg_client_updatelock(client); + torrentItemRefs = g_hash_table_get_values(trg_client_get_torrent_table(client)); for (li = torrentItemRefs; li; li = g_list_next(li)) { rr = (GtkTreeRowReference *) li->data; model = gtk_tree_row_reference_get_model(rr); @@ -117,29 +130,28 @@ static GObject *trg_destination_combo_constructor(GType type, gtk_tree_model_get(model, &iter, TORRENT_COLUMN_JSON, &t, -1); dd = torrent_get_download_dir(t); - if (dd) - g_slist_str_set_add(&dirs, dd); - + if (dd && g_strcmp0(dd, defaultDownDir)) + g_slist_str_set_add(&dirs, dd, -1); } gtk_tree_path_free(path); } } g_list_free(torrentItemRefs); - g_mutex_unlock(client->updateMutex); + g_slist_str_set_add(&dirs, defaultDownDir, 0); for (sli = dirs; sli != NULL; sli = g_slist_next(sli)) gtk_list_store_insert_with_values(comboModel, NULL, INT_MAX, 0, (gchar *) sli->data, -1); - g_str_slist_free(dirs); + trg_client_updateunlock(client); + g_slist_free(dirs); gtk_combo_box_set_model(GTK_COMBO_BOX(object), GTK_TREE_MODEL(comboModel)); gtk_combo_box_entry_set_text_column(GTK_COMBO_BOX_ENTRY(object), 0); - /* cleanup */ g_object_unref(comboModel); return object; @@ -166,14 +178,13 @@ trg_destination_combo_class_init(TrgDestinationComboClass * klass) G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - } static void trg_destination_combo_init(TrgDestinationCombo * self) { } -GtkWidget *trg_destination_combo_new(trg_client * client) +GtkWidget *trg_destination_combo_new(TrgClient * client) { return GTK_WIDGET(g_object_new(TRG_TYPE_DESTINATION_COMBO, "trg-client", client, NULL)); diff --git a/src/trg-destination-combo.h b/src/trg-destination-combo.h index 17ecc84..c5926a9 100644 --- a/src/trg-destination-combo.h +++ b/src/trg-destination-combo.h @@ -47,7 +47,7 @@ typedef struct { GType trg_destination_combo_get_type(void); -GtkWidget *trg_destination_combo_new(trg_client * client); +GtkWidget *trg_destination_combo_new(TrgClient * client); G_END_DECLS #endif /* TRG_DESTINATION_COMBO_H_ */ diff --git a/src/trg-files-tree-view.c b/src/trg-files-tree-view.c index 89581bc..f0975fa 100644 --- a/src/trg-files-tree-view.c +++ b/src/trg-files-tree-view.c @@ -39,7 +39,7 @@ G_DEFINE_TYPE(TrgFilesTreeView, trg_files_tree_view, TRG_TYPE_TREE_VIEW) typedef struct _TrgFilesTreeViewPrivate TrgFilesTreeViewPrivate; struct _TrgFilesTreeViewPrivate { - trg_client *client; + TrgClient *client; TrgMainWindow *win; }; @@ -306,21 +306,21 @@ static void trg_files_tree_view_init(TrgFilesTreeView * self) G_CALLBACK(view_onButtonPressed), NULL); g_signal_connect(self, "popup-menu", G_CALLBACK(view_onPopupMenu), NULL); - - trg_tree_view_setup_columns(ttv); } TrgFilesTreeView *trg_files_tree_view_new(TrgFilesModel * model, TrgMainWindow * win, - trg_client * client) + TrgClient * client) { GObject *obj = g_object_new(TRG_TYPE_FILES_TREE_VIEW, NULL); TrgFilesTreeViewPrivate *priv = TRG_FILES_TREE_VIEW_GET_PRIVATE(obj); + trg_tree_view_set_prefs(TRG_TREE_VIEW(obj), trg_client_get_prefs(client)); gtk_tree_view_set_model(GTK_TREE_VIEW(obj), GTK_TREE_MODEL(model)); priv->client = client; priv->win = win; + trg_tree_view_setup_columns(TRG_TREE_VIEW(obj)); //trg_tree_view_restore_sort(TRG_TREE_VIEW(obj)); return TRG_FILES_TREE_VIEW(obj); diff --git a/src/trg-files-tree-view.h b/src/trg-files-tree-view.h index ac006f9..06f83ba 100644 --- a/src/trg-files-tree-view.h +++ b/src/trg-files-tree-view.h @@ -50,7 +50,7 @@ GType trg_files_tree_view_get_type(void); TrgFilesTreeView *trg_files_tree_view_new(TrgFilesModel * model, TrgMainWindow * win, - trg_client * client); + TrgClient * client); G_END_DECLS #endif /* TRG_FILES_TREE_VIEW_H_ */ diff --git a/src/trg-main-window.c b/src/trg-main-window.c index 13c1d99..790caf9 100644 --- a/src/trg-main-window.c +++ b/src/trg-main-window.c @@ -33,7 +33,6 @@ #include <gdk/gdkkeysyms.h> #include <curl/curl.h> #include <libnotify/notify.h> -#include <gconf/gconf-client.h> #include "dispatch.h" #include "trg-client.h" @@ -48,7 +47,7 @@ #include "trg-main-window.h" #include "trg-about-window.h" #include "trg-tree-view.h" -#include "trg-preferences.h" +#include "trg-prefs.h" #include "trg-torrent-model.h" #include "trg-torrent-tree-view.h" #include "trg-peers-model.h" @@ -134,8 +133,7 @@ static gboolean trg_torrent_tree_view_visible_func(GtkTreeModel * model, gpointer data); static TrgTorrentTreeView * trg_main_window_torrent_tree_view_new(TrgMainWindow * win, - GtkTreeModel * model, - TrgStateSelector * selector); + GtkTreeModel * model); static gboolean trg_dialog_error_handler(TrgMainWindow * win, JsonObject * response, int status); @@ -199,7 +197,7 @@ G_DEFINE_TYPE(TrgMainWindow, trg_main_window, GTK_TYPE_WINDOW) typedef struct _TrgMainWindowPrivate TrgMainWindowPrivate; struct _TrgMainWindowPrivate { - trg_client *client; + TrgClient *client; TrgToolbar *toolBar; TrgMenuBar *menuBar; @@ -258,19 +256,19 @@ static void update_selected_torrent_notebook(TrgMainWindow * win, gint mode, gint64 id) { TrgMainWindowPrivate *priv = TRG_MAIN_WINDOW_GET_PRIVATE(win); - trg_client *client = priv->client; + TrgClient *client = priv->client; JsonObject *t; GtkTreeIter iter; - if (id >= 0 && get_torrent_data(client->torrentTable, id, &t, &iter)) { + if (id >= 0 && get_torrent_data(trg_client_get_torrent_table(client), id, &t, &iter)) { trg_toolbar_torrent_actions_sensitive(priv->toolBar, TRUE); trg_menu_bar_torrent_actions_sensitive(priv->menuBar, TRUE); trg_general_panel_update(priv->genDetails, t, &iter); trg_trackers_model_update(priv->trackersModel, - client->updateSerial, t, mode); - trg_files_model_update(priv->filesModel, client->updateSerial, t, + trg_client_get_serial(client), t, mode); + trg_files_model_update(priv->filesModel, trg_client_get_serial(client), t, mode); - trg_peers_model_update(priv->peersModel, client->updateSerial, t, + trg_peers_model_update(priv->peersModel, trg_client_get_serial(client), t, mode); } else if (id < 0) { trg_main_window_torrent_scrub(win); @@ -287,6 +285,7 @@ static void torrent_event_notification(TrgTorrentModel * model, GtkTreeIter * iter, gpointer data) { TrgMainWindowPrivate *priv = TRG_MAIN_WINDOW_GET_PRIVATE(data); + TrgPrefs *prefs = trg_client_get_prefs(priv->client); gchar *name; NotifyNotification *notify; @@ -294,7 +293,7 @@ static void torrent_event_notification(TrgTorrentModel * model, || !gtk_status_icon_is_embedded(priv->statusIcon)) return; - if (!gconf_client_get_bool(priv->client->gconf, prefKey, NULL)) + if (!trg_prefs_get_bool(prefs, prefKey, TRG_PREFS_NOFLAGS)) return; gtk_tree_model_get(GTK_TREE_MODEL(model), iter, @@ -324,7 +323,7 @@ static void on_torrent_completed(TrgTorrentModel * model, torrent_event_notification(model, GTK_STOCK_APPLY, _("This torrent has completed."), TORRENT_COMPLETE_NOTIFY_TMOUT, - TRG_GCONF_KEY_COMPLETE_NOTIFY, iter, data); + TRG_PREFS_KEY_COMPLETE_NOTIFY, iter, data); } static void on_torrent_addremove(TrgTorrentModel * model, gpointer data) @@ -339,7 +338,7 @@ static void on_torrent_added(TrgTorrentModel * model, torrent_event_notification(model, GTK_STOCK_ADD, _("This torrent has been added."), TORRENT_ADD_NOTIFY_TMOUT, - TRG_GCONF_KEY_ADD_NOTIFY, iter, data); + TRG_PREFS_KEY_ADD_NOTIFY, iter, data); } static gboolean delete_event(GtkWidget * w, @@ -352,16 +351,19 @@ static gboolean delete_event(GtkWidget * w, static void destroy_window(GtkWidget * w, gpointer data G_GNUC_UNUSED) { TrgMainWindowPrivate *priv = TRG_MAIN_WINDOW_GET_PRIVATE(w); + TrgPrefs *prefs = trg_client_get_prefs(priv->client); int width, height; + gtk_window_get_size(GTK_WINDOW(w), &width, &height); - gconf_client_set_int(priv->client->gconf, TRG_GCONF_KEY_WINDOW_HEIGHT, - height, NULL); - gconf_client_set_int(priv->client->gconf, TRG_GCONF_KEY_WINDOW_WIDTH, - width, NULL); + trg_prefs_set_int(prefs, TRG_PREFS_KEY_WINDOW_HEIGHT, + height, TRG_PREFS_GLOBAL); + trg_prefs_set_int(prefs, TRG_PREFS_KEY_WINDOW_WIDTH, + width, TRG_PREFS_GLOBAL); trg_tree_view_persist(TRG_TREE_VIEW(priv->peersTreeView)); trg_tree_view_persist(TRG_TREE_VIEW(priv->filesTreeView)); trg_tree_view_persist(TRG_TREE_VIEW(priv->torrentTreeView)); trg_tree_view_persist(TRG_TREE_VIEW(priv->trackersTreeView)); + trg_prefs_save(prefs); gtk_main_quit(); } @@ -425,14 +427,15 @@ static void pause_all_cb(GtkWidget * w G_GNUC_UNUSED, gpointer data) gboolean trg_add_from_filename(TrgMainWindow * win, gchar ** uris) { TrgMainWindowPrivate *priv = TRG_MAIN_WINDOW_GET_PRIVATE(win); - trg_client *client = priv->client; + TrgClient *client = priv->client; + TrgPrefs *prefs = trg_client_get_prefs(client); GSList *filesList = NULL; int i; for (i = 0; uris[i]; i++) filesList = g_slist_append(filesList, uris[i]); - if (pref_get_add_options_dialog(client->gconf)) { + if (trg_prefs_get_bool(prefs, TRG_PREFS_KEY_ADD_OPTIONS_DIALOG, TRG_PREFS_GLOBAL)) { gdk_threads_enter(); TrgTorrentAddDialog *dialog = trg_torrent_add_dialog_new(win, client, filesList); @@ -445,7 +448,7 @@ gboolean trg_add_from_filename(TrgMainWindow * win, gchar ** uris) args->list = filesList; args->cb_data = win; args->client = client; - args->paused = pref_get_start_paused(client->gconf); + args->paused = trg_prefs_get_bool(prefs, TRG_PREFS_KEY_START_PAUSED, TRG_PREFS_GLOBAL); args->extraArgs = FALSE; launch_add_thread(args); @@ -491,18 +494,12 @@ static void connect_cb(GtkWidget * w G_GNUC_UNUSED, gpointer data) priv = TRG_MAIN_WINDOW_GET_PRIVATE(data); populate_result = - trg_client_populate_with_settings(priv->client, - priv->client->gconf); + trg_client_populate_with_settings(priv->client); if (populate_result < 0) { gchar *msg; switch (populate_result) { - case TRG_GCONF_SCHEMA_ERROR: - msg = - _ - ("Unable to retrieve connection settings from GConf. Schema not installed?"); - break; case TRG_NO_HOSTNAME_SET: msg = _("No hostname set"); break; @@ -511,8 +508,6 @@ static void connect_cb(GtkWidget * w G_GNUC_UNUSED, gpointer data) break; } - - dialog = gtk_message_dialog_new(GTK_WINDOW(data), GTK_DIALOG_DESTROY_WITH_PARENT, @@ -782,6 +777,7 @@ static GtkWidget *trg_main_window_notebook_new(TrgMainWindow * win) { TrgMainWindowPrivate *priv = TRG_MAIN_WINDOW_GET_PRIVATE(win); + TrgPrefs *prefs = trg_client_get_prefs(priv->client); GtkWidget *notebook = priv->notebook = gtk_notebook_new(); @@ -810,14 +806,13 @@ GtkWidget *trg_main_window_notebook_new(TrgMainWindow * win) gtk_label_new(_("Files"))); priv->peersModel = trg_peers_model_new(); - priv->peersTreeView = trg_peers_tree_view_new(priv->peersModel); + priv->peersTreeView = trg_peers_tree_view_new(prefs, priv->peersModel); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), my_scrolledwin_new(GTK_WIDGET (priv->peersTreeView)), gtk_label_new(_("Peers"))); - if (gconf_client_get_bool - (priv->client->gconf, TRG_GCONF_KEY_SHOW_GRAPH, NULL)) + if (trg_prefs_get_bool(prefs, TRG_PREFS_KEY_SHOW_GRAPH, TRG_PREFS_GLOBAL)) trg_main_window_add_graph(win, FALSE); else priv->graphNotebookIndex = -1; @@ -844,7 +839,7 @@ static void on_session_get(JsonObject * response, int status, { TrgMainWindow *win = TRG_MAIN_WINDOW(data); TrgMainWindowPrivate *priv = TRG_MAIN_WINDOW_GET_PRIVATE(data); - trg_client *client = priv->client; + TrgClient *client = priv->client; JsonObject *newSession; gdk_threads_enter(); @@ -857,7 +852,7 @@ static void on_session_get(JsonObject * response, int status, newSession = get_arguments(response); - if (!client->session) { + if (!trg_client_is_connected(client)) { float version; if (session_get_version(newSession, &version)) { if (version < TRANSMISSION_MIN_SUPPORTED) { @@ -902,21 +897,20 @@ on_torrent_get(JsonObject * response, int mode, int status, gpointer data) { TrgMainWindowPrivate *priv = TRG_MAIN_WINDOW_GET_PRIVATE(data); - trg_client *client = priv->client; + TrgClient *client = priv->client; trg_torrent_model_update_stats stats; /* Disconnected between request and response callback */ - if (!client->session) { + if (!trg_client_is_connected(client)) { response_unref(response); return; } - g_mutex_lock(client->updateMutex); + trg_client_updatelock(client); gdk_threads_enter(); if (status != CURLE_OK) { - client->failCount++; - if (client->failCount >= 3) { + if (trg_client_inc_failcount(client) >= TRG_MAX_RETRIES) { trg_main_window_conn_changed(TRG_MAIN_WINDOW(data), FALSE); trg_dialog_error_handler(TRG_MAIN_WINDOW(data), response, status); @@ -927,26 +921,26 @@ on_torrent_get(JsonObject * response, int mode, int status, gpointer data) msg = make_error_message(response, status); statusBarMsg = g_strdup_printf(_("Request %d/%d failed: %s"), - client->failCount, 3, msg); + trg_client_get_failcount(client), TRG_MAX_RETRIES, msg); trg_status_bar_push_connection_msg(priv->statusBar, statusBarMsg); g_free((gpointer) msg); g_free(statusBarMsg); - g_timeout_add_seconds(client->interval, + g_timeout_add_seconds(trg_client_get_interval(client), trg_update_torrents_timerfunc, data); } gdk_threads_leave(); - g_mutex_unlock(client->updateMutex); + trg_client_updateunlock(client); response_unref(response); return; } - client->failCount = 0; + trg_client_reset_failcount(client); memset(&stats, 0, sizeof(trg_torrent_model_update_stats)); - client->updateSerial++; + trg_client_inc_serial(client); - trg_torrent_model_update(priv->torrentModel, priv->client, + trg_torrent_model_update(priv->torrentModel, client, response, &stats, mode); update_selected_torrent_notebook(TRG_MAIN_WINDOW(data), mode, @@ -958,11 +952,11 @@ on_torrent_get(JsonObject * response, int mode, int status, gpointer data) trg_torrent_graph_set_speed(priv->graph, &stats); if (mode != TORRENT_GET_MODE_INTERACTION) - g_timeout_add_seconds(client->interval, + g_timeout_add_seconds(trg_client_get_interval(client), trg_update_torrents_timerfunc, data); gdk_threads_leave(); - g_mutex_unlock(client->updateMutex); + trg_client_updateunlock(client); response_unref(response); } @@ -993,12 +987,12 @@ static void on_torrent_get_update(JsonObject * response, int status, static gboolean trg_update_torrents_timerfunc(gpointer data) { TrgMainWindowPrivate *priv = TRG_MAIN_WINDOW_GET_PRIVATE(data); - trg_client *client = priv->client; + TrgClient *tc = priv->client; - if (client->session) - dispatch_async(client, - torrent_get(client->activeOnlyUpdate ? -2 : -1), - client->activeOnlyUpdate ? on_torrent_get_active : + if (trg_client_is_connected(tc)) + dispatch_async(tc, + torrent_get(trg_client_get_activeonlyupdate(tc) ? -2 : -1), + trg_client_get_activeonlyupdate(tc) ? on_torrent_get_active : on_torrent_get_update, data); return FALSE; @@ -1078,13 +1072,11 @@ static TrgTorrentTreeView *trg_main_window_torrent_tree_view_new(TrgMainWindow * win, GtkTreeModel * - model, - TrgStateSelector - * - selector - G_GNUC_UNUSED) + model) { - TrgTorrentTreeView *torrentTreeView = trg_torrent_tree_view_new(model); + TrgMainWindowPrivate *priv = TRG_MAIN_WINDOW_GET_PRIVATE(win); + TrgTorrentTreeView *torrentTreeView = trg_torrent_tree_view_new(trg_client_get_prefs(priv->client), + model); GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(torrentTreeView)); @@ -1162,8 +1154,9 @@ on_generic_interactive_action(JsonObject * response, int status, gpointer data) { TrgMainWindowPrivate *priv = TRG_MAIN_WINDOW_GET_PRIVATE(data); + TrgClient *tc = priv->client; - if (priv->client->session) { + if (trg_client_is_connected(tc)) { gdk_threads_enter(); trg_dialog_error_handler(TRG_MAIN_WINDOW(data), response, status); gdk_threads_leave(); @@ -1172,7 +1165,7 @@ on_generic_interactive_action(JsonObject * response, int status, gint64 id; if (json_object_has_member(response, PARAM_TAG)) id = json_object_get_int_member(response, PARAM_TAG); - else if (priv->client->activeOnlyUpdate) + else if (trg_client_get_activeonlyupdate(tc)) id = -2; else id = -1; @@ -1225,7 +1218,7 @@ static void trg_main_window_conn_changed(TrgMainWindow * win, gboolean connected) { TrgMainWindowPrivate *priv = TRG_MAIN_WINDOW_GET_PRIVATE(win); - trg_client *tc = priv->client; + TrgClient *tc = priv->client; trg_toolbar_connected_change(priv->toolBar, connected); trg_menu_bar_connected_change(priv->menuBar, connected); @@ -1238,9 +1231,6 @@ void trg_main_window_conn_changed(TrgMainWindow * win, gboolean connected) gtk_widget_set_sensitive(GTK_WIDGET(priv->genDetails), connected);; if (!connected) { - json_object_unref(tc->session); - tc->session = NULL; - gtk_list_store_clear(GTK_LIST_STORE(priv->torrentModel)); trg_main_window_torrent_scrub(win); trg_state_selector_disconnect(priv->stateSelector); @@ -1248,6 +1238,8 @@ void trg_main_window_conn_changed(TrgMainWindow * win, gboolean connected) if (priv->graphNotebookIndex >= 0) trg_torrent_graph_set_nothing(priv->graph); } + + trg_client_status_change(tc, connected); } static void @@ -1455,17 +1447,18 @@ static GtkWidget *limit_menu_new(TrgMainWindow * win, gchar * title, JsonArray * ids) { TrgMainWindowPrivate *priv = TRG_MAIN_WINDOW_GET_PRIVATE(win); - trg_client *client = priv->client; + TrgClient *client = priv->client; JsonObject *current = NULL; GtkTreeIter iter; GtkWidget *toplevel, *menu, *item; gint64 limit; if (ids) - get_torrent_data(client->torrentTable, priv->selectedTorrentId, - ¤t, &iter); + get_torrent_data(trg_client_get_torrent_table(client), + priv->selectedTorrentId, + ¤t, &iter); else - current = client->session; + current = trg_client_get_session(client); limit = json_object_get_boolean_member(current, enabledKey) ? json_object_get_int_member(current, speedKey) : -1; @@ -1576,7 +1569,7 @@ trg_status_icon_view_menu(GtkStatusIcon * icon G_GNUC_UNUSED, GdkEventButton * event, gpointer data) { TrgMainWindowPrivate *priv = TRG_MAIN_WINDOW_GET_PRIVATE(data); - gboolean connected = priv->client->session != NULL; + gboolean connected = trg_client_is_connected(priv->client); GtkWidget *menu; menu = gtk_menu_new(); @@ -1700,14 +1693,14 @@ static gboolean window_state_event(GtkWidget * widget, gpointer trayIcon) { TrgMainWindowPrivate *priv = TRG_MAIN_WINDOW_GET_PRIVATE(widget); + TrgPrefs *prefs = trg_client_get_prefs(priv->client); if (priv->statusIcon && event->changed_mask == GDK_WINDOW_STATE_ICONIFIED && (event->new_window_state == GDK_WINDOW_STATE_ICONIFIED || event->new_window_state == (GDK_WINDOW_STATE_ICONIFIED | GDK_WINDOW_STATE_MAXIMIZED)) && - gconf_client_get_bool_or_true(priv->client->gconf, - TRG_GCONF_KEY_SYSTEM_TRAY_MINIMISE)) + trg_prefs_get_bool(prefs, TRG_PREFS_KEY_SYSTEM_TRAY_MINIMISE, TRG_PREFS_GLOBAL)) { gtk_widget_hide(GTK_WIDGET(widget)); } @@ -1791,6 +1784,7 @@ static GObject *trg_main_window_constructor(GType type, GtkIconTheme *theme; gint width, height; gboolean tray; + TrgPrefs *prefs; self = TRG_MAIN_WINDOW(G_OBJECT_CLASS (trg_main_window_parent_class)->constructor @@ -1798,6 +1792,8 @@ static GObject *trg_main_window_constructor(GType type, construct_params)); priv = TRG_MAIN_WINDOW_GET_PRIVATE(self); + prefs = trg_client_get_prefs(priv->client); + theme = gtk_icon_theme_get_default(); priv->icon = gtk_icon_theme_load_icon(theme, PACKAGE_NAME, 48, @@ -1818,7 +1814,7 @@ static GObject *trg_main_window_constructor(GType type, G_CALLBACK(window_state_event), NULL); priv->torrentModel = trg_torrent_model_new(); - priv->client->torrentTable = get_torrent_table(priv->torrentModel); + trg_client_set_torrent_table(priv->client, get_torrent_table(priv->torrentModel)); g_signal_connect(priv->torrentModel, "torrent-completed", G_CALLBACK(on_torrent_completed), self); @@ -1840,8 +1836,7 @@ static GObject *trg_main_window_constructor(GType type, priv->torrentTreeView = trg_main_window_torrent_tree_view_new(self, - priv->sortedTorrentModel, - priv->stateSelector); + priv->sortedTorrentModel); g_signal_connect(priv->torrentTreeView, "key-press-event", G_CALLBACK(torrent_tv_key_press_event), self); g_signal_connect(priv->torrentTreeView, "popup-menu", @@ -1920,8 +1915,7 @@ static GObject *trg_main_window_constructor(GType type, gtk_paned_pack2(GTK_PANED(priv->vpaned), priv->notebook, FALSE, FALSE); tray = - gconf_client_get_bool_or_true(priv->client->gconf, - TRG_GCONF_KEY_SYSTEM_TRAY); + trg_prefs_get_bool(prefs, TRG_PREFS_KEY_SYSTEM_TRAY, TRG_PREFS_GLOBAL); if (tray) trg_main_window_add_status_icon(self); else @@ -1934,11 +1928,11 @@ static GObject *trg_main_window_constructor(GType type, FALSE, FALSE, 2); width = - gconf_client_get_int(priv->client->gconf, - TRG_GCONF_KEY_WINDOW_WIDTH, NULL); + trg_prefs_get_int(prefs, + TRG_PREFS_KEY_WINDOW_WIDTH, TRG_PREFS_GLOBAL); height = - gconf_client_get_int(priv->client->gconf, - TRG_GCONF_KEY_WINDOW_HEIGHT, NULL); + trg_prefs_get_int(prefs, + TRG_PREFS_KEY_WINDOW_HEIGHT, TRG_PREFS_GLOBAL); if (width > 0 && height > 0) gtk_window_set_default_size(GTK_WINDOW(self), width, height); @@ -1968,22 +1962,22 @@ static void trg_main_window_class_init(TrgMainWindowClass * klass) G_PARAM_STATIC_BLURB)); } -void auto_connect_if_required(TrgMainWindow * win, trg_client * tc) +void auto_connect_if_required(TrgMainWindow * win, TrgClient * tc) { + TrgPrefs *prefs = trg_client_get_prefs(tc); gchar *host = - gconf_client_get_string(tc->gconf, TRG_GCONF_KEY_HOSTNAME, - NULL); + trg_prefs_get_string(prefs, TRG_PREFS_KEY_HOSTNAME, TRG_PREFS_PROFILE); + if (host) { gint len = strlen(host); g_free(host); if (len > 0 - && gconf_client_get_bool(tc->gconf, - TRG_GCONF_KEY_AUTO_CONNECT, NULL)) + && trg_prefs_get_bool(prefs, TRG_PREFS_KEY_AUTO_CONNECT, TRG_PREFS_PROFILE)) connect_cb(NULL, win); } } -TrgMainWindow *trg_main_window_new(trg_client * tc) +TrgMainWindow *trg_main_window_new(TrgClient * tc) { return g_object_new(TRG_TYPE_MAIN_WINDOW, "trg-client", tc, NULL); } diff --git a/src/trg-main-window.h b/src/trg-main-window.h index 4c46a34..89eb12a 100644 --- a/src/trg-main-window.h +++ b/src/trg-main-window.h @@ -61,8 +61,8 @@ gboolean trg_add_from_filename(TrgMainWindow * win, gchar ** uris); void on_session_set(JsonObject * response, int status, gpointer data); void on_generic_interactive_action(JsonObject * response, int status, gpointer data); -void auto_connect_if_required(TrgMainWindow * win, trg_client * tc); -TrgMainWindow *trg_main_window_new(trg_client * tc); +void auto_connect_if_required(TrgMainWindow * win, TrgClient * tc); +TrgMainWindow *trg_main_window_new(TrgClient * tc); void trg_main_window_add_status_icon(TrgMainWindow * win); void trg_main_window_remove_status_icon(TrgMainWindow * win); void trg_main_window_add_graph(TrgMainWindow * win, gboolean show); diff --git a/src/trg-peers-tree-view.c b/src/trg-peers-tree-view.c index f1f09a9..e85cbd2 100644 --- a/src/trg-peers-tree-view.c +++ b/src/trg-peers-tree-view.c @@ -29,6 +29,7 @@ #include <glib/gi18n.h> #include <gtk/gtk.h> +#include "trg-prefs.h" #include "trg-tree-view.h" #include "trg-peers-model.h" #include "trg-peers-tree-view.h" @@ -69,15 +70,15 @@ static void trg_peers_tree_view_init(TrgPeersTreeView * self) _("Client"), "client", 0); gtk_tree_view_set_search_column(GTK_TREE_VIEW(self), PEERSCOL_HOST); - trg_tree_view_setup_columns(ttv); } -TrgPeersTreeView *trg_peers_tree_view_new(TrgPeersModel * model) +TrgPeersTreeView *trg_peers_tree_view_new(TrgPrefs *prefs, TrgPeersModel * model) { GObject *obj = g_object_new(TRG_TYPE_PEERS_TREE_VIEW, NULL); - + trg_tree_view_set_prefs(TRG_TREE_VIEW(obj), prefs); gtk_tree_view_set_model(GTK_TREE_VIEW(obj), GTK_TREE_MODEL(model)); trg_tree_view_restore_sort(TRG_TREE_VIEW(obj)); + trg_tree_view_setup_columns(TRG_TREE_VIEW(obj)); return TRG_PEERS_TREE_VIEW(obj); } diff --git a/src/trg-peers-tree-view.h b/src/trg-peers-tree-view.h index ce1a8a0..dbd5e03 100644 --- a/src/trg-peers-tree-view.h +++ b/src/trg-peers-tree-view.h @@ -24,6 +24,7 @@ #include <glib-object.h> #include <gtk/gtk.h> +#include "trg-prefs.h" #include "trg-peers-model.h" G_BEGIN_DECLS @@ -48,7 +49,7 @@ typedef struct { GType trg_peers_tree_view_get_type(void); -TrgPeersTreeView *trg_peers_tree_view_new(TrgPeersModel * model); +TrgPeersTreeView *trg_peers_tree_view_new(TrgPrefs *prefs, TrgPeersModel * model); G_END_DECLS #endif /* TRG_PEERS_TREE_VIEW_H_ */ diff --git a/src/trg-preferences-dialog.c b/src/trg-preferences-dialog.c index 0010f71..7b421c9 100644 --- a/src/trg-preferences-dialog.c +++ b/src/trg-preferences-dialog.c @@ -24,45 +24,92 @@ #include <glib.h> #include <glib/gi18n.h> #include <glib-object.h> +#include <glib/gprintf.h> #include <gtk/gtk.h> -#include <gconf/gconf-client.h> #include "hig.h" -#include "trg-preferences-dialog.h" #include "trg-json-widgets.h" +#include "trg-preferences-dialog.h" #include "trg-main-window.h" -#include "trg-preferences.h" +#include "trg-prefs.h" #include "util.h" #define TRG_PREFERENCES_DIALOG_GET_PRIVATE(object) \ (G_TYPE_INSTANCE_GET_PRIVATE ((object), TRG_TYPE_PREFERENCES_DIALOG, TrgPreferencesDialogPrivate)) G_DEFINE_TYPE(TrgPreferencesDialog, trg_preferences_dialog, - GTK_TYPE_DIALOG) + GTK_TYPE_DIALOG) enum { - PROP_0, - PROP_TRG_CLIENT, - PROP_MAIN_WINDOW + PROP_0, PROP_TRG_CLIENT, PROP_MAIN_WINDOW }; -#define GCONF_OBJECT_KEY "gconf-key" - struct _TrgPreferencesDialogPrivate { TrgMainWindow *win; - trg_client *client; + TrgClient *client; + TrgPrefs *prefs; + GtkWidget *profileDelButton; + GtkWidget *profileComboBox; + GtkWidget *profileNameEntry; + GList *widgets; }; static GObject *instance = NULL; -static void -trg_preferences_dialog_set_property(GObject * object, - guint prop_id, - const GValue * value, - GParamSpec * pspec G_GNUC_UNUSED) -{ +static void trg_pref_widget_desc_free(trg_pref_widget_desc *wd) { + if (wd->key) + g_free(wd->key); + g_free(wd); +} + +static trg_pref_widget_desc* trg_pref_widget_desc_new(GtkWidget *w, gchar *key, + int flags) { + trg_pref_widget_desc *desc = g_new0(trg_pref_widget_desc, 1); + desc->widget = w; + desc->key = g_strdup(key); + desc->flags = flags; + return desc; +} + +static void trg_pref_widget_refresh(TrgPreferencesDialog *dlg, + trg_pref_widget_desc* wd) { + TrgPreferencesDialogPrivate *priv = TRG_PREFERENCES_DIALOG_GET_PRIVATE(dlg); + + wd->refreshFunc(priv->prefs, wd); +} + +static void trg_pref_widget_refresh_all(TrgPreferencesDialog *dlg) { + TrgPreferencesDialogPrivate *priv = TRG_PREFERENCES_DIALOG_GET_PRIVATE(dlg); + + GList *li; + for (li = priv->widgets; li; li = g_list_next(li)) + trg_pref_widget_refresh(dlg, (trg_pref_widget_desc*) li->data); +} + +static void trg_pref_widget_save(TrgPreferencesDialog *dlg, + trg_pref_widget_desc* wd) { + TrgPreferencesDialogPrivate *priv = TRG_PREFERENCES_DIALOG_GET_PRIVATE(dlg); + + wd->saveFunc(priv->prefs, wd); +} + +static void trg_pref_widget_save_all(TrgPreferencesDialog *dlg) { + TrgPreferencesDialogPrivate *priv = TRG_PREFERENCES_DIALOG_GET_PRIVATE(dlg); + + if (trg_prefs_get_profile_id(priv->prefs) < 0) + return; + + GList *li; + for (li = priv->widgets; li; li = g_list_next(li)) { + trg_pref_widget_desc* wd = (trg_pref_widget_desc*) li->data; + trg_pref_widget_save(dlg, wd); + } +} + +static void trg_preferences_dialog_set_property(GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec G_GNUC_UNUSED) { TrgPreferencesDialogPrivate *priv = - TRG_PREFERENCES_DIALOG_GET_PRIVATE(object); + TRG_PREFERENCES_DIALOG_GET_PRIVATE(object); switch (prop_id) { case PROP_MAIN_WINDOW: @@ -70,26 +117,32 @@ trg_preferences_dialog_set_property(GObject * object, break; case PROP_TRG_CLIENT: priv->client = g_value_get_pointer(value); + priv->prefs = trg_client_get_prefs(priv->client); break; } } -static void -trg_preferences_response_cb(GtkDialog * dlg, gint res_id, - gpointer data G_GNUC_UNUSED) -{ +static void trg_preferences_response_cb(GtkDialog * dlg, gint res_id, + gpointer data G_GNUC_UNUSED) { + TrgPreferencesDialogPrivate *priv = TRG_PREFERENCES_DIALOG_GET_PRIVATE(dlg); + + trg_pref_widget_save_all(TRG_PREFERENCES_DIALOG(dlg)); + + trg_prefs_save(priv->prefs); + + GList *li; + for (li = priv->widgets; li; li = g_list_next(li)) + trg_pref_widget_desc_free((trg_pref_widget_desc*) li->data); + g_list_free(priv->widgets); + gtk_widget_destroy(GTK_WIDGET(dlg)); instance = NULL; } -static void -trg_preferences_dialog_get_property(GObject * object, - guint prop_id, - GValue * value, - GParamSpec * pspec G_GNUC_UNUSED) -{ +static void trg_preferences_dialog_get_property(GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec G_GNUC_UNUSED) { TrgPreferencesDialogPrivate *priv = - TRG_PREFERENCES_DIALOG_GET_PRIVATE(object); + TRG_PREFERENCES_DIALOG_GET_PRIVATE(object); switch (prop_id) { case PROP_MAIN_WINDOW: @@ -101,205 +154,205 @@ trg_preferences_dialog_get_property(GObject * object, } } -static void update_activeonly_cb(GtkToggleButton * w, gpointer data) -{ - trg_client *client = (trg_client *) data; - client->activeOnlyUpdate = gtk_toggle_button_get_active(w); +static void update_activeonly_cb(GtkToggleButton * w, gpointer data) { + trg_client_set_activeonlyupdate(TRG_CLIENT(data), + gtk_toggle_button_get_active(w)); } -static void toggled_cb(GtkToggleButton * w, gpointer gconf) -{ - const char *key = g_object_get_data(G_OBJECT(w), GCONF_OBJECT_KEY); - gboolean flag = gtk_toggle_button_get_active(w); +static void entry_refresh(TrgPrefs *prefs, void *wdp) { + trg_pref_widget_desc *wd = (trg_pref_widget_desc*) wdp; + gchar *value = trg_prefs_get_string(prefs, wd->key, wd->flags); + if (value) { + gtk_entry_set_text(GTK_ENTRY(wd->widget), value); + g_free(value); + } else { + gtk_entry_set_text(GTK_ENTRY(wd->widget), ""); + } +} - gconf_client_set_bool(GCONF_CLIENT(gconf), key, flag, NULL); +static void entry_save(TrgPrefs *prefs, void *wdp) { + trg_pref_widget_desc *wd = (trg_pref_widget_desc*) wdp; + trg_prefs_set_string(prefs, wd->key, + gtk_entry_get_text(GTK_ENTRY(wd->widget)), wd->flags); } -static GtkWidget *new_check_button(GConfClient * gconf, - const char *mnemonic, const char *key) -{ - GtkWidget *w = gtk_check_button_new_with_mnemonic(mnemonic); +static GtkWidget *trgp_entry_new(TrgPreferencesDialog *dlg, gchar *key, + int flags) { + TrgPreferencesDialogPrivate *priv = TRG_PREFERENCES_DIALOG_GET_PRIVATE(dlg); + GtkWidget *w; - g_object_set_data_full(G_OBJECT(w), GCONF_OBJECT_KEY, - g_strdup(key), g_free); + w = gtk_entry_new(); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), - gconf_client_get_bool(gconf, key, NULL)); - g_signal_connect(w, "toggled", G_CALLBACK(toggled_cb), gconf); - return w; -} + trg_pref_widget_desc *wd = trg_pref_widget_desc_new(w, key, flags); + wd->saveFunc = &entry_save; + wd->refreshFunc = &entry_refresh; + + entry_refresh(priv->prefs, wd); + priv->widgets = g_list_append(priv->widgets, wd); -static void interval_changed_cb(GtkWidget * w, gpointer data) -{ - trg_client *client = (trg_client *) data; - client->interval = - gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(w)); + return w; } -static void spun_cb_int(GtkWidget * widget, gpointer gconf) -{ - gchar *key = g_object_get_data(G_OBJECT(widget), GCONF_OBJECT_KEY); +static void check_refresh(TrgPrefs *prefs, void *wdp) { + trg_pref_widget_desc *wd = (trg_pref_widget_desc*) wdp; + gboolean value = trg_prefs_get_bool(prefs, wd->key, wd->flags); - gconf_client_set_int(GCONF_CLIENT(gconf), - key, - gtk_spin_button_get_value_as_int - (GTK_SPIN_BUTTON(widget)), NULL); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(wd->widget), value); } -static GtkWidget *new_spin_button(GConfClient * gconf, - const gchar * key, - int low, int high, int step, int deflt) -{ - GtkWidget *w; - gint currentValue; +static void check_save(TrgPrefs *prefs, void *wdp) { + trg_pref_widget_desc *wd = (trg_pref_widget_desc*) wdp; + trg_prefs_set_bool(prefs, wd->key, + gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wd->widget)), + wd->flags); +} - w = gtk_spin_button_new_with_range(low, high, step); - g_object_set_data_full(G_OBJECT(w), GCONF_OBJECT_KEY, - g_strdup(key), g_free); +static GtkWidget *trgp_check_new(TrgPreferencesDialog *dlg, + const char *mnemonic, gchar *key, int flags) { + TrgPreferencesDialogPrivate *priv = TRG_PREFERENCES_DIALOG_GET_PRIVATE(dlg); - gtk_spin_button_set_digits(GTK_SPIN_BUTTON(w), 0); - - currentValue = - gconf_client_get_int_or_default(gconf, key, deflt, NULL); + GtkWidget *w = gtk_check_button_new_with_mnemonic(mnemonic); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(w), currentValue); + trg_pref_widget_desc *wd = trg_pref_widget_desc_new(w, key, flags); + wd->saveFunc = &check_save; + wd->refreshFunc = &check_refresh; + check_refresh(priv->prefs, wd); - g_signal_connect(w, "value-changed", G_CALLBACK(spun_cb_int), gconf); + priv->widgets = g_list_append(priv->widgets, wd); return w; } -static void entry_changed_cb(GtkEntry * w, gpointer gconf) -{ - const char *key, *value; +static void spin_refresh(TrgPrefs *prefs, void *wdp) { + trg_pref_widget_desc *wd = (trg_pref_widget_desc*) wdp; + GtkWidget *widget = wd->widget; - key = g_object_get_data(G_OBJECT(w), GCONF_OBJECT_KEY); - value = gtk_entry_get_text(w); + gint value = trg_prefs_get_int(prefs, wd->key, wd->flags); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), value); +} - gconf_client_set_string(GCONF_CLIENT(gconf), key, value, NULL); +static void spin_save(TrgPrefs * prefs, void* wdp) { + trg_pref_widget_desc *wd = (trg_pref_widget_desc*) wdp; + trg_prefs_set_int(prefs, wd->key, + gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(wd->widget)), + wd->flags); } -static GtkWidget *new_entry(GConfClient * gconf, const char *key) -{ +static GtkWidget *trgp_spin_new(TrgPreferencesDialog *dlg, gchar * key, + int low, int high, int step, int flags) { + TrgPreferencesDialogPrivate *priv = TRG_PREFERENCES_DIALOG_GET_PRIVATE(dlg); GtkWidget *w; - const char *value; - w = gtk_entry_new(); - value = gconf_client_get_string(gconf, key, NULL); + w = gtk_spin_button_new_with_range(low, high, step); - if (value != NULL) { - gtk_entry_set_text(GTK_ENTRY(w), value); - g_free((gpointer) value); - } + gtk_spin_button_set_digits(GTK_SPIN_BUTTON(w), 0); - g_object_set_data_full(G_OBJECT(w), GCONF_OBJECT_KEY, - g_strdup(key), g_free); + trg_pref_widget_desc *wd = trg_pref_widget_desc_new(w, key, flags); + wd->saveFunc = &spin_save; + wd->refreshFunc = &spin_refresh; + + spin_refresh(priv->prefs, wd); + priv->widgets = g_list_append(priv->widgets, wd); - g_signal_connect(w, "changed", G_CALLBACK(entry_changed_cb), gconf); return w; } -static void toggle_filter_trackers(GtkToggleButton * w, gpointer win) -{ - TrgStateSelector *selector = - trg_main_window_get_state_selector(TRG_MAIN_WINDOW(win)); +static void interval_changed_cb(GtkWidget * w, gpointer data) { + trg_client_set_interval(TRG_CLIENT(data), + gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(w))); +} + +static void toggle_filter_trackers(GtkToggleButton * w, gpointer win) { + TrgStateSelector *selector = trg_main_window_get_state_selector( + TRG_MAIN_WINDOW(win)); trg_state_selector_set_show_trackers(selector, - gtk_toggle_button_get_active(w)); + gtk_toggle_button_get_active(w)); } -static void toggle_filter_dirs(GtkToggleButton * w, gpointer win) -{ - TrgStateSelector *selector = - trg_main_window_get_state_selector(TRG_MAIN_WINDOW(win)); - trg_state_selector_set_show_dirs(selector, - gtk_toggle_button_get_active(w)); +static void toggle_filter_dirs(GtkToggleButton * w, gpointer win) { + TrgStateSelector *selector = trg_main_window_get_state_selector( + TRG_MAIN_WINDOW(win)); + trg_state_selector_set_show_dirs(selector, gtk_toggle_button_get_active(w)); } -static void toggle_graph(GtkToggleButton * w, gpointer win) -{ +static void toggle_graph(GtkToggleButton * w, gpointer win) { if (gtk_toggle_button_get_active(w)) trg_main_window_add_graph(TRG_MAIN_WINDOW(win), TRUE); else trg_main_window_remove_graph(TRG_MAIN_WINDOW(win)); } -static void toggle_tray_icon(GtkToggleButton * w, gpointer win) -{ +static void toggle_tray_icon(GtkToggleButton * w, gpointer win) { if (gtk_toggle_button_get_active(w)) trg_main_window_add_status_icon(TRG_MAIN_WINDOW(win)); else trg_main_window_remove_status_icon(TRG_MAIN_WINDOW(win)); } -static GtkWidget *trg_prefs_desktopPage(trg_client * client, - TrgMainWindow * win) -{ +static GtkWidget *trg_prefs_desktopPage(TrgPreferencesDialog *dlg) { + TrgPreferencesDialogPrivate *priv = TRG_PREFERENCES_DIALOG_GET_PRIVATE(dlg); + GtkWidget *tray, *w, *t; gint row = 0; - GConfClient *gconf = client->gconf; - t = hig_workarea_create(); hig_workarea_add_section_title(t, &row, _("Features")); - w = new_check_button(gconf, _("Directory filters"), - TRG_GCONF_KEY_FILTER_DIRS); + w = trgp_check_new(dlg, _("Directory filters"), TRG_PREFS_KEY_FILTER_DIRS, + TRG_PREFS_GLOBAL); g_signal_connect(G_OBJECT(w), "toggled", - G_CALLBACK(toggle_filter_dirs), win); + G_CALLBACK(toggle_filter_dirs), priv->win); hig_workarea_add_wide_control(t, &row, w); - w = new_check_button(gconf, _("Tracker filters"), - TRG_GCONF_KEY_FILTER_TRACKERS); + w = trgp_check_new(dlg, _("Tracker filters"), + TRG_PREFS_KEY_FILTER_TRACKERS, TRG_PREFS_GLOBAL); g_signal_connect(G_OBJECT(w), "toggled", - G_CALLBACK(toggle_filter_trackers), win); + G_CALLBACK(toggle_filter_trackers), priv->win); hig_workarea_add_wide_control(t, &row, w); - w = new_check_button(gconf, _("Show graph"), TRG_GCONF_KEY_SHOW_GRAPH); + w = trgp_check_new(dlg, _("Show graph"), TRG_PREFS_KEY_SHOW_GRAPH, + TRG_PREFS_GLOBAL); g_signal_connect(G_OBJECT(w), "toggled", - G_CALLBACK(toggle_graph), win); + G_CALLBACK(toggle_graph), priv->win); hig_workarea_add_wide_control(t, &row, w); hig_workarea_add_section_title(t, &row, _("System Tray")); - tray = new_check_button(gconf, _("Show in system tray"), - TRG_GCONF_KEY_SYSTEM_TRAY); + tray = trgp_check_new(dlg, _("Show in system tray"), + TRG_PREFS_KEY_SYSTEM_TRAY, TRG_PREFS_GLOBAL); g_signal_connect(G_OBJECT(tray), "toggled", - G_CALLBACK(toggle_tray_icon), win); + G_CALLBACK(toggle_tray_icon), priv->win); hig_workarea_add_wide_control(t, &row, tray); - w = new_check_button(gconf, _("Minimise to system tray"), - TRG_GCONF_KEY_SYSTEM_TRAY_MINIMISE); - gtk_widget_set_sensitive(w, - gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON - (tray))); + w = trgp_check_new(dlg, _("Minimise to system tray"), + TRG_PREFS_KEY_SYSTEM_TRAY_MINIMISE, TRG_PREFS_GLOBAL); + gtk_widget_set_sensitive(w, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON + (tray))); g_signal_connect(G_OBJECT(tray), "toggled", - G_CALLBACK(toggle_active_arg_is_sensitive), w); + G_CALLBACK(toggle_active_arg_is_sensitive), w); hig_workarea_add_wide_control(t, &row, w); - w = new_check_button(gconf, _("Torrent added notifications"), - TRG_GCONF_KEY_ADD_NOTIFY); - gtk_widget_set_sensitive(w, - gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON - (tray))); + w = trgp_check_new(dlg, _("Torrent added notifications"), + TRG_PREFS_KEY_ADD_NOTIFY, TRG_PREFS_GLOBAL); + gtk_widget_set_sensitive(w, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON + (tray))); g_signal_connect(G_OBJECT(tray), "toggled", - G_CALLBACK(toggle_active_arg_is_sensitive), w); + G_CALLBACK(toggle_active_arg_is_sensitive), w); hig_workarea_add_wide_control(t, &row, w); - w = new_check_button(gconf, _("Torrent complete notifications"), - TRG_GCONF_KEY_COMPLETE_NOTIFY); - gtk_widget_set_sensitive(w, - gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON - (tray))); + w = trgp_check_new(dlg, _("Torrent complete notifications"), + TRG_PREFS_KEY_COMPLETE_NOTIFY, TRG_PREFS_GLOBAL); + gtk_widget_set_sensitive(w, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON + (tray))); g_signal_connect(G_OBJECT(tray), "toggled", - G_CALLBACK(toggle_active_arg_is_sensitive), w); + G_CALLBACK(toggle_active_arg_is_sensitive), w); hig_workarea_add_wide_control(t, &row, w); return t; } -static GtkWidget *trg_prefs_behaviorPage(trg_client * client) -{ +static GtkWidget *trg_prefs_behaviorPage(TrgPreferencesDialog * dlg) { GtkWidget *w, *t; gint row = 0; @@ -307,171 +360,316 @@ static GtkWidget *trg_prefs_behaviorPage(trg_client * client) hig_workarea_add_section_title(t, &row, _("Torrents")); - w = new_check_button(client->gconf, _("Start paused"), - TRG_GCONF_KEY_START_PAUSED); + w = trgp_check_new(dlg, _("Start paused"), TRG_PREFS_KEY_START_PAUSED, + TRG_PREFS_GLOBAL); hig_workarea_add_wide_control(t, &row, w); - w = new_check_button(client->gconf, _("Options dialog on add"), - TRG_GCONF_KEY_ADD_OPTIONS_DIALOG); + w = trgp_check_new(dlg, _("Options dialog on add"), + TRG_PREFS_KEY_ADD_OPTIONS_DIALOG, TRG_PREFS_GLOBAL); hig_workarea_add_wide_control(t, &row, w); return t; } -static GtkWidget *trg_prefs_serverPage(trg_client * client) -{ - GtkWidget *w, *t; - gint row = 0; +static void profile_changed_cb(GtkWidget *w, gpointer data) { + GtkTreeModel *model = gtk_combo_box_get_model(GTK_COMBO_BOX(w)); + TrgPreferencesDialogPrivate *priv = + TRG_PREFERENCES_DIALOG_GET_PRIVATE(data); + + GtkTreeIter iter; + gint profile_id; + + trg_pref_widget_save_all(TRG_PREFERENCES_DIALOG(data)); + + gint n_children = gtk_tree_model_iter_n_children(model, NULL); + if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(w), &iter)) { + gtk_tree_model_get(model, &iter, 0, &profile_id, -1); + trg_prefs_set_profile(priv->prefs, profile_id); + trg_pref_widget_refresh_all(TRG_PREFERENCES_DIALOG(data)); + gtk_widget_set_sensitive(priv->profileDelButton, n_children > 1); + } else { + gtk_widget_set_sensitive(priv->profileDelButton, FALSE); + gtk_combo_box_set_active(GTK_COMBO_BOX(w), 0); + } +} + +static void trg_prefs_profile_combo_populate(TrgPreferencesDialog *dialog, + GtkComboBox *combo, TrgPrefs *prefs) { + TrgPreferencesDialogPrivate *priv = + TRG_PREFERENCES_DIALOG_GET_PRIVATE(dialog); + + gint profile_id = trg_prefs_get_int(prefs, TRG_PREFS_KEY_PROFILE_ID, + TRG_PREFS_GLOBAL); + GtkListStore *store = GTK_LIST_STORE(gtk_combo_box_get_model(combo)); + GList *profiles = json_array_get_elements(trg_prefs_get_profiles(prefs)); + GList *li; + + int i = 0; + for (li = profiles; li; li = g_list_next(li)) { + JsonObject *profile = json_node_get_object((JsonNode*) li->data); + const gchar *name_value; + if (json_object_has_member(profile, TRG_PREFS_KEY_PROFILE_NAME)) { + name_value = json_object_get_string_member(profile, + TRG_PREFS_KEY_PROFILE_NAME); + } else { + name_value = _(TRG_PROFILE_NAME_DEFAULT); + } + GtkTreeIter iter; + gtk_list_store_insert_with_values(store, &iter, INT_MAX, 0, i, 1, + name_value, -1); + if (i++ == profile_id) + gtk_combo_box_set_active_iter(combo, &iter); + } + + gtk_widget_set_sensitive(priv->profileDelButton, g_list_length(profiles) > 1); + + +} + +static GtkWidget *trg_prefs_profile_combo_new(TrgClient *tc) { + GtkWidget *w; + GtkCellRenderer *r; + GtkListStore *store = gtk_list_store_new(2, G_TYPE_INT, G_TYPE_STRING); + + w = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store)); + r = gtk_cell_renderer_text_new(); + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT (w), r, FALSE); + gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(w), r, "text", 1); + + return w; +} - GConfClient *gconf = client->gconf; +static void name_changed_cb(GtkWidget *w, gpointer data) { + TrgPreferencesDialogPrivate *priv = + TRG_PREFERENCES_DIALOG_GET_PRIVATE(data); + GtkTreeIter iter; + GtkTreeModel *model; + GtkComboBox *combo; + + combo = GTK_COMBO_BOX(priv->profileComboBox); + model = gtk_combo_box_get_model(combo); + + if (gtk_combo_box_get_active_iter(combo, &iter)) { + gtk_list_store_set(GTK_LIST_STORE(model), &iter, 1, + gtk_entry_get_text(GTK_ENTRY(w)), -1); + } +} + +static void del_profile_cb(GtkWidget *w, gpointer data) { + GtkWidget *win = gtk_widget_get_toplevel(w); + TrgPreferencesDialogPrivate *priv = TRG_PREFERENCES_DIALOG_GET_PRIVATE(win); + TrgPrefs *prefs = priv->prefs; + GtkComboBox *combo = GTK_COMBO_BOX(data); + GtkTreeModel *profileModel = gtk_combo_box_get_model(combo); + GtkTreeIter iter; + gint profile_id; + + if (gtk_combo_box_get_active_iter(combo, &iter)) { + gtk_tree_model_get(profileModel, &iter, 0, &profile_id, -1); + trg_prefs_del_profile(prefs, (guint)profile_id); + trg_prefs_set_profile(prefs, -1); + gtk_list_store_remove(GTK_LIST_STORE(profileModel), &iter); + gtk_combo_box_set_active(combo, 0); + } +} + +static void add_profile_cb(GtkWidget *w, gpointer data) { + GtkWidget *win = gtk_widget_get_toplevel(w); + TrgPreferencesDialogPrivate *priv = TRG_PREFERENCES_DIALOG_GET_PRIVATE(win); + GtkComboBox *combo = GTK_COMBO_BOX(data); + GtkTreeModel *profileModel = gtk_combo_box_get_model(combo); + GtkTreeIter iter; + + gint new_id = trg_prefs_new_profile(priv->prefs); + gtk_list_store_insert_with_values(GTK_LIST_STORE(profileModel), &iter, + INT_MAX, 0, new_id, 1, _(TRG_PROFILE_NAME_DEFAULT), -1); + gtk_combo_box_set_active_iter(combo, &iter); +} + +static GtkWidget *trg_prefs_serverPage(TrgPreferencesDialog *dlg) { + TrgPreferencesDialogPrivate *priv = TRG_PREFERENCES_DIALOG_GET_PRIVATE(dlg); + TrgClient *tc = priv->client; + TrgPrefs *prefs = priv->prefs; + + GtkWidget *w, *t, *frame, *frameHbox, *profileLabel; + GtkWidget *profileButtonsHbox; + gint row = 0; t = hig_workarea_create(); + /* Profile */ + + hig_workarea_add_section_title(t, &row, _("Profile")); + + priv->profileNameEntry = trgp_entry_new(dlg, TRG_PREFS_KEY_PROFILE_NAME, + TRG_PREFS_PROFILE); + + w = priv->profileComboBox = trg_prefs_profile_combo_new(priv->client); + profileLabel = gtk_label_new(_("Profile: ")); + + profileButtonsHbox = gtk_hbox_new(FALSE, 0); + w = gtk_button_new_from_stock(GTK_STOCK_ADD); + g_signal_connect(w, "clicked", G_CALLBACK(add_profile_cb), priv->profileComboBox); + gtk_box_pack_start(GTK_BOX(profileButtonsHbox), w, FALSE, FALSE, 4); + + w = priv->profileDelButton = gtk_button_new_from_stock(GTK_STOCK_DELETE); + g_signal_connect(w, "clicked", G_CALLBACK(del_profile_cb), priv->profileComboBox); + gtk_widget_set_sensitive(w, FALSE); + gtk_box_pack_start(GTK_BOX(profileButtonsHbox), w, FALSE, FALSE, 4); + + trg_prefs_profile_combo_populate(dlg, GTK_COMBO_BOX(priv->profileComboBox), + prefs); + g_signal_connect(G_OBJECT(priv->profileComboBox), "changed", G_CALLBACK(profile_changed_cb), dlg); + + /* Name */ + + g_signal_connect(priv->profileNameEntry, "changed", G_CALLBACK(name_changed_cb), dlg); + + hig_workarea_add_row(t, &row, _("Name:"), priv->profileNameEntry, NULL); + + gtk_table_attach(GTK_TABLE(t), profileButtonsHbox, 1, 2, row, row + 1, + GTK_EXPAND | GTK_SHRINK, 0, 0, 0); + + row++; + hig_workarea_add_section_title(t, &row, _("Server")); - w = new_entry(gconf, TRG_GCONF_KEY_HOSTNAME); + w = trgp_entry_new(dlg, TRG_PREFS_KEY_HOSTNAME, TRG_PREFS_PROFILE); hig_workarea_add_row(t, &row, _("Host:"), w, NULL); - w = new_spin_button(gconf, TRG_GCONF_KEY_PORT, 1, 65535, 1, - TRG_PORT_DEFAULT); + w = trgp_spin_new(dlg, TRG_PREFS_KEY_PORT, 1, 65535, 1, TRG_PREFS_PROFILE); hig_workarea_add_row(t, &row, _("Port:"), w, NULL); - w = new_check_button(gconf, _("Automatically connect"), - TRG_GCONF_KEY_AUTO_CONNECT); - hig_workarea_add_wide_control(t, &row, w); + w = trgp_entry_new(dlg, TRG_PREFS_KEY_USERNAME, TRG_PREFS_PROFILE); + hig_workarea_add_row(t, &row, _("Username:"), w, NULL); - w = new_check_button(gconf, _("SSL"), TRG_GCONF_KEY_SSL); - hig_workarea_add_wide_control(t, &row, w); + w = trgp_entry_new(dlg, TRG_PREFS_KEY_PASSWORD, TRG_PREFS_PROFILE); + gtk_entry_set_visibility(GTK_ENTRY(w), FALSE); + hig_workarea_add_row(t, &row, _("Password:"), w, NULL); - w = new_spin_button(gconf, TRG_GCONF_KEY_UPDATE_INTERVAL, 1, 60, 1, - TRG_INTERVAL_DEFAULT); + w = trgp_spin_new(dlg, TRG_PREFS_KEY_UPDATE_INTERVAL, 1, 60, 1, + TRG_PREFS_PROFILE); g_signal_connect(w, "value-changed", G_CALLBACK(interval_changed_cb), - client); + tc); hig_workarea_add_row(t, &row, _("Update interval:"), w, NULL); - w = new_check_button(gconf, _("Update active torrents only"), - TRG_GCONF_KEY_UPDATE_ACTIVE_ONLY); + w = trgp_check_new(dlg, _("Automatically connect"), + TRG_PREFS_KEY_AUTO_CONNECT, TRG_PREFS_PROFILE); + hig_workarea_add_wide_control(t, &row, w); + + w = trgp_check_new(dlg, _("SSL"), TRG_PREFS_KEY_SSL, TRG_PREFS_PROFILE); + hig_workarea_add_wide_control(t, &row, w); + + w = trgp_check_new(dlg, _("Update active torrents only"), + TRG_PREFS_KEY_UPDATE_ACTIVE_ONLY, TRG_PREFS_PROFILE); g_signal_connect(w, "toggled", G_CALLBACK(update_activeonly_cb), - client); + tc); hig_workarea_add_wide_control(t, &row, w); hig_workarea_add_section_divider(t, &row); - hig_workarea_add_section_title(t, &row, _("Authentication")); - - w = new_entry(gconf, TRG_GCONF_KEY_USERNAME); - hig_workarea_add_row(t, &row, _("Username:"), w, NULL); - w = new_entry(gconf, TRG_GCONF_KEY_PASSWORD); - gtk_entry_set_visibility(GTK_ENTRY(w), FALSE); - hig_workarea_add_row(t, &row, _("Password:"), w, NULL); + frame = gtk_frame_new(NULL); + frameHbox = gtk_hbox_new(FALSE, 2); + gtk_box_pack_start(GTK_BOX(frameHbox), profileLabel, FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(frameHbox), priv->profileComboBox, FALSE, FALSE, + 4); + gtk_frame_set_label_widget(GTK_FRAME(frame), frameHbox); + gtk_container_add(GTK_CONTAINER(frame), t); - return t; + return frame; } static GObject *trg_preferences_dialog_constructor(GType type, - guint - n_construct_properties, - GObjectConstructParam * - construct_params) -{ + guint n_construct_properties, GObjectConstructParam * construct_params) { GObject *object; TrgPreferencesDialogPrivate *priv; GtkWidget *notebook; - object = - G_OBJECT_CLASS - (trg_preferences_dialog_parent_class)->constructor(type, - n_construct_properties, - construct_params); + object = G_OBJECT_CLASS + (trg_preferences_dialog_parent_class)->constructor(type, + n_construct_properties, construct_params); priv = TRG_PREFERENCES_DIALOG_GET_PRIVATE(object); - gtk_window_set_transient_for(GTK_WINDOW(object), - GTK_WINDOW(priv->win)); + gtk_window_set_transient_for(GTK_WINDOW(object), GTK_WINDOW(priv->win)); gtk_window_set_destroy_with_parent(GTK_WINDOW(object), TRUE); - gtk_dialog_add_button(GTK_DIALOG(object), GTK_STOCK_CLOSE, - GTK_RESPONSE_CLOSE); + gtk_dialog_add_button(GTK_DIALOG(object), GTK_STOCK_APPLY, + GTK_RESPONSE_APPLY); - gtk_dialog_set_default_response(GTK_DIALOG(object), - GTK_RESPONSE_CLOSE); + gtk_dialog_set_default_response(GTK_DIALOG(object), GTK_RESPONSE_CLOSE); gtk_window_set_title(GTK_WINDOW(object), _("Local Preferences")); gtk_container_set_border_width(GTK_CONTAINER(object), GUI_PAD); g_signal_connect(G_OBJECT(object), - "response", - G_CALLBACK(trg_preferences_response_cb), NULL); + "response", + G_CALLBACK(trg_preferences_response_cb), NULL); notebook = gtk_notebook_new(); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), - trg_prefs_serverPage(priv->client), - gtk_label_new(_("Connection"))); + trg_prefs_serverPage(TRG_PREFERENCES_DIALOG(object)), + gtk_label_new(_("Connection"))); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), - trg_prefs_desktopPage(priv->client, - priv->win), - gtk_label_new(_("Desktop"))); + trg_prefs_desktopPage(TRG_PREFERENCES_DIALOG(object)), + gtk_label_new(_("Desktop"))); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), - trg_prefs_behaviorPage(priv->client), - gtk_label_new(_("Behavior"))); + trg_prefs_behaviorPage(TRG_PREFERENCES_DIALOG(object)), + gtk_label_new(_("Behavior"))); gtk_container_set_border_width(GTK_CONTAINER(notebook), GUI_PAD); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(object)->vbox), notebook, - TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(object)->vbox), notebook, TRUE, TRUE, + 0); gtk_widget_show_all(GTK_DIALOG(object)->vbox); return object; } -static void trg_preferences_dialog_init(TrgPreferencesDialog * pref_dlg) -{ +static void trg_preferences_dialog_init(TrgPreferencesDialog * pref_dlg) { } -static void -trg_preferences_dialog_class_init(TrgPreferencesDialogClass * class) -{ +static void trg_preferences_dialog_class_init(TrgPreferencesDialogClass * class) { GObjectClass *g_object_class = (GObjectClass *) class; g_object_class->constructor = trg_preferences_dialog_constructor; g_object_class->set_property = trg_preferences_dialog_set_property; g_object_class->get_property = trg_preferences_dialog_get_property; - g_object_class_install_property(g_object_class, - PROP_TRG_CLIENT, - g_param_spec_pointer - ("trg-client", "TClient", - "Client", - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB)); - - g_object_class_install_property(g_object_class, - PROP_MAIN_WINDOW, - g_param_spec_object - ("main-window", "Main Window", - "Main Window", TRG_TYPE_MAIN_WINDOW, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB)); + g_object_class_install_property( + g_object_class, + PROP_TRG_CLIENT, + g_param_spec_pointer( + "trg-client", + "TClient", + "Client", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY + | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK + | G_PARAM_STATIC_BLURB)); + + g_object_class_install_property( + g_object_class, + PROP_MAIN_WINDOW, + g_param_spec_object( + "main-window", + "Main Window", + "Main Window", + TRG_TYPE_MAIN_WINDOW, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY + | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK + | G_PARAM_STATIC_BLURB)); g_type_class_add_private(g_object_class, - sizeof(TrgPreferencesDialogPrivate)); + sizeof(TrgPreferencesDialogPrivate)); } GtkWidget *trg_preferences_dialog_get_instance(TrgMainWindow * win, - trg_client * client) -{ + TrgClient * client) { if (instance == NULL) { - instance = g_object_new(TRG_TYPE_PREFERENCES_DIALOG, - "main-window", win, - "trg-client", client, NULL); + instance = g_object_new(TRG_TYPE_PREFERENCES_DIALOG, "main-window", + win, "trg-client", client, NULL); } return GTK_WIDGET(instance); diff --git a/src/trg-preferences-dialog.h b/src/trg-preferences-dialog.h index d99f911..8b90284 100644 --- a/src/trg-preferences-dialog.h +++ b/src/trg-preferences-dialog.h @@ -23,7 +23,6 @@ #include <glib.h> #include <glib-object.h> #include <gtk/gtk.h> -#include <gconf/gconf-client.h> #include "trg-main-window.h" @@ -38,6 +37,14 @@ typedef struct _TrgPreferencesDialogPrivate TrgPreferencesDialogPrivate; #define TRG_IS_PREFERENCES_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), TRG_TYPE_PREFERENCES_DIALOG)) #define TRG_PREFERENCES_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), TRG_TYPE_PREFERENCES_DIALOG, TrgPreferencesDialogClass)) +typedef struct { + GtkWidget *widget; + int flags; + gchar *key; + void (*saveFunc)(TrgPrefs*,void*); + void (*refreshFunc)(TrgPrefs*,void*); +} trg_pref_widget_desc; + struct _TrgPreferencesDialog { GtkDialog dialog; TrgPreferencesDialogPrivate *priv; @@ -50,6 +57,6 @@ struct _TrgPreferencesDialogClass { GType trg_preferences_dialog_get_type(void); GtkWidget *trg_preferences_dialog_get_instance(TrgMainWindow * win, - trg_client * client); + TrgClient * client); G_END_DECLS #endif /* TRG_PREFERENCES_WINDOW_H_ */ diff --git a/src/trg-preferences.c b/src/trg-preferences.c deleted file mode 100644 index 8c7fafe..0000000 --- a/src/trg-preferences.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - * transmission-remote-gtk - Transmission RPC client for GTK - * Copyright (C) 2011 Alan Fitton - - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include <glib.h> -#include <gconf/gconf-client.h> - -#include "util.h" -#include "trg-preferences.h" - -gboolean pref_get_add_options_dialog(GConfClient * gcc) -{ - return gconf_client_get_bool_or_true(gcc, - TRG_GCONF_KEY_ADD_OPTIONS_DIALOG); -} - -gboolean pref_get_start_paused(GConfClient * gcc) -{ - return gconf_client_get_bool(gcc, TRG_GCONF_KEY_START_PAUSED, NULL); -} diff --git a/src/trg-preferences.h b/src/trg-preferences.h deleted file mode 100644 index bd37195..0000000 --- a/src/trg-preferences.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * transmission-remote-gtk - A GTK RPC client to Transmission - * Copyright (C) 2011 Alan Fitton - - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef TRG_PREFERENCES_H_ -#define TRG_PREFERENCES_H_ - -#define TRG_PORT_DEFAULT 9091 -#define TRG_INTERVAL_DEFAULT 3 -#define TRG_GCONF_KEY_HOSTNAME "/apps/transmission-remote-gtk/hostname" -#define TRG_GCONF_KEY_PORT "/apps/transmission-remote-gtk/port" -#define TRG_GCONF_KEY_USERNAME "/apps/transmission-remote-gtk/username" -#define TRG_GCONF_KEY_PASSWORD "/apps/transmission-remote-gtk/password" -#define TRG_GCONF_KEY_AUTO_CONNECT "/apps/transmission-remote-gtk/auto-connect" -#define TRG_GCONF_KEY_SSL "/apps/transmission-remote-gtk/ssl" -#define TRG_GCONF_KEY_UPDATE_INTERVAL "/apps/transmission-remote-gtk/update-interval" -#define TRG_GCONF_KEY_COMPLETE_NOTIFY "/apps/transmission-remote-gtk/complete-notify" -#define TRG_GCONF_KEY_ADD_NOTIFY "/apps/transmission-remote-gtk/add-notify" -#define TRG_GCONF_KEY_WINDOW_WIDTH "/apps/transmission-remote-gtk/window-width" -#define TRG_GCONF_KEY_WINDOW_HEIGHT "/apps/transmission-remote-gtk/window-height" -#define TRG_GCONF_KEY_GRAPH_SPAN "/apps/transmission-remote-gtk/graph-span" -#define TRG_GCONF_KEY_SYSTEM_TRAY "/apps/transmission-remote-gtk/system-tray" -#define TRG_GCONF_KEY_SHOW_GRAPH "/apps/transmission-remote-gtk/show-graph" -#define TRG_GCONF_KEY_SYSTEM_TRAY_MINIMISE "/apps/transmission-remote-gtk/system-tray-minimise" -#define TRG_GCONF_KEY_FILTER_TRACKERS "/apps/transmission-remote-gtk/filter-trackers" -#define TRG_GCONF_KEY_FILTER_DIRS "/apps/transmission-remote-gtk/filter-dirs" -#define TRG_GCONF_KEY_LAST_TORRENT_DIR "/apps/transmission-remote-gtk/last-torrent-dir" -#define TRG_GCONF_KEY_ADD_OPTIONS_DIALOG "/apps/transmission-remote-gtk/add-options-dialog" -#define TRG_GCONF_KEY_START_PAUSED "/apps/transmission-remote-gtk/start-paused" -#define TRG_GCONF_KEY_UPDATE_ACTIVE_ONLY "/apps/transmission-remote-gtk/update-active-only" - -gboolean pref_get_start_paused(GConfClient * gcc); -gboolean pref_get_add_options_dialog(GConfClient * gcc); - -#endif /* TRG_PREFERENCES_H_ */ diff --git a/src/trg-prefs.c b/src/trg-prefs.c new file mode 100644 index 0000000..5ef7ff9 --- /dev/null +++ b/src/trg-prefs.c @@ -0,0 +1,355 @@ +/* + * transmission-remote-gtk - Transmission RPC client for GTK + * Copyright (C) 2011 Alan Fitton + + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <glib.h> +#include <stdio.h> +#include <json-glib/json-glib.h> +#include <glib/gi18n.h> +#include <glib/gprintf.h> + +#include "util.h" +#include "trg-client.h" +#include "trg-prefs.h" + +G_DEFINE_TYPE (TrgPrefs, trg_prefs, G_TYPE_OBJECT) + +#define GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRG_TYPE_PREFS, TrgPrefsPrivate)) + +typedef struct _TrgPrefsPrivate TrgPrefsPrivate; + +struct _TrgPrefsPrivate { + JsonObject *defaultsObj; + JsonNode *user; + JsonObject *userObj; + gchar *file; +}; + +static void trg_prefs_get_property(GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) { + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void trg_prefs_set_property(GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) { + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void trg_prefs_dispose(GObject *object) { + G_OBJECT_CLASS (trg_prefs_parent_class)->dispose(object); +} + +static void trg_prefs_create_defaults(TrgPrefs *p) { + TrgPrefsPrivate *priv = GET_PRIVATE(p); + priv->defaultsObj = json_object_new(); + + trg_prefs_add_default_string(p, TRG_PREFS_KEY_PROFILE_NAME, + _(TRG_PROFILE_NAME_DEFAULT)); + trg_prefs_add_default_int(p, TRG_PREFS_KEY_PORT, 9091); + trg_prefs_add_default_int(p, TRG_PREFS_KEY_UPDATE_INTERVAL, 3); + + trg_prefs_add_default_bool(p, TRG_PREFS_KEY_FILTER_DIRS, TRUE); + trg_prefs_add_default_bool(p, TRG_PREFS_KEY_FILTER_TRACKERS, TRUE); + trg_prefs_add_default_bool(p, TRG_PREFS_KEY_AUTO_CONNECT, FALSE); + trg_prefs_add_default_bool(p, TRG_PREFS_KEY_SHOW_GRAPH, TRUE); + trg_prefs_add_default_bool(p, TRG_PREFS_KEY_SHOW_GRAPH, TRUE); + trg_prefs_add_default_bool(p, TRG_PREFS_KEY_ADD_OPTIONS_DIALOG, TRUE); +} + +static GObject *trg_prefs_constructor(GType type, guint n_construct_properties, + GObjectConstructParam * construct_params) { + GObject *object; + TrgPrefsPrivate *priv; + + object = G_OBJECT_CLASS + (trg_prefs_parent_class)->constructor(type, n_construct_properties, + construct_params); + priv = GET_PRIVATE(object); + + trg_prefs_create_defaults(TRG_PREFS(object)); + + priv->file = g_build_filename (g_get_user_config_dir (), + g_get_application_name (), + TRG_PREFS_FILENAME, NULL); + + return object; +} + +static void trg_prefs_class_init(TrgPrefsClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private(klass, sizeof(TrgPrefsPrivate)); + + object_class->get_property = trg_prefs_get_property; + object_class->set_property = trg_prefs_set_property; + object_class->dispose = trg_prefs_dispose; + object_class->constructor = trg_prefs_constructor; +} + +static void trg_prefs_init(TrgPrefs *self) { +} + +TrgPrefs* +trg_prefs_new(void) { + return g_object_new(TRG_TYPE_PREFS, NULL); +} + +static JsonObject *trg_prefs_new_profile_object() { + JsonObject *obj = json_object_new(); + return obj; +} + +void trg_prefs_add_default_int(TrgPrefs *p, gchar *key, int value) { + TrgPrefsPrivate *priv = GET_PRIVATE(p); + json_object_set_int_member(priv->defaultsObj, key, value); +} + +void trg_prefs_add_default_string(TrgPrefs *p, gchar *key, gchar *value) { + TrgPrefsPrivate *priv = GET_PRIVATE(p); + json_object_set_string_member(priv->defaultsObj, key, value); +} + +void trg_prefs_add_default_double(TrgPrefs *p, gchar *key, double value) { + TrgPrefsPrivate *priv = GET_PRIVATE(p); + json_object_set_double_member(priv->defaultsObj, key, value); +} + +void trg_prefs_add_default_bool(TrgPrefs *p, gchar *key, gboolean value) { + TrgPrefsPrivate *priv = GET_PRIVATE(p); + json_object_set_boolean_member(priv->defaultsObj, key, value); +} + +gint trg_prefs_get_profile_id(TrgPrefs *p) { + TrgPrefsPrivate *priv = GET_PRIVATE(p); + return (gint)json_object_get_int_member(priv->userObj, TRG_PREFS_KEY_PROFILE_ID); +} + +JsonObject *trg_prefs_get_current_profile(TrgPrefs *p) { + JsonArray *profiles = trg_prefs_get_profiles(p); + return json_array_get_object_element(profiles, trg_prefs_get_profile_id(p)); +} + +JsonNode *trg_prefs_get_value(TrgPrefs *p, gchar *key, int flags) { + TrgPrefsPrivate *priv = GET_PRIVATE(p); + + if ((flags & TRG_PREFS_PROFILE)) { + JsonObject *profile = trg_prefs_get_current_profile(p); + if (json_object_has_member(profile, key)) { + return json_object_get_member(profile, key); + } else if ((flags & TRG_PREFS_NEWNODE)) { + JsonNode *newNode = json_node_new(JSON_NODE_VALUE); + json_object_set_member(profile, key, newNode); + return newNode; + } + } else { + if (json_object_has_member(priv->userObj, key)) { + return json_object_get_member(priv->userObj, key); + } else if ((flags & TRG_PREFS_NEWNODE)) { + JsonNode *newNode = json_node_new(JSON_NODE_VALUE); + json_object_set_member(priv->userObj, key, newNode); + return newNode; + } + } + + if (priv->defaultsObj && json_object_has_member(priv->defaultsObj, + key)) { + return json_object_get_member(priv->defaultsObj, key); + } + + return NULL; +} + +gchar *trg_prefs_get_string(TrgPrefs *p, gchar *key, int flags) { + JsonNode *node = trg_prefs_get_value(p, key, flags); + if (node) + return g_strdup(json_node_get_string(node)); + else + return NULL; +} + +int trg_prefs_get_int(TrgPrefs *p, gchar *key, int flags) { + JsonNode *node = trg_prefs_get_value(p, key, flags); + if (node) + return json_node_get_int(node); + else + return 0; +} + +gdouble trg_prefs_get_double(TrgPrefs *p, gchar *key, int flags) { + JsonNode *node = trg_prefs_get_value(p, key, flags); + if (node) + return json_node_get_double(node); + else + return 0.0; +} + +gboolean trg_prefs_get_bool(TrgPrefs *p, gchar *key, int flags) { + JsonNode *node = trg_prefs_get_value(p, key, flags); + if (node) + return json_node_get_boolean(node); + else + return FALSE; +} + +void trg_prefs_set_int(TrgPrefs *p, gchar *key, int value, int flags) { + JsonNode *node = trg_prefs_get_value(p, key, flags | TRG_PREFS_NEWNODE); + json_node_set_int(node, (gint64)value); +} + +void trg_prefs_set_string(TrgPrefs *p, gchar *key, const gchar *value, + int flags) { + JsonNode *node = trg_prefs_get_value(p, key, flags | TRG_PREFS_NEWNODE); + json_node_set_string(node, value); +} + +void trg_prefs_set_profile(TrgPrefs *p, int index) { + trg_prefs_set_int(p, TRG_PREFS_KEY_PROFILE_ID, index, TRG_PREFS_GLOBAL); +} + +gint trg_prefs_new_profile(TrgPrefs *p) { + JsonArray *profiles = trg_prefs_get_profiles(p); + JsonObject *newp = trg_prefs_new_profile_object(); + json_array_add_object_element(profiles, newp); + return json_array_get_length(profiles) - 1; +} + +void trg_prefs_del_profile(TrgPrefs *p, guint index) { + JsonArray *profiles = trg_prefs_get_profiles(p); + json_array_remove_element(profiles, index); +} + +JsonArray* trg_prefs_get_profiles(TrgPrefs *p) { + TrgPrefsPrivate *priv = GET_PRIVATE(p); + return json_object_get_array_member(priv->userObj, TRG_PREFS_KEY_PROFILES); +} + +void trg_prefs_set_double(TrgPrefs *p, gchar *key, gdouble value, int flags) { + JsonNode *node = trg_prefs_get_value(p, key, flags | TRG_PREFS_NEWNODE); + json_node_set_double(node, value); +} + +void trg_prefs_set_bool(TrgPrefs *p, gchar *key, gboolean value, int flags) { + JsonNode *node = trg_prefs_get_value(p, key, flags | TRG_PREFS_NEWNODE); + json_node_set_boolean(node, value); +} + +gboolean trg_prefs_save(TrgPrefs *p) { + TrgPrefsPrivate *priv = GET_PRIVATE(p); + JsonGenerator *gen = json_generator_new(); + gchar *dirName; + gboolean success = TRUE; + + dirName = g_path_get_dirname (priv->file); + if (!g_file_test(dirName, G_FILE_TEST_IS_DIR)) + success = g_mkdir_with_parents (dirName, TRG_PREFS_DEFAULT_DIR_MODE) == 0; + g_free(dirName); + + if (!success) { + g_error("Problem creating parent directory (permissions?) for: %s\n", priv->file); + return success; + } + + g_object_set(G_OBJECT(gen), "pretty", TRUE, NULL); + json_generator_set_root(gen, priv->user); + + success = json_generator_to_file(gen, priv->file, NULL); + if (!success) + g_error("Problem writing configuration file (permissions?) to: %s", priv->file); + + g_object_unref(gen); + + return success; +} + +JsonObject *trg_prefs_get_root(TrgPrefs *p) { + TrgPrefsPrivate *priv = GET_PRIVATE(p); + return priv->userObj; +} + +void trg_prefs_empty_init(TrgPrefs *p) { + TrgPrefsPrivate *priv = GET_PRIVATE(p); + priv->user = json_node_new(JSON_NODE_OBJECT); + priv->userObj = json_object_new(); + json_node_take_object(priv->user, priv->userObj); + + JsonObject *profile = trg_prefs_new_profile_object(); + + JsonArray *profiles = json_array_new(); + json_array_add_object_element(profiles, profile); + json_object_set_array_member(priv->userObj, TRG_PREFS_KEY_PROFILES, + profiles); + + json_object_set_int_member(priv->userObj, TRG_PREFS_KEY_PROFILE_ID, 0); +} + +void trg_prefs_load(TrgPrefs *p) { + TrgPrefsPrivate *priv = GET_PRIVATE(p); + JsonParser *parser = json_parser_new(); + JsonNode *root; + guint n_profiles; + JsonArray *profiles; + + gboolean parsed = json_parser_load_from_file(parser, priv->file, NULL); + + if (!parsed) { + trg_prefs_empty_init(p); + g_object_unref(parser); + return; + } + + root = json_parser_get_root(parser); + if (root) { + priv->user = json_node_copy(root); + priv->userObj = json_node_get_object(priv->user); + } + + g_object_unref(parser); + + if (!root) { + trg_prefs_empty_init(p); + return; + } + + if (!json_object_has_member(priv->userObj, TRG_PREFS_KEY_PROFILES)) { + profiles = json_array_new(); + json_object_set_array_member(priv->userObj, TRG_PREFS_KEY_PROFILES, + profiles); + } else { + profiles = json_object_get_array_member(priv->userObj, + TRG_PREFS_KEY_PROFILES); + } + + n_profiles = json_array_get_length(profiles); + + if (n_profiles < 1) { + json_array_add_object_element(profiles, trg_prefs_new_profile_object()); + trg_prefs_set_int(p, TRG_PREFS_KEY_PROFILE_ID, 0, TRG_PREFS_GLOBAL); + } else { + gint profile_id = trg_prefs_get_int(p, TRG_PREFS_KEY_PROFILE_ID, + TRG_PREFS_GLOBAL); + if (profile_id >= n_profiles) + trg_prefs_set_int(p, TRG_PREFS_KEY_PROFILE_ID, 0, TRG_PREFS_GLOBAL); + } +} diff --git a/src/trg-prefs.h b/src/trg-prefs.h new file mode 100644 index 0000000..0bbdd74 --- /dev/null +++ b/src/trg-prefs.h @@ -0,0 +1,127 @@ +/* + * transmission-remote-gtk - A GTK RPC client to Transmission + * Copyright (C) 2011 Alan Fitton + + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef _TRG_PREFS_H_ +#define _TRG_PREFS_H_ + +#include <glib-object.h> +#include <json-glib/json-glib.h> + +#define TRG_PREFS_FILENAME "config.json" +#define TRG_PREFS_DEFAULT_DIR_MODE 448 +#define TRG_PORT_DEFAULT 9091 +#define TRG_INTERVAL_DEFAULT 3 +#define TRG_PROFILE_NAME_DEFAULT "Default" + +#define TRG_PREFS_KEY_PROFILE_ID "profile-id" +#define TRG_PREFS_KEY_PROFILES "profiles" +#define TRG_PREFS_KEY_PROFILE_NAME "profile-name" +#define TRG_PREFS_KEY_HOSTNAME "hostname" +#define TRG_PREFS_KEY_PORT "port" +#define TRG_PREFS_KEY_USERNAME "username" +#define TRG_PREFS_KEY_PASSWORD "password" +#define TRG_PREFS_KEY_AUTO_CONNECT "auto-connect" +#define TRG_PREFS_KEY_SSL "ssl" +#define TRG_PREFS_KEY_UPDATE_INTERVAL "update-interval" +#define TRG_PREFS_KEY_COMPLETE_NOTIFY "complete-notify" +#define TRG_PREFS_KEY_ADD_NOTIFY "add-notify" +#define TRG_PREFS_KEY_WINDOW_WIDTH "window-width" +#define TRG_PREFS_KEY_WINDOW_HEIGHT "window-height" +#define TRG_PREFS_KEY_GRAPH_SPAN "graph-span" +#define TRG_PREFS_KEY_SYSTEM_TRAY "system-tray" +#define TRG_PREFS_KEY_SHOW_GRAPH "show-graph" +#define TRG_PREFS_KEY_SYSTEM_TRAY_MINIMISE "system-tray-minimise" +#define TRG_PREFS_KEY_FILTER_TRACKERS "filter-trackers" +#define TRG_PREFS_KEY_FILTER_DIRS "filter-dirs" +#define TRG_PREFS_KEY_LAST_TORRENT_DIR "last-torrent-dir" +#define TRG_PREFS_KEY_ADD_OPTIONS_DIALOG "add-options-dialog" +#define TRG_PREFS_KEY_START_PAUSED "start-paused" +#define TRG_PREFS_KEY_UPDATE_ACTIVE_ONLY "update-active-only" + +#define TRG_PREFS_KEY_TREE_VIEWS "tree-views" +#define TRG_PREFS_KEY_TV_SORT_TYPE "sort-type" +#define TRG_PREFS_KEY_TV_SORT_COL "sort-col" +#define TRG_PREFS_KEY_TV_COLUMNS "columns" +#define TRG_PREFS_KEY_TV_WIDTHS "widths" + +#define TRG_PREFS_NOFLAGS (1 << 0) /* 0x00 */ +#define TRG_PREFS_GLOBAL (1 << 1) /* 0x01 */ +#define TRG_PREFS_PROFILE (1 << 2) /* 0x02 */ +#define TRG_PREFS_NEWNODE (1 << 3) /* 0x04 */ + +G_BEGIN_DECLS + +#define TRG_TYPE_PREFS trg_prefs_get_type() + +#define TRG_PREFS(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), TRG_TYPE_PREFS, TrgPrefs)) + +#define TRG_PREFS_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), TRG_TYPE_PREFS, TrgPrefsClass)) + +#define TRG_IS_PREFS(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TRG_TYPE_PREFS)) + +#define TRG_IS_PREFS_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), TRG_TYPE_PREFS)) + +#define TRG_PREFS_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), TRG_TYPE_PREFS, TrgPrefsClass)) + +typedef struct { + GObject parent; +} TrgPrefs; + +typedef struct { + GObjectClass parent_class; +} TrgPrefsClass; + +GType trg_prefs_get_type (void); + +TrgPrefs* trg_prefs_new (void); + +void trg_prefs_add_default_int(TrgPrefs *p, gchar *key, int value); +void trg_prefs_add_default_string(TrgPrefs *p, gchar *key, gchar *value); +void trg_prefs_add_default_double(TrgPrefs *p, gchar *key, double value); +void trg_prefs_add_default_bool(TrgPrefs *p, gchar *key, gboolean value); + +JsonNode *trg_prefs_get_value(TrgPrefs *p, gchar *key, int flags); +gchar *trg_prefs_get_string(TrgPrefs *p, gchar *key, int flags); +int trg_prefs_get_int(TrgPrefs *p, gchar *key, int flags); +gdouble trg_prefs_get_double(TrgPrefs *p, gchar *key, int flags); +gboolean trg_prefs_get_bool(TrgPrefs *p, gchar *key, int flags); +JsonArray* trg_prefs_get_profiles(TrgPrefs *p); +gint trg_prefs_get_profile_id(TrgPrefs *p); +void trg_prefs_del_profile(TrgPrefs *p, guint index); +void trg_prefs_set_profile(TrgPrefs *p, int index); +gint trg_prefs_new_profile(TrgPrefs *p); +JsonObject *trg_get_current_profile(TrgPrefs *p); +JsonObject *trg_prefs_get_root(TrgPrefs *p); + +void trg_prefs_set_int(TrgPrefs *p, gchar *key, int value, int flags); +void trg_prefs_set_string(TrgPrefs *p, gchar *key, const gchar *value, int flags); +void trg_prefs_set_double(TrgPrefs *p, gchar *key, double value, int flags); +void trg_prefs_set_bool(TrgPrefs *p, gchar *key, gboolean value, int flags); + +gboolean trg_prefs_save(TrgPrefs *p); +void trg_prefs_load(TrgPrefs *p); + +G_END_DECLS + +#endif /* _TRG_PREFS_H_ */ diff --git a/src/trg-remote-prefs-dialog.c b/src/trg-remote-prefs-dialog.c index a65371f..880d811 100644 --- a/src/trg-remote-prefs-dialog.c +++ b/src/trg-remote-prefs-dialog.c @@ -44,7 +44,7 @@ enum { typedef struct _TrgRemotePrefsDialogPrivate TrgRemotePrefsDialogPrivate; struct _TrgRemotePrefsDialogPrivate { - trg_client *client; + TrgClient *client; TrgMainWindow *parent; GtkWidget *done_script_entry; @@ -587,7 +587,7 @@ static GObject *trg_remote_prefs_dialog_constructor(GType type, n_construct_properties, construct_params); priv = TRG_REMOTE_PREFS_DIALOG_GET_PRIVATE(object); - session = priv->client->session; + session = trg_client_get_session(priv->client); gtk_window_set_title(GTK_WINDOW(object), _("Remote Preferences")); gtk_window_set_transient_for(GTK_WINDOW(object), @@ -679,7 +679,7 @@ trg_remote_prefs_dialog_init(TrgRemotePrefsDialog * self G_GNUC_UNUSED) TrgRemotePrefsDialog *trg_remote_prefs_dialog_get_instance(TrgMainWindow * parent, - trg_client * + TrgClient * client) { if (instance == NULL) { diff --git a/src/trg-remote-prefs-dialog.h b/src/trg-remote-prefs-dialog.h index a6af9ea..1f8113e 100644 --- a/src/trg-remote-prefs-dialog.h +++ b/src/trg-remote-prefs-dialog.h @@ -50,7 +50,7 @@ GType trg_remote_prefs_dialog_get_type(void); TrgRemotePrefsDialog *trg_remote_prefs_dialog_get_instance(TrgMainWindow * parent, - trg_client * + TrgClient * client); G_END_DECLS diff --git a/src/trg-state-selector.c b/src/trg-state-selector.c index f16412b..fa34516 100644 --- a/src/trg-state-selector.c +++ b/src/trg-state-selector.c @@ -26,7 +26,7 @@ #include "trg-state-selector.h" #include "trg-torrent-model.h" #include "util.h" -#include "trg-preferences.h" +#include "trg-prefs.h" #include "trg-client.h" enum { @@ -47,7 +47,7 @@ struct _TrgStateSelectorPrivate { guint flag; gboolean showDirs; gboolean showTrackers; - trg_client *client; + TrgClient *client; GHashTable *trackers; GHashTable *directories; GRegex *urlHostRegex; @@ -263,8 +263,9 @@ void trg_state_selector_update(TrgStateSelector * s) { TrgStateSelectorPrivate *priv = TRG_STATE_SELECTOR_GET_PRIVATE(s); GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(s)); - trg_client *client = priv->client; - GList *torrentItemRefs = g_hash_table_get_values(client->torrentTable); + TrgClient *client = priv->client; + gint64 updateSerial = trg_client_get_serial(client); + GList *torrentItemRefs = g_hash_table_get_values(trg_client_get_torrent_table(client)); GtkTreeIter iter; GList *trackersList, *trackerItem, *li; GtkTreeRowReference *rr; @@ -273,7 +274,7 @@ void trg_state_selector_update(TrgStateSelector * s) gpointer result; struct cruft_remove_args cruft; - if (!client->session) + if (!trg_client_is_connected(client)) return; for (li = torrentItemRefs; li; li = g_list_next(li)) { @@ -315,7 +316,7 @@ void trg_state_selector_update(TrgStateSelector * s) (GtkTreeRowReference *) result, - client->updateSerial); + updateSerial); g_free(announceHost); } else { trg_state_selector_insert(s, N_CATEGORIES, @@ -325,7 +326,7 @@ void trg_state_selector_update(TrgStateSelector * s) GTK_STOCK_NETWORK, STATE_SELECTOR_NAME, announceHost, STATE_SELECTOR_SERIAL, - client->updateSerial, + updateSerial, STATE_SELECTOR_BIT, FILTER_FLAG_TRACKER, -1); g_hash_table_insert(priv->trackers, announceHost, @@ -342,7 +343,7 @@ void trg_state_selector_update(TrgStateSelector * s) trg_state_selector_update_serial(model, (GtkTreeRowReference *) result, - client->updateSerial); + updateSerial); } else { trg_state_selector_insert(s, N_CATEGORIES+ g_hash_table_size(priv->trackers), -1, dir, &iter); @@ -351,7 +352,7 @@ void trg_state_selector_update(TrgStateSelector * s) GTK_STOCK_DIRECTORY, STATE_SELECTOR_NAME, dir, STATE_SELECTOR_SERIAL, - client->updateSerial, + updateSerial, STATE_SELECTOR_BIT, FILTER_FLAG_DIR, -1); g_hash_table_insert(priv->directories, g_strdup(dir), @@ -362,7 +363,7 @@ void trg_state_selector_update(TrgStateSelector * s) g_list_free(torrentItemRefs); - cruft.serial = client->updateSerial; + cruft.serial = trg_client_get_serial(client); if (priv->showTrackers) { cruft.table = priv->trackers; @@ -510,18 +511,19 @@ static void trg_state_selector_init(TrgStateSelector * self) STATE_SELECTOR_NAME); } -TrgStateSelector *trg_state_selector_new(trg_client * client) +TrgStateSelector *trg_state_selector_new(TrgClient * client) { GObject *obj = g_object_new(TRG_TYPE_STATE_SELECTOR, NULL); TrgStateSelectorPrivate *priv = TRG_STATE_SELECTOR_GET_PRIVATE(obj); + TrgPrefs *prefs = trg_client_get_prefs(client); priv->client = client; priv->showDirs = - gconf_client_get_bool(client->gconf, - TRG_GCONF_KEY_FILTER_DIRS, NULL); + trg_prefs_get_bool(prefs, + TRG_PREFS_KEY_FILTER_DIRS, TRG_PREFS_GLOBAL); priv->showTrackers = - gconf_client_get_bool_or_true(client->gconf, - TRG_GCONF_KEY_FILTER_TRACKERS); + trg_prefs_get_bool(prefs, + TRG_PREFS_KEY_FILTER_TRACKERS, TRG_PREFS_GLOBAL); return TRG_STATE_SELECTOR(obj); } diff --git a/src/trg-state-selector.h b/src/trg-state-selector.h index 03e4f1e..f611149 100644 --- a/src/trg-state-selector.h +++ b/src/trg-state-selector.h @@ -58,7 +58,7 @@ typedef struct { } TrgStateSelectorClass; GType trg_state_selector_get_type(void); -TrgStateSelector *trg_state_selector_new(trg_client * client); +TrgStateSelector *trg_state_selector_new(TrgClient * client); G_END_DECLS guint32 trg_state_selector_get_flag(TrgStateSelector * s); void trg_state_selector_update(TrgStateSelector * s); diff --git a/src/trg-stats-dialog.c b/src/trg-stats-dialog.c index d5b6561..9ecbc28 100644 --- a/src/trg-stats-dialog.c +++ b/src/trg-stats-dialog.c @@ -45,13 +45,15 @@ enum { PROP_CLIENT }; +#define STATS_UPDATE_INTERVAL 5 + G_DEFINE_TYPE(TrgStatsDialog, trg_stats_dialog, GTK_TYPE_DIALOG) #define TRG_STATS_DIALOG_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRG_TYPE_STATS_DIALOG, TrgStatsDialogPrivate)) typedef struct _TrgStatsDialogPrivate TrgStatsDialogPrivate; struct _TrgStatsDialogPrivate { - trg_client *client; + TrgClient *client; TrgMainWindow *parent; GtkWidget *tv; GtkListStore *model; @@ -210,8 +212,8 @@ static void on_stats_reply(JsonObject * response, int status, update_int_stat(args, priv->rr_session_count, "sessionCount"); update_time_stat(args, priv->rr_active, "secondsActive"); - if (priv->client->session) - g_timeout_add_seconds(5, trg_update_stats_timerfunc, data); + if (trg_client_is_connected(priv->client)) + g_timeout_add_seconds(STATS_UPDATE_INTERVAL, trg_update_stats_timerfunc, data); } else { trg_error_dialog(GTK_WINDOW(data), status, response); } @@ -351,7 +353,7 @@ static void trg_stats_dialog_init(TrgStatsDialog * self) } TrgStatsDialog *trg_stats_dialog_get_instance(TrgMainWindow * parent, - trg_client * client) + TrgClient * client) { if (instance == NULL) { instance = g_object_new(TRG_TYPE_STATS_DIALOG, diff --git a/src/trg-stats-dialog.h b/src/trg-stats-dialog.h index 1353d68..ee0656e 100644 --- a/src/trg-stats-dialog.h +++ b/src/trg-stats-dialog.h @@ -50,7 +50,7 @@ typedef struct { GType trg_stats_dialog_get_type(void); TrgStatsDialog *trg_stats_dialog_get_instance(TrgMainWindow * parent, - trg_client * client); + TrgClient * client); G_END_DECLS #endif /* TRG_STATS_DIALOG_H_ */ diff --git a/src/trg-status-bar.c b/src/trg-status-bar.c index 3e45b72..8ccbe72 100644 --- a/src/trg-status-bar.c +++ b/src/trg-status-bar.c @@ -79,27 +79,29 @@ void trg_status_bar_connect(TrgStatusBar * sb, JsonObject * session) void trg_status_bar_update(TrgStatusBar * sb, trg_torrent_model_update_stats * stats, - trg_client * client) + TrgClient * client) { TrgStatusBarPrivate *priv; + JsonObject *session; gchar *statusBarUpdate; gint64 uplimitraw, downlimitraw; gchar downRateTotalString[32], upRateTotalString[32]; gchar uplimit[64], downlimit[64]; priv = TRG_STATUS_BAR_GET_PRIVATE(sb); + session = trg_client_get_session(client); /* The session should always exist otherwise this function wouldn't be called */ downlimitraw = - json_object_get_boolean_member(client->session, + json_object_get_boolean_member(session, SGET_SPEED_LIMIT_DOWN_ENABLED) ? - json_object_get_int_member(client->session, + json_object_get_int_member(session, SGET_SPEED_LIMIT_DOWN) : -1; uplimitraw = - json_object_get_boolean_member(client->session, + json_object_get_boolean_member(session, SGET_SPEED_LIMIT_UP_ENABLED) ? - json_object_get_int_member(client->session, + json_object_get_int_member(session, SGET_SPEED_LIMIT_UP) : -1; trg_strlspeed(downRateTotalString, diff --git a/src/trg-status-bar.h b/src/trg-status-bar.h index 88b4ed1..4f7212e 100644 --- a/src/trg-status-bar.h +++ b/src/trg-status-bar.h @@ -53,7 +53,7 @@ TrgStatusBar *trg_status_bar_new(); G_END_DECLS void trg_status_bar_update(TrgStatusBar * sb, trg_torrent_model_update_stats * stats, - trg_client * client); + TrgClient * client); void trg_status_bar_connect(TrgStatusBar * sb, JsonObject * session); void trg_status_bar_push_connection_msg(TrgStatusBar * sb, const gchar * msg); diff --git a/src/trg-torrent-add-dialog.c b/src/trg-torrent-add-dialog.c index f6f17e6..ae44c0e 100644 --- a/src/trg-torrent-add-dialog.c +++ b/src/trg-torrent-add-dialog.c @@ -26,7 +26,6 @@ #include <gtk/gtk.h> #include <json-glib/json-glib.h> #include <glib/gprintf.h> -#include <gconf/gconf-client.h> #include "hig.h" #include "util.h" @@ -36,7 +35,7 @@ #include "trg-torrent-add-dialog.h" #include "trg-cell-renderer-size.h" #include "trg-destination-combo.h" -#include "trg-preferences.h" +#include "trg-prefs.h" #include "requests.h" #include "torrent.h" #include "json.h" @@ -74,7 +73,7 @@ typedef struct _TrgTorrentAddDialogPrivate TrgTorrentAddDialogPrivate; struct _TrgTorrentAddDialogPrivate { - trg_client *client; + TrgClient *client; TrgMainWindow *parent; GSList *filenames; GtkWidget *source_chooser; @@ -733,19 +732,18 @@ static void trg_torrent_add_dialog_set_filenames(TrgTorrentAddDialog * d, } static void trg_torrent_add_dialog_generic_save_dir(GtkFileChooser * c, - GConfClient * gcc) + TrgPrefs *prefs) { gchar *cwd = gtk_file_chooser_get_current_folder(c); if (cwd) { - gconf_client_set_string(gcc, TRG_GCONF_KEY_LAST_TORRENT_DIR, cwd, - NULL); + trg_prefs_set_string(prefs, TRG_PREFS_KEY_LAST_TORRENT_DIR, cwd, TRG_PREFS_GLOBAL); g_free(cwd); } } static GtkWidget *trg_torrent_add_dialog_generic(GtkWindow * parent, - GConfClient * gcc) + TrgPrefs * prefs) { GtkWidget *w = gtk_file_chooser_dialog_new(_("Add a Torrent"), parent, GTK_FILE_CHOOSER_ACTION_OPEN, @@ -755,7 +753,7 @@ static GtkWidget *trg_torrent_add_dialog_generic(GtkWindow * parent, GTK_RESPONSE_ACCEPT, NULL); gchar *dir = - gconf_client_get_string(gcc, TRG_GCONF_KEY_LAST_TORRENT_DIR, NULL); + trg_prefs_get_string(prefs, TRG_PREFS_KEY_LAST_TORRENT_DIR, TRG_PREFS_GLOBAL); if (dir) { gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(w), dir); g_free(dir); @@ -774,7 +772,7 @@ static void trg_torrent_add_dialog_source_click_cb(GtkWidget * w, TrgTorrentAddDialogPrivate *priv = TRG_TORRENT_ADD_DIALOG_GET_PRIVATE(data); GtkWidget *d = trg_torrent_add_dialog_generic(GTK_WINDOW(data), - priv->client->gconf); + trg_client_get_prefs(priv->client)); if (gtk_dialog_run(GTK_DIALOG(d)) == GTK_RESPONSE_ACCEPT) { if (priv->filenames) @@ -784,7 +782,7 @@ static void trg_torrent_add_dialog_source_click_cb(GtkWidget * w, gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(d)); trg_torrent_add_dialog_generic_save_dir(GTK_FILE_CHOOSER(d), - priv->client->gconf); + trg_client_get_prefs(priv->client)); trg_torrent_add_dialog_set_filenames(TRG_TORRENT_ADD_DIALOG(data), priv->filenames); } @@ -804,6 +802,7 @@ static GObject *trg_torrent_add_dialog_constructor(GType type, construct_params); TrgTorrentAddDialogPrivate *priv = TRG_TORRENT_ADD_DIALOG_GET_PRIVATE(obj); + TrgPrefs *prefs = trg_client_get_prefs(priv->client); GtkWidget *t, *l; gint row = 0; @@ -836,8 +835,7 @@ static GObject *trg_torrent_add_dialog_constructor(GType type, priv->paused_check = gtk_check_button_new_with_mnemonic(_("Start _paused")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->paused_check), - pref_get_start_paused(priv-> - client->gconf)); + trg_prefs_get_bool(prefs, TRG_PREFS_KEY_START_PAUSED, TRG_PREFS_GLOBAL)); priv->priority_combo = gtr_priority_combo_new(); gtk_combo_box_set_active(GTK_COMBO_BOX(priv->priority_combo), 1); @@ -967,7 +965,7 @@ static void trg_torrent_add_dialog_init(TrgTorrentAddDialog * self) } TrgTorrentAddDialog *trg_torrent_add_dialog_new(TrgMainWindow * parent, - trg_client * client, + TrgClient * client, GSList * filenames) { return g_object_new(TRG_TYPE_TORRENT_ADD_DIALOG, @@ -975,17 +973,17 @@ TrgTorrentAddDialog *trg_torrent_add_dialog_new(TrgMainWindow * parent, "parent", parent, "client", client, NULL); } -void trg_torrent_add_dialog(TrgMainWindow * win, trg_client * client) +void trg_torrent_add_dialog(TrgMainWindow * win, TrgClient * client) { GtkWidget *w; GtkWidget *c; + TrgPrefs *prefs = trg_client_get_prefs(client); - w = trg_torrent_add_dialog_generic(GTK_WINDOW(win), client->gconf); + w = trg_torrent_add_dialog_generic(GTK_WINDOW(win), prefs); c = gtk_check_button_new_with_mnemonic(_("Show _options dialog")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(c), - pref_get_add_options_dialog - (client->gconf)); + trg_prefs_get_bool(prefs, TRG_PREFS_KEY_ADD_OPTIONS_DIALOG, TRG_PREFS_GLOBAL)); gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(w), c); if (gtk_dialog_run(GTK_DIALOG(w)) == GTK_RESPONSE_ACCEPT) { @@ -996,7 +994,7 @@ void trg_torrent_add_dialog(TrgMainWindow * win, trg_client * client) GSList *l = gtk_file_chooser_get_filenames(chooser); trg_torrent_add_dialog_generic_save_dir(GTK_FILE_CHOOSER(w), - client->gconf); + prefs); if (showOptions) { TrgTorrentAddDialog *dialog = @@ -1009,7 +1007,7 @@ void trg_torrent_add_dialog(TrgMainWindow * win, trg_client * client) args->list = l; args->cb_data = win; args->client = client; - args->paused = pref_get_start_paused(client->gconf); + args->paused = trg_prefs_get_bool(prefs, TRG_PREFS_KEY_START_PAUSED, TRG_PREFS_GLOBAL); args->extraArgs = FALSE; launch_add_thread(args); diff --git a/src/trg-torrent-add-dialog.h b/src/trg-torrent-add-dialog.h index a64379d..88ed9ab 100644 --- a/src/trg-torrent-add-dialog.h +++ b/src/trg-torrent-add-dialog.h @@ -53,7 +53,7 @@ typedef struct { struct add_torrent_threadfunc_args { GSList *list; - trg_client *client; + TrgClient *client; gpointer cb_data; gboolean paused; gchar *dir; @@ -64,9 +64,9 @@ struct add_torrent_threadfunc_args { GType trg_torrent_add_dialog_get_type(void); TrgTorrentAddDialog *trg_torrent_add_dialog_new(TrgMainWindow * win, - trg_client * client, + TrgClient * client, GSList * filenames); -void trg_torrent_add_dialog(TrgMainWindow * win, trg_client * client); +void trg_torrent_add_dialog(TrgMainWindow * win, TrgClient * client); void launch_add_thread(struct add_torrent_threadfunc_args *args); G_END_DECLS diff --git a/src/trg-torrent-add-url-dialog.c b/src/trg-torrent-add-url-dialog.c index 737c749..0a2908c 100644 --- a/src/trg-torrent-add-url-dialog.c +++ b/src/trg-torrent-add-url-dialog.c @@ -36,7 +36,7 @@ typedef struct _TrgTorrentAddUrlDialogPrivate TrgTorrentAddUrlDialogPrivate; struct _TrgTorrentAddUrlDialogPrivate { - trg_client *client; + TrgClient *client; TrgMainWindow *win; GtkWidget *urlEntry, *startCheck, *addButton; }; @@ -113,7 +113,7 @@ static void trg_torrent_add_url_dialog_init(TrgTorrentAddUrlDialog * self) } TrgTorrentAddUrlDialog *trg_torrent_add_url_dialog_new(TrgMainWindow * win, - trg_client * client) + TrgClient * client) { GObject *obj = g_object_new(TRG_TYPE_TORRENT_ADD_URL_DIALOG, NULL); TrgTorrentAddUrlDialogPrivate *priv = diff --git a/src/trg-torrent-add-url-dialog.h b/src/trg-torrent-add-url-dialog.h index 8e2fb26..a9a801d 100644 --- a/src/trg-torrent-add-url-dialog.h +++ b/src/trg-torrent-add-url-dialog.h @@ -49,7 +49,7 @@ typedef struct { GType trg_torrent_add_url_dialog_get_type(void); TrgTorrentAddUrlDialog *trg_torrent_add_url_dialog_new(TrgMainWindow * win, - trg_client * + TrgClient * client); G_END_DECLS diff --git a/src/trg-torrent-model.c b/src/trg-torrent-model.c index 7e9c3a1..b939afd 100644 --- a/src/trg-torrent-model.c +++ b/src/trg-torrent-model.c @@ -439,7 +439,7 @@ gboolean get_torrent_data(GHashTable * table, gint64 id, JsonObject ** t, return found; } -void trg_torrent_model_update(TrgTorrentModel * model, trg_client * tc, +void trg_torrent_model_update(TrgTorrentModel * model, TrgClient * tc, JsonObject * response, trg_torrent_model_update_stats * stats, gint mode) @@ -473,7 +473,7 @@ void trg_torrent_model_update(TrgTorrentModel * model, trg_client * tc, if (!result) { gtk_list_store_append(GTK_LIST_STORE(model), &iter); - update_torrent_iter(model, tc->updateSerial, &iter, t, stats); + update_torrent_iter(model, trg_client_get_serial(tc), &iter, t, stats); path = gtk_tree_model_get_path(GTK_TREE_MODEL(model), &iter); rr = gtk_tree_row_reference_new(GTK_TREE_MODEL(model), path); @@ -491,7 +491,7 @@ void trg_torrent_model_update(TrgTorrentModel * model, trg_client * tc, if (path) { if (gtk_tree_model_get_iter (GTK_TREE_MODEL(model), &iter, path)) { - update_torrent_iter(model, tc->updateSerial, &iter, t, + update_torrent_iter(model, trg_client_get_serial(tc), &iter, t, stats); } gtk_tree_path_free(path); @@ -504,7 +504,7 @@ void trg_torrent_model_update(TrgTorrentModel * model, trg_client * tc, if (mode == TORRENT_GET_MODE_UPDATE) { GList *hitlist = trg_torrent_model_find_removed(GTK_TREE_MODEL(model), - tc->updateSerial); + trg_client_get_serial(tc)); if (hitlist) { for (li = hitlist; li; li = g_list_next(li)) { g_hash_table_remove(priv->ht, li->data); diff --git a/src/trg-torrent-model.h b/src/trg-torrent-model.h index c752127..714af50 100644 --- a/src/trg-torrent-model.h +++ b/src/trg-torrent-model.h @@ -69,7 +69,7 @@ G_END_DECLS find_existing_peer_item(GtkListStore * model, JsonObject * p, GtkTreeIter * iter); -void trg_torrent_model_update(TrgTorrentModel * model, trg_client * tc, +void trg_torrent_model_update(TrgTorrentModel * model, TrgClient * tc, JsonObject * response, trg_torrent_model_update_stats * stats, gint mode); diff --git a/src/trg-torrent-move-dialog.c b/src/trg-torrent-move-dialog.c index d683663..b270b4a 100644 --- a/src/trg-torrent-move-dialog.c +++ b/src/trg-torrent-move-dialog.c @@ -39,7 +39,7 @@ typedef struct _TrgTorrentMoveDialogPrivate TrgTorrentMoveDialogPrivate; struct _TrgTorrentMoveDialogPrivate { - trg_client *client; + TrgClient *client; TrgMainWindow *win; TrgTorrentTreeView *treeview; JsonArray *ids; @@ -148,7 +148,7 @@ static GObject *trg_torrent_move_dialog_constructor(GType type, JsonObject *json; const gchar *name; - get_torrent_data(priv->client->torrentTable, + get_torrent_data(trg_client_get_torrent_table(priv->client), trg_mw_get_selected_torrent_id(priv->win), &json, NULL); name = torrent_get_name(json); @@ -263,7 +263,7 @@ static void trg_torrent_move_dialog_init(TrgTorrentMoveDialog * self) } TrgTorrentMoveDialog *trg_torrent_move_dialog_new(TrgMainWindow * win, - trg_client * client, + TrgClient * client, TrgTorrentTreeView * ttv) { return g_object_new(TRG_TYPE_TORRENT_MOVE_DIALOG, diff --git a/src/trg-torrent-move-dialog.h b/src/trg-torrent-move-dialog.h index 34ed63c..c99f78f 100644 --- a/src/trg-torrent-move-dialog.h +++ b/src/trg-torrent-move-dialog.h @@ -49,7 +49,7 @@ typedef struct { GType trg_torrent_move_dialog_get_type(void); TrgTorrentMoveDialog *trg_torrent_move_dialog_new(TrgMainWindow * win, - trg_client * client, + TrgClient * client, TrgTorrentTreeView * ttv); diff --git a/src/trg-torrent-props-dialog.c b/src/trg-torrent-props-dialog.c index 3b8809d..4e4e9bd 100644 --- a/src/trg-torrent-props-dialog.c +++ b/src/trg-torrent-props-dialog.c @@ -25,13 +25,13 @@ #include "json.h" #include "dispatch.h" #include "trg-client.h" +#include "trg-json-widgets.h" #include "requests.h" #include "protocol-constants.h" #include "trg-torrent-model.h" #include "trg-torrent-tree-view.h" #include "trg-torrent-props-dialog.h" #include "trg-main-window.h" -#include "trg-json-widgets.h" #include "hig.h" G_DEFINE_TYPE(TrgTorrentPropsDialog, trg_torrent_props_dialog, @@ -50,7 +50,7 @@ typedef struct _TrgTorrentPropsDialogPrivate TrgTorrentPropsDialogPrivate; struct _TrgTorrentPropsDialogPrivate { TrgTorrentTreeView *tv; - trg_client *client; + TrgClient *client; TrgMainWindow *parent; JsonArray *targetIds; @@ -274,7 +274,7 @@ static GObject *trg_torrent_props_dialog_constructor(GType type, selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->tv)); rowCount = gtk_tree_selection_count_selected_rows(selection); - get_torrent_data(priv->client->torrentTable, + get_torrent_data(trg_client_get_torrent_table(priv->client), trg_mw_get_selected_torrent_id(priv->parent), &json, NULL); priv->targetIds = build_json_id_array(priv->tv); @@ -382,7 +382,7 @@ trg_torrent_props_dialog_init(TrgTorrentPropsDialog * self G_GNUC_UNUSED) TrgTorrentPropsDialog *trg_torrent_props_dialog_new(GtkWindow * window, TrgTorrentTreeView * treeview, - trg_client * client) + TrgClient * client) { return g_object_new(TRG_TYPE_TORRENT_PROPS_DIALOG, "parent-window", window, diff --git a/src/trg-torrent-props-dialog.h b/src/trg-torrent-props-dialog.h index 9d1efed..78d72de 100644 --- a/src/trg-torrent-props-dialog.h +++ b/src/trg-torrent-props-dialog.h @@ -50,7 +50,7 @@ GType trg_torrent_props_dialog_get_type(void); TrgTorrentPropsDialog *trg_torrent_props_dialog_new(GtkWindow * window, TrgTorrentTreeView * treeview, - trg_client * client); + TrgClient * client); G_END_DECLS #endif /* TRG_TORRENT_PROPS_DIALOG_H_ */ diff --git a/src/trg-torrent-tree-view.c b/src/trg-torrent-tree-view.c index d05e872..8c73fcc 100644 --- a/src/trg-torrent-tree-view.c +++ b/src/trg-torrent-tree-view.c @@ -20,6 +20,7 @@ #include <glib/gi18n.h> #include <gtk/gtk.h> +#include "trg-prefs.h" #include "trg-tree-view.h" #include "trg-torrent-model.h" #include "trg-torrent-tree-view.h" @@ -88,8 +89,6 @@ static void trg_torrent_tree_view_init(TrgTorrentTreeView * tttv) gtk_tree_view_set_search_column(GTK_TREE_VIEW(tttv), TORRENT_COLUMN_NAME); - - trg_tree_view_setup_columns(ttv); } static void @@ -118,11 +117,13 @@ JsonArray *build_json_id_array(TrgTorrentTreeView * tv) return ids; } -TrgTorrentTreeView *trg_torrent_tree_view_new(GtkTreeModel * model) +TrgTorrentTreeView *trg_torrent_tree_view_new(TrgPrefs *prefs, GtkTreeModel * model) { GObject *obj = g_object_new(TRG_TYPE_TORRENT_TREE_VIEW, NULL); + trg_tree_view_set_prefs(TRG_TREE_VIEW(obj), prefs); gtk_tree_view_set_model(GTK_TREE_VIEW(obj), model); + trg_tree_view_setup_columns(TRG_TREE_VIEW(obj)); trg_tree_view_restore_sort(TRG_TREE_VIEW(obj)); return TRG_TORRENT_TREE_VIEW(obj); diff --git a/src/trg-torrent-tree-view.h b/src/trg-torrent-tree-view.h index 20929e4..e6369ac 100644 --- a/src/trg-torrent-tree-view.h +++ b/src/trg-torrent-tree-view.h @@ -23,6 +23,7 @@ #include <glib-object.h> #include <json-glib/json-glib.h> +#include "trg-prefs.h" #include "trg-torrent-model.h" #include "trg-tree-view.h" #include "trg-state-selector.h" @@ -49,7 +50,7 @@ typedef struct { GType trg_torrent_tree_view_get_type(void); -TrgTorrentTreeView *trg_torrent_tree_view_new(GtkTreeModel * model); +TrgTorrentTreeView *trg_torrent_tree_view_new(TrgPrefs *prefs, GtkTreeModel * model); JsonArray *build_json_id_array(TrgTorrentTreeView * tv); gboolean get_torrent_data(GHashTable * table, gint64 id, JsonObject ** t, GtkTreeIter * out_iter); diff --git a/src/trg-trackers-tree-view.c b/src/trg-trackers-tree-view.c index 73cdf71..2fbccdf 100644 --- a/src/trg-trackers-tree-view.c +++ b/src/trg-trackers-tree-view.c @@ -20,6 +20,7 @@ #include <glib/gi18n.h> #include <gtk/gtk.h> +#include "trg-prefs.h" #include "trg-trackers-tree-view.h" #include "trg-tree-view.h" #include "trg-client.h" @@ -37,7 +38,7 @@ G_DEFINE_TYPE(TrgTrackersTreeView, trg_trackers_tree_view, typedef struct _TrgTrackersTreeViewPrivate TrgTrackersTreeViewPrivate; struct _TrgTrackersTreeViewPrivate { - trg_client *client; + TrgClient *client; GtkCellRenderer *announceRenderer; GtkTreeViewColumn *announceColumn; TrgMainWindow *win; @@ -62,7 +63,7 @@ on_trackers_update(JsonObject * response, int status, gpointer data) } void trg_trackers_tree_view_new_connection(TrgTrackersTreeView * tv, - trg_client * tc) + TrgClient * tc) { TrgTrackersTreeViewPrivate *priv = TRG_TRACKERS_TREE_VIEW_GET_PRIVATE(tv); @@ -177,8 +178,6 @@ static void trg_trackers_tree_view_init(TrgTrackersTreeView * self) trg_tree_view_reg_column(ttv, TRG_COLTYPE_TEXT, TRACKERCOL_SCRAPE, _("Scrape URL"), "scrape-url", 0); - - trg_tree_view_setup_columns(ttv); } static void add_tracker(GtkWidget * w, gpointer data) @@ -338,13 +337,15 @@ static gboolean view_onPopupMenu(GtkWidget * treeview, gpointer userdata) } TrgTrackersTreeView *trg_trackers_tree_view_new(TrgTrackersModel * model, - trg_client * client, + TrgClient * client, TrgMainWindow * win) { GObject *obj = g_object_new(TRG_TYPE_TRACKERS_TREE_VIEW, NULL); TrgTrackersTreeViewPrivate *priv = TRG_TRACKERS_TREE_VIEW_GET_PRIVATE(obj); + trg_tree_view_set_prefs(TRG_TREE_VIEW(obj), trg_client_get_prefs(client)); + g_signal_connect(obj, "button-press-event", G_CALLBACK(view_onButtonPressed), NULL); g_signal_connect(obj, "popup-menu", G_CALLBACK(view_onPopupMenu), @@ -354,6 +355,7 @@ TrgTrackersTreeView *trg_trackers_tree_view_new(TrgTrackersModel * model, priv->client = client; priv->win = win; + trg_tree_view_setup_columns(TRG_TREE_VIEW(obj)); //trg_tree_view_restore_sort(TRG_TREE_VIEW(obj)); return TRG_TRACKERS_TREE_VIEW(obj); diff --git a/src/trg-trackers-tree-view.h b/src/trg-trackers-tree-view.h index a6e61ae..c98a472 100644 --- a/src/trg-trackers-tree-view.h +++ b/src/trg-trackers-tree-view.h @@ -51,10 +51,10 @@ typedef struct { GType trg_trackers_tree_view_get_type(void); TrgTrackersTreeView *trg_trackers_tree_view_new(TrgTrackersModel * model, - trg_client * client, + TrgClient * client, TrgMainWindow * win); void trg_trackers_tree_view_new_connection(TrgTrackersTreeView * tv, - trg_client * tc); + TrgClient * tc); G_END_DECLS #endif /* TRG_TRACKERS_TREE_VIEW_H_ */ diff --git a/src/trg-tree-view.c b/src/trg-tree-view.c index a64b403..75f6674 100644 --- a/src/trg-tree-view.c +++ b/src/trg-tree-view.c @@ -19,9 +19,10 @@ #include <stdlib.h> #include <gtk/gtk.h> -#include <gconf/gconf-client.h> +#include <json-glib/json-glib.h> #include <glib/gi18n.h> +#include "trg-prefs.h" #include "trg-tree-view.h" #include "trg-cell-renderer-speed.h" #include "trg-cell-renderer-size.h" @@ -32,6 +33,11 @@ #include "trg-cell-renderer-priority.h" #include "trg-cell-renderer-numgtzero.h" +enum { + PROP_0, + PROP_PREFS +}; + G_DEFINE_TYPE(TrgTreeView, trg_tree_view, GTK_TYPE_TREE_VIEW) #define TRG_TREE_VIEW_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRG_TYPE_TREE_VIEW, TrgTreeViewPrivate)) @@ -39,11 +45,73 @@ typedef struct _TrgTreeViewPrivate TrgTreeViewPrivate; struct _TrgTreeViewPrivate { GList *columns; + TrgPrefs *prefs; }; +static void +trg_tree_view_get_property(GObject * object, guint property_id, + GValue * value, GParamSpec * pspec) +{ + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); +} + +static void +trg_tree_view_set_property(GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec) +{ + TrgTreeViewPrivate *priv = TRG_TREE_VIEW_GET_PRIVATE(object); + switch (property_id) { + case PROP_PREFS: + priv->prefs = g_value_get_object(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + } +} + +static GObject *trg_tree_view_constructor(GType type, + guint + n_construct_properties, + GObjectConstructParam + * construct_params) +{ + GObject *obj = G_OBJECT_CLASS + (trg_tree_view_parent_class)->constructor(type, + n_construct_properties, + construct_params); + //TrgTreeViewPrivate *priv = TRG_TREE_VIEW_GET_PRIVATE(obj); + + return obj; +} + +static JsonObject* trg_prefs_get_tree_view_props(TrgTreeView *tv) +{ + TrgTreeViewPrivate *priv = TRG_TREE_VIEW_GET_PRIVATE(tv); + JsonObject *root = trg_prefs_get_root(priv->prefs); + const gchar *className = G_OBJECT_TYPE_NAME(tv); + JsonObject *obj; + JsonObject *tvProps = NULL; + + if (!json_object_has_member(root, TRG_PREFS_KEY_TREE_VIEWS)) { + obj = json_object_new(); + json_object_set_object_member(root, TRG_PREFS_KEY_TREE_VIEWS, obj); + } else { + obj = json_object_get_object_member(root, TRG_PREFS_KEY_TREE_VIEWS); + } + + if (!json_object_has_member(obj, className)) { + tvProps = json_object_new(); + json_object_set_object_member(obj, className, tvProps); + } else { + tvProps = json_object_get_object_member(obj, className); + } + + return tvProps; +} + static void trg_tree_view_add_column_after(TrgTreeView * tv, trg_column_description * desc, - gchar ** widths, gint i, + gint64 width, GtkTreeViewColumn * after_col); trg_column_description *trg_tree_view_reg_column(TrgTreeView * tv, @@ -67,7 +135,7 @@ trg_column_description *trg_tree_view_reg_column(TrgTreeView * tv, } static trg_column_description *trg_tree_view_find_column(TrgTreeView * tv, - gchar * id) + const gchar * id) { TrgTreeViewPrivate *priv = TRG_TREE_VIEW_GET_PRIVATE(tv); GList *li; @@ -82,26 +150,6 @@ static trg_column_description *trg_tree_view_find_column(TrgTreeView * tv, return NULL; } -static gchar **trg_gconf_get_csv(TrgTreeView * tv, gchar * key) -{ - gchar **ret = NULL; - GConfClient *gcc = gconf_client_get_default(); - gchar *gconf_key = - g_strdup_printf("/apps/transmission-remote-gtk/%s-%s", - G_OBJECT_TYPE_NAME(tv), key); - gchar *gconf_value = gconf_client_get_string(gcc, gconf_key, NULL); - - if (gconf_value) { - ret = g_strsplit(gconf_value, ",", -1); - g_free(gconf_value); - } - - g_free(gconf_key); - g_object_unref(gcc); - - return ret; -} - static void trg_tree_view_hide_column(GtkWidget * w, GtkTreeViewColumn * col) { @@ -114,9 +162,9 @@ static void trg_tree_view_hide_column(GtkWidget * w, static void trg_tree_view_add_column(TrgTreeView * tv, trg_column_description * desc, - gchar ** widths, gint i) + gint64 width) { - trg_tree_view_add_column_after(tv, desc, widths, i, NULL); + trg_tree_view_add_column_after(tv, desc, width, NULL); } static void trg_tree_view_user_add_column_cb(GtkWidget * w, @@ -126,7 +174,7 @@ static void trg_tree_view_user_add_column_cb(GtkWidget * w, TrgTreeView *tv = TRG_TREE_VIEW(gtk_tree_view_column_get_tree_view(col)); - trg_tree_view_add_column_after(tv, desc, NULL, -1, col); + trg_tree_view_add_column_after(tv, desc, -1, col); } static void @@ -182,7 +230,7 @@ col_onButtonPressed(GtkButton * button, GdkEventButton * event, static void trg_tree_view_add_column_after(TrgTreeView * tv, trg_column_description * desc, - gchar ** widths, gint i, + gint64 width, GtkTreeViewColumn * after_col) { GtkCellRenderer *renderer; @@ -299,16 +347,14 @@ static void trg_tree_view_add_column_after(TrgTreeView * tv, gtk_tree_view_column_set_reorderable(column, TRUE); gtk_tree_view_column_set_sort_column_id(column, desc->model_column); - if (!widths && desc->defaultWidth > 0) { + if (width < 0 && desc->defaultWidth > 0) { gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED); gtk_tree_view_column_set_fixed_width(column, desc->defaultWidth); - } else if (widths && i >= 0) { - gchar *ws = widths[i]; - int w = atoi(ws); + } else if (width > 0) { gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED); - gtk_tree_view_column_set_fixed_width(column, w); + gtk_tree_view_column_set_fixed_width(column, width); } g_object_set_data(G_OBJECT(column), "column-desc", desc); @@ -330,122 +376,100 @@ static void trg_tree_view_add_column_after(TrgTreeView * tv, void trg_tree_view_persist(TrgTreeView * tv) { - GConfClient *gcc = gconf_client_get_default(); + JsonObject *props = trg_prefs_get_tree_view_props(tv); GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(tv)); GList *cols = gtk_tree_view_get_columns(GTK_TREE_VIEW(tv)); - gint n_cols = g_list_length(cols); + + GList *li; gint sort_column_id; GtkSortType sort_type; - const gchar *tree_view_name = G_OBJECT_TYPE_NAME(tv); - gchar *cols_key = - g_strdup_printf("/apps/transmission-remote-gtk/%s-columns", - tree_view_name); - gchar *widths_key = - g_strdup_printf("/apps/transmission-remote-gtk/%s-widths", - tree_view_name); - gchar **cols_v = g_new0(gchar *, n_cols + 1); - gchar **widths_v = g_new0(gchar *, n_cols + 1); - gchar *widths_js, *cols_js; - GList *li; - int i = 0; + + JsonArray *widths, *columns; + if (json_object_has_member(props, TRG_PREFS_KEY_TV_WIDTHS)) + json_object_remove_member(props, TRG_PREFS_KEY_TV_WIDTHS); + + widths = json_array_new(); + json_object_set_array_member(props, TRG_PREFS_KEY_TV_WIDTHS, widths); + + if (json_object_has_member(props, TRG_PREFS_KEY_TV_COLUMNS)) + json_object_remove_member(props, TRG_PREFS_KEY_TV_COLUMNS); + + columns = json_array_new(); + json_object_set_array_member(props, TRG_PREFS_KEY_TV_COLUMNS, columns); for (li = cols; li; li = g_list_next(li)) { GtkTreeViewColumn *col = (GtkTreeViewColumn *) li->data; trg_column_description *desc = g_object_get_data(G_OBJECT(li->data), "column-desc"); - cols_v[i] = desc->id; - widths_v[i] = - g_strdup_printf("%d", gtk_tree_view_column_get_width(col)); - i++; - } - widths_js = g_strjoinv(",", widths_v); - cols_js = g_strjoinv(",", cols_v); - - if (gtk_tree_sortable_get_sort_column_id - (GTK_TREE_SORTABLE(model), &sort_column_id, &sort_type)) { - gchar *sort_col_key = - g_strdup_printf("/apps/transmission-remote-gtk/%s-sort_col", - tree_view_name); - gchar *sort_type_key = - g_strdup_printf("/apps/transmission-remote-gtk/%s-sort_type", - tree_view_name); - gconf_client_set_int(gcc, sort_col_key, sort_column_id, NULL); - gconf_client_set_int(gcc, sort_type_key, (gint) sort_type, NULL); - g_free(sort_type_key); - g_free(sort_col_key); + json_array_add_string_element(columns, desc->id); + json_array_add_int_element(widths, gtk_tree_view_column_get_width(col)); } - gconf_client_set_string(gcc, cols_key, cols_js, NULL); - gconf_client_set_string(gcc, widths_key, widths_js, NULL); - - g_free(cols_key); - g_free(widths_key); - g_free(widths_js); - g_free(cols_js); - g_free(cols_v); - g_strfreev(widths_v); - g_list_free(cols); - g_object_unref(gcc); + gtk_tree_sortable_get_sort_column_id(GTK_TREE_SORTABLE(model), &sort_column_id, &sort_type); + + if (json_object_has_member(props, TRG_PREFS_KEY_TV_SORT_COL)) + json_object_remove_member(props, TRG_PREFS_KEY_TV_SORT_COL); + + if (json_object_has_member(props, TRG_PREFS_KEY_TV_SORT_TYPE)) + json_object_remove_member(props, TRG_PREFS_KEY_TV_SORT_TYPE); + + json_object_set_int_member(props, TRG_PREFS_KEY_TV_SORT_COL, (gint64)sort_column_id); + json_object_set_int_member(props, TRG_PREFS_KEY_TV_SORT_TYPE, (gint64)sort_type); } void trg_tree_view_restore_sort(TrgTreeView * tv) { - GConfClient *gcc = gconf_client_get_default(); + JsonObject *props = trg_prefs_get_tree_view_props(tv); GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(tv)); - gchar *sort_col_key = - g_strdup_printf("/apps/transmission-remote-gtk/%s-sort_col", - G_OBJECT_TYPE_NAME(tv)); - gchar *sort_type_key = - g_strdup_printf("/apps/transmission-remote-gtk/%s-sort_type", - G_OBJECT_TYPE_NAME(tv)); - GConfValue *sort_col_gv = - gconf_client_get_without_default(gcc, sort_col_key, NULL); - GConfValue *sort_type_gv = - gconf_client_get_without_default(gcc, sort_type_key, NULL); - if (sort_col_gv) { - gint sort_col_value = gconf_value_get_int(sort_col_gv); - GtkSortType sort_type_value = GTK_SORT_ASCENDING; - if (sort_type_gv) { - sort_type_value = - (GtkSortType) gconf_value_get_int(sort_type_gv); - gconf_value_free(sort_type_gv); - } - gconf_value_free(sort_col_gv); + + if (json_object_has_member(props, TRG_PREFS_KEY_TV_SORT_COL) && + json_object_has_member(props, TRG_PREFS_KEY_TV_SORT_TYPE)) { + gint64 sort_col = json_object_get_int_member(props, TRG_PREFS_KEY_TV_SORT_COL); + gint64 sort_type = json_object_get_int_member(props, TRG_PREFS_KEY_TV_SORT_TYPE); gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(model), - sort_col_value, - sort_type_value); + sort_col, + (GtkSortType)sort_type); + } - g_free(sort_col_key); - g_free(sort_type_key); - g_object_unref(gcc); +} + +void trg_tree_view_set_prefs(TrgTreeView *tv, TrgPrefs *prefs) +{ + TrgTreeViewPrivate *priv = TRG_TREE_VIEW_GET_PRIVATE(tv); + priv->prefs = prefs; } void trg_tree_view_setup_columns(TrgTreeView * tv) { TrgTreeViewPrivate *priv = TRG_TREE_VIEW_GET_PRIVATE(tv); - gchar **columns = trg_gconf_get_csv(tv, "columns"); - GList *li; - int i; - trg_column_description *desc; + JsonObject *props = trg_prefs_get_tree_view_props(tv); - if (columns) { - gchar **widths = trg_gconf_get_csv(tv, "widths"); - for (i = 0; columns[i]; i++) { - trg_column_description *desc = - trg_tree_view_find_column(tv, columns[i]); - if (desc) - trg_tree_view_add_column(tv, desc, widths, i); - } - g_strfreev(columns); - if (widths) - g_strfreev(widths); - } else { + if (!json_object_has_member(props, TRG_PREFS_KEY_TV_COLUMNS) || + !json_object_has_member(props, TRG_PREFS_KEY_TV_WIDTHS)) { + GList *li; for (li = priv->columns; li; li = g_list_next(li)) { - desc = (trg_column_description *) li->data; + trg_column_description *desc = (trg_column_description *) li->data; if (desc && !(desc->flags & TRG_COLUMN_EXTRA)) - trg_tree_view_add_column(tv, desc, NULL, -1); + trg_tree_view_add_column(tv, desc, -1); } + return; + } + + GList *columns = json_array_get_elements(json_object_get_array_member(props, TRG_PREFS_KEY_TV_COLUMNS)); + GList *widths = json_array_get_elements(json_object_get_array_member(props, TRG_PREFS_KEY_TV_WIDTHS)); + + GList *wli = widths; + GList *cli = columns; + + for (; cli; cli = g_list_next(cli)) { + trg_column_description *desc = + trg_tree_view_find_column(tv, json_node_get_string((JsonNode*)cli->data)); + if (desc) { + gint64 width = json_node_get_int((JsonNode*)wli->data); + trg_tree_view_add_column(tv, desc, width); + } + wli = g_list_next(wli); } } @@ -469,9 +493,27 @@ GList *trg_tree_view_get_selected_refs_list(GtkTreeView * tv) } static void -trg_tree_view_class_init(TrgTreeViewClass * klass G_GNUC_UNUSED) +trg_tree_view_class_init(TrgTreeViewClass * klass) { + GObjectClass *object_class = G_OBJECT_CLASS(klass); + g_type_class_add_private(klass, sizeof(TrgTreeViewPrivate)); + + object_class->get_property = trg_tree_view_get_property; + object_class->set_property = trg_tree_view_set_property; + object_class->constructor = trg_tree_view_constructor; + + g_object_class_install_property(object_class, + PROP_PREFS, + g_param_spec_object + ("prefs", "Trg Prefs", + "Trg Prefs", + TRG_TYPE_PREFS, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_NAME | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB)); } static void trg_tree_view_init(TrgTreeView * tv) diff --git a/src/trg-tree-view.h b/src/trg-tree-view.h index 027f0fd..3a4e4ba 100644 --- a/src/trg-tree-view.h +++ b/src/trg-tree-view.h @@ -22,6 +22,8 @@ #include <glib-object.h> +#include "trg-prefs.h" + G_BEGIN_DECLS #define TRG_TYPE_TREE_VIEW trg_tree_view_get_type() #define TRG_TREE_VIEW(obj) \ @@ -85,6 +87,7 @@ trg_column_description *trg_tree_view_reg_column(TrgTreeView * tv, gchar * header, gchar * id, gint flags); void trg_tree_view_setup_columns(TrgTreeView * tv); +void trg_tree_view_set_prefs(TrgTreeView *tv, TrgPrefs *prefs); void trg_tree_view_persist(TrgTreeView * tv); void trg_tree_view_restore_sort(TrgTreeView * tv); @@ -23,7 +23,6 @@ #include <math.h> #include <string.h> -#include <gconf/gconf-client.h> #include <glib/gi18n.h> #include <glib-object.h> #include <curl/curl.h> @@ -86,46 +85,6 @@ void trg_error_dialog(GtkWindow * parent, int status, g_free((gpointer) msg); } -gint gconf_client_get_int_or_default(GConfClient * gconf, - const gchar * key, int deflt, - GError ** error) -{ - GConfValue *value = - gconf_client_get_without_default(gconf, key, error); - gint ret; - if (value) { - ret = gconf_value_get_int(value); - gconf_value_free(value); - } else { - ret = deflt; - } - return ret; -} - -gboolean g_slist_str_set_add(GSList ** list, const gchar * string) -{ - GSList *li; - for (li = *list; li; li = g_slist_next(li)) - if (!g_strcmp0((gchar *) li->data, string)) - return FALSE; - - *list = g_slist_insert_sorted(*list, g_strdup(string), (GCompareFunc)g_strcmp0); - return TRUE; -} - -gboolean gconf_client_get_bool_or_true(GConfClient * gconf, gchar * key) -{ - GConfValue *value = gconf_client_get_without_default(gconf, key, NULL); - gboolean ret = TRUE; - - if (value) { - ret = gconf_value_get_bool(value); - gconf_value_free(value); - } - - return ret; -} - const gchar *make_error_message(JsonObject * response, int status) { if (status == FAIL_JSON_DECODE) { @@ -23,7 +23,6 @@ #define UTIL_H_ #include <gtk/gtk.h> -#include <gconf/gconf-client.h> #include <glib-object.h> #include <json-glib/json-glib.h> @@ -41,15 +40,9 @@ #define GIGABYTE_FACTOR ( 1024.0 * 1024.0 * 1024.0 ) void add_file_id_to_array(JsonObject * args, gchar * key, gint index); -gboolean g_slist_str_set_add(GSList ** list, const gchar * string); void g_str_slist_free(GSList * list); GRegex *trg_uri_host_regex_new(void); gchar *trg_gregex_get_first(GRegex * rx, const gchar * uri); -gboolean gconf_client_get_bool_or_true(GConfClient * gconf, gchar * key); -gint gconf_client_get_int_or_default(GConfClient * gconf, - const gchar * key, int deflt, - GError ** error); - void response_unref(JsonObject * response); const gchar *make_error_message(JsonObject * response, int status); void trg_error_dialog(GtkWindow * parent, int status, |