diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/json.c | 2 | ||||
-rw-r--r-- | src/main.c | 9 | ||||
-rw-r--r-- | src/remote-exec.c | 10 | ||||
-rw-r--r-- | src/requests.c | 4 | ||||
-rw-r--r-- | src/session-get.c | 2 | ||||
-rw-r--r-- | src/torrent.c | 2 | ||||
-rw-r--r-- | src/trg-client.c | 16 | ||||
-rw-r--r-- | src/trg-client.h | 27 | ||||
-rw-r--r-- | src/trg-destination-combo.c | 13 | ||||
-rw-r--r-- | src/trg-json-widgets.c | 8 | ||||
-rw-r--r-- | src/trg-main-window.c | 2 | ||||
-rw-r--r-- | src/trg-model.c | 5 | ||||
-rw-r--r-- | src/trg-persistent-tree-view.c | 5 | ||||
-rw-r--r-- | src/trg-preferences-dialog.c | 7 | ||||
-rw-r--r-- | src/trg-prefs.c | 8 | ||||
-rw-r--r-- | src/trg-remote-prefs-dialog.c | 9 | ||||
-rw-r--r-- | src/trg-sortable-filtered-model.c | 26 | ||||
-rw-r--r-- | src/trg-status-bar.c | 11 | ||||
-rw-r--r-- | src/trg-torrent-graph.c | 4 | ||||
-rw-r--r-- | src/trg-torrent-model.c | 26 | ||||
-rw-r--r-- | src/trg-torrent-props-dialog.c | 13 | ||||
-rw-r--r-- | src/trg-tree-view.c | 11 |
22 files changed, 186 insertions, 34 deletions
@@ -27,6 +27,8 @@ #include "requests.h" #include "json.h" +/* JSON helper functions */ + gchar *trg_serialize(JsonNode * req) { JsonGenerator *generator; @@ -40,6 +40,15 @@ #include "trg-client.h" #include "util.h" +/* The file with the main() function. It converts arguments into a NULL terminated + * array, with relative paths converted to absolute paths. + * + * Much of the code here is to optionally handle passing torrent files/URLs to + * a first instance. UNIX can use libunique (should alternatively use + * GApplication for GNOME3). Windows uses the mailslot feature in the + * native Win32 API, so there is no dependency on dbus etc. + */ + #define TRG_LIBUNIQUE_DOMAIN "uk.org.eth0.trg" #define TRG_MAILSLOT_NAME "\\\\.\\mailslot\\TransmissionRemoteGTK" //Name given to the Mailslot #define MAILSLOT_BUFFER_SIZE 1024*32 diff --git a/src/remote-exec.c b/src/remote-exec.c index 30627b2..c3e1a74 100644 --- a/src/remote-exec.c +++ b/src/remote-exec.c @@ -27,6 +27,16 @@ #include "protocol-constants.h" #include "torrent.h" +/* A few functions used to build local commands, otherwise known as actions. + * + * The functionality from a user perspective is documented in the wiki. + * The code below really just uses GRegex to replace variable identifier + * with the values inside the connected profile, the session, or the first selected + * torrent (in that order of precedence). A field seperator I call a repeater + * can be appended to a variable in square brackets, like %{id}[,] to + * cause it to be repeated for each selection. + */ + static const char json_exceptions[] = { 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, diff --git a/src/requests.c b/src/requests.c index 380c46a..0e17fb3 100644 --- a/src/requests.c +++ b/src/requests.c @@ -29,6 +29,10 @@ #include "util.h" #include "requests.h" +/* A bunch of functions for creating the various requests, in the form of a + * JsonNode ready for dispatch. + */ + static JsonNode *base_request(gchar * method); JsonNode *generic_request(gchar * method, JsonArray * ids) diff --git a/src/session-get.c b/src/session-get.c index aec8e74..4bb37b2 100644 --- a/src/session-get.c +++ b/src/session-get.c @@ -24,6 +24,8 @@ #include "protocol-constants.h" #include "session-get.h" +/* Just some functions to get fields out of a session-get response. */ + const gchar *session_get_version_string(JsonObject *s) { return json_object_get_string_member(s, SGET_VERSION); diff --git a/src/torrent.c b/src/torrent.c index c26defc..10f2dde 100644 --- a/src/torrent.c +++ b/src/torrent.c @@ -27,6 +27,8 @@ #include "protocol-constants.h" #include "util.h" +/* Just some functions to get fields out of the torrent object. */ + JsonArray *torrent_get_peers(JsonObject * t) { g_assert(json_object_get_array_member(t, FIELD_PEERS)); diff --git a/src/trg-client.c b/src/trg-client.c index 2f42d99..c25f166 100644 --- a/src/trg-client.c +++ b/src/trg-client.c @@ -37,6 +37,21 @@ #include "util.h" #include "trg-client.h" +/* This class manages/does quite a few things, and is passed around a lot. It: + * + * 1) Holds/inits the single TrgPrefs object for managing configuration. + * 2) Manages a thread pool for making requests + * (each thread has its own CURL client in thread local storage) + * 3) Holds current connection details needed by CURL clients. + * (session ID, username, password, URL, ssl, proxy) + * 4) Holds a hash table for looking up a torrent by its ID. + * 5) Dispatches synchronous/asyncrhonous requests and tracks failures. + * 6) Holds connection state, an update serial, and provides signals for + * connect/disconnect. + * 7) Provides a mutex for locking updates. + * 8) Holds the latest session object sent in a session-get response. + */ + G_DEFINE_TYPE (TrgClient, trg_client, G_TYPE_OBJECT) enum { @@ -497,6 +512,7 @@ trg_tls *trg_tls_new(TrgClient *tc) tls->curl = curl_easy_init(); curl_easy_setopt(tls->curl, CURLOPT_USERAGENT, PACKAGE_NAME); curl_easy_setopt(tls->curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + curl_easy_setopt(tls->curl, CURLOPT_TIMEOUT, 20); curl_easy_setopt(tls->curl, CURLOPT_WRITEFUNCTION, &http_receive_callback); curl_easy_setopt(tls->curl, CURLOPT_HEADERFUNCTION, &header_callback); diff --git a/src/trg-client.h b/src/trg-client.h index cf3e04f..31a9267 100644 --- a/src/trg-client.h +++ b/src/trg-client.h @@ -22,6 +22,19 @@ #ifndef _TRG_CLIENT_H_ #define _TRG_CLIENT_H_ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <curl/curl.h> +#include <curl/easy.h> + +#include <json-glib/json-glib.h> +#include <glib-object.h> + +#include "trg-prefs.h" +#include "session-get.h" + #define TRANSMISSION_MIN_SUPPORTED 2.0 #define X_TRANSMISSION_SESSION_ID_HEADER_PREFIX "X-Transmission-Session-Id: " #define TRG_MAX_RETRIES 3 @@ -37,19 +50,6 @@ #define TRG_NO_HOSTNAME_SET -2 #define SESSION_UPDATE_DIVISOR 10 -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <curl/curl.h> -#include <curl/easy.h> - -#include <json-glib/json-glib.h> -#include <glib-object.h> - -#include "trg-prefs.h" -#include "session-get.h" - #define HTTP_URI_PREFIX "http" #define HTTPS_URI_PREFIX "https" #define HTTP_OK 200 @@ -59,7 +59,6 @@ #define FAIL_RESPONSE_UNSUCCESSFUL -3 #define DISPATCH_POOL_SIZE 3 - typedef struct { int status; int size; diff --git a/src/trg-destination-combo.c b/src/trg-destination-combo.c index e30b747..11f5085 100644 --- a/src/trg-destination-combo.c +++ b/src/trg-destination-combo.c @@ -119,19 +119,6 @@ void trg_destination_combo_save_selection(TrgDestinationCombo *combo_box) } } -/*static void trg_destination_combo_entry_changed(GtkEntry *entry, - gpointer user_data) { - GtkComboBox *combo = GTK_COMBO_BOX(user_data); - GtkTreeIter iter; - - if (gtk_combo_box_get_active_iter(combo, &iter)) { - GtkTreeModel *model = gtk_combo_box_get_model(combo); - const gchar *text = gtk_entry_get_text(entry); - gtk_list_store_set(GTK_LIST_STORE(model), &iter, DEST_COLUMN_DIR, text, - DEST_COLUMN_LABEL, text, -1); - } - }*/ - static void gtk_combo_box_entry_active_changed(GtkComboBox *combo_box, gpointer user_data) { GtkTreeModel *model; diff --git a/src/trg-json-widgets.c b/src/trg-json-widgets.c index 2409ba1..b412c12 100644 --- a/src/trg-json-widgets.c +++ b/src/trg-json-widgets.c @@ -23,6 +23,14 @@ #include "trg-json-widgets.h" #include "util.h" +/* Functions for creating widgets that load/save their state from/to a JSON + * object. This is used by the torrent properties and remote settings dialogs. + * The pattern here is farily similar to that used in local configuration, + * the widget creation functions take a list as an argument, which gets a + * trg_json_widget_desc appended to it. This contains the key, and the function + * pointers for load/save. + */ + void trg_json_widgets_save(GList *list, JsonObject *out) { GList *li; diff --git a/src/trg-main-window.c b/src/trg-main-window.c index 3147170..8b71a8a 100644 --- a/src/trg-main-window.c +++ b/src/trg-main-window.c @@ -76,6 +76,8 @@ #include "trg-remote-prefs-dialog.h" #include "trg-preferences-dialog.h" +/* The rather large main window class, which glues everything together. */ + static void update_selected_torrent_notebook(TrgMainWindow * win, gint mode, gint64 id); #ifdef HAVE_LIBNOTIFY diff --git a/src/trg-model.c b/src/trg-model.c index 5796507..e10c974 100644 --- a/src/trg-model.c +++ b/src/trg-model.c @@ -21,6 +21,11 @@ #include <gtk/gtk.h> #include <json-glib/json-glib.h> +/* An extension of GtkListStore which provides some functions for looking up + * an entry by ID. Also for removing entries which have an old update serial, + * which means it needs removing. + */ + struct trg_model_remove_removed_foreachfunc_args { gint64 currentSerial; gint serial_column; diff --git a/src/trg-persistent-tree-view.c b/src/trg-persistent-tree-view.c index 9eff200..a8ce65e 100644 --- a/src/trg-persistent-tree-view.c +++ b/src/trg-persistent-tree-view.c @@ -24,6 +24,11 @@ #include "trg-preferences-dialog.h" #include "util.h" +/* A config TreeView which can save/restore simple data into the TrgConf backend. + * It's not actually a GtkTreeView, it's a GtKVBox which contains the buttons + * to add/remove entries as well as the TreeView. + */ + G_DEFINE_TYPE (TrgPersistentTreeView, trg_persistent_tree_view, GTK_TYPE_VBOX) #define GET_PRIVATE(o) \ diff --git a/src/trg-preferences-dialog.c b/src/trg-preferences-dialog.c index cd92688..8a4c810 100644 --- a/src/trg-preferences-dialog.c +++ b/src/trg-preferences-dialog.c @@ -35,6 +35,13 @@ #include "trg-prefs.h" #include "util.h" +/* UI frontend to modify configurables stored in TrgConf. + * To avoid lots of repetitive code, use our own functions for creating widgets + * which also create a trg_pref_widget_desc structure and add it to a list. + * This contains details of the config key, config flags etc, and a function + * pointer for a save/display function. These are all called on save/load. + */ + #define TRG_PREFERENCES_DIALOG_GET_PRIVATE(object) \ (G_TYPE_INSTANCE_GET_PRIVATE ((object), TRG_TYPE_PREFERENCES_DIALOG, TrgPreferencesDialogPrivate)) diff --git a/src/trg-prefs.c b/src/trg-prefs.c index ae3996f..33d8f39 100644 --- a/src/trg-prefs.c +++ b/src/trg-prefs.c @@ -28,6 +28,14 @@ #include "trg-client.h" #include "trg-prefs.h" +/* I replaced GConf with this custom configuration backend for a few reasons. + * 1) Better windows support. No dependency on DBus. + * 2) We're including a JSON parser/writer anyway. + * 3) The GConf API is pretty verbose sometimes, working with lists is awkward. + * 4) Easily switch between profiles, and scope config to either profiles or global. + * 5) Transparently use configurables from the current connection, not current profile. + */ + G_DEFINE_TYPE (TrgPrefs, trg_prefs, G_TYPE_OBJECT) #define GET_PRIVATE(o) \ diff --git a/src/trg-remote-prefs-dialog.c b/src/trg-remote-prefs-dialog.c index 8f869dd..b9a059e 100644 --- a/src/trg-remote-prefs-dialog.c +++ b/src/trg-remote-prefs-dialog.c @@ -31,6 +31,15 @@ #include "trg-json-widgets.h" #include "session-get.h" +/* Using the widget creation functions in trg-json-widgets.c, load remote + * preferences from the latest session object held by TrgClient. + * If the user clicks OK, use trg-json-widgets to build up a request object + * and send that in a session-set request. + * + * The on_session_set callback should cause that session object to be refreshed + * as soon as the set is complete. + */ + G_DEFINE_TYPE(TrgRemotePrefsDialog, trg_remote_prefs_dialog, GTK_TYPE_DIALOG) #define TRG_REMOTE_PREFS_DIALOG_GET_PRIVATE(o) \ diff --git a/src/trg-sortable-filtered-model.c b/src/trg-sortable-filtered-model.c index c7b3418..198a723 100644 --- a/src/trg-sortable-filtered-model.c +++ b/src/trg-sortable-filtered-model.c @@ -21,10 +21,17 @@ #include "trg-sortable-filtered-model.h" +/* This class extends GtkTreeModelFilter, so it can implement the + * GtkTreeSortable interface. All of the sortable functions are passed on to + * a child GtkTreeModelSort. Also proxy the sort-column-changed signal + * so that a TreeViewColumn can track changes for indicators. + */ + static void trg_sortable_filtered_model_tree_sortable_init(GtkTreeSortableIface *iface); /* TreeSortable interface */ +static GtkTreeSortable *trg_sortable_filtered_model_get_real_sortable(GtkTreeSortable *sortable); static gboolean trg_sortable_filtered_model_sort_get_sort_column_id( GtkTreeSortable *sortable, gint *sort_column_id, GtkSortType *order); static void trg_sortable_filtered_model_sort_set_sort_column_id( @@ -37,6 +44,8 @@ static void trg_sortable_filtered_model_sort_set_default_sort_func( GDestroyNotify destroy); static gboolean trg_sortable_filtered_model_sort_has_default_sort_func( GtkTreeSortable *sortable); +static void trg_sortable_filtered_model_sort_column_changed(GtkTreeSortable *realSortable, + GtkTreeSortable *fakeSortable); G_DEFINE_TYPE_WITH_CODE( TrgSortableFilteredModel, @@ -64,7 +73,7 @@ static void trg_sortable_filtered_model_tree_sortable_init( trg_sortable_filtered_model_sort_has_default_sort_func; } -static void trg_sortable_filtered_model_sort_column_changed(GtkTreeSortable *realSortable, +static void trg_sortable_filtered_model_sort_column_changed(GtkTreeSortable *realSortable G_GNUC_UNUSED, GtkTreeSortable *fakeSortable) { g_signal_emit_by_name (fakeSortable, "sort-column-changed"); @@ -89,16 +98,21 @@ trg_sortable_filtered_model_new (GtkTreeSortable *child_model, return GTK_TREE_MODEL(obj); } +static GtkTreeSortable *trg_sortable_filtered_model_get_real_sortable(GtkTreeSortable *sortable) +{ + return GTK_TREE_SORTABLE(gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(sortable))); +} + static gboolean trg_sortable_filtered_model_sort_get_sort_column_id( GtkTreeSortable *sortable, gint *sort_column_id, GtkSortType *order) { - GtkTreeSortable *realSortable = GTK_TREE_SORTABLE(gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(sortable))); + GtkTreeSortable *realSortable = trg_sortable_filtered_model_get_real_sortable(sortable); return gtk_tree_sortable_get_sort_column_id(realSortable, sort_column_id, order); } static void trg_sortable_filtered_model_sort_set_sort_column_id( GtkTreeSortable *sortable, gint sort_column_id, GtkSortType order) { - GtkTreeSortable *realSortable = GTK_TREE_SORTABLE(gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(sortable))); + GtkTreeSortable *realSortable = trg_sortable_filtered_model_get_real_sortable(sortable); gtk_tree_sortable_set_sort_column_id(realSortable, sort_column_id, order); } @@ -106,7 +120,7 @@ static void trg_sortable_filtered_model_sort_set_sort_func( GtkTreeSortable *sortable, gint sort_column_id, GtkTreeIterCompareFunc func, gpointer data, GDestroyNotify destroy) { - GtkTreeSortable *realSortable = GTK_TREE_SORTABLE(gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(sortable))); + GtkTreeSortable *realSortable = trg_sortable_filtered_model_get_real_sortable(sortable); gtk_tree_sortable_set_sort_func(realSortable, sort_column_id, func, data, destroy); } @@ -114,13 +128,13 @@ static void trg_sortable_filtered_model_sort_set_default_sort_func( GtkTreeSortable *sortable, GtkTreeIterCompareFunc func, gpointer data, GDestroyNotify destroy) { - GtkTreeSortable *realSortable = GTK_TREE_SORTABLE(gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(sortable))); + GtkTreeSortable *realSortable = trg_sortable_filtered_model_get_real_sortable(sortable); gtk_tree_sortable_set_default_sort_func(realSortable, func, data, destroy); } static gboolean trg_sortable_filtered_model_sort_has_default_sort_func( GtkTreeSortable *sortable) { - GtkTreeSortable *realSortable = GTK_TREE_SORTABLE(gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(sortable))); + GtkTreeSortable *realSortable = trg_sortable_filtered_model_get_real_sortable(sortable); return gtk_tree_sortable_has_default_sort_func(realSortable); } diff --git a/src/trg-status-bar.c b/src/trg-status-bar.c index cb28778..8e5725e 100644 --- a/src/trg-status-bar.c +++ b/src/trg-status-bar.c @@ -26,6 +26,17 @@ #include "session-get.h" #include "util.h" +/* A subclass of GtkHBox which contains a status label on the left. + * Free space indicator on left-right. + * Speed (including limits if in use) label on right-right. + * + * Status and speed labels should be updated on every torrent-get using + * trg_status_bar_update. Free space is updated with trg_status_bar_session_update. + * + * There's a signal in TrgClient for session updates, connected into the + * main window, which calls this. Session updates happen every 10 torrent-get updates. + */ + G_DEFINE_TYPE(TrgStatusBar, trg_status_bar, GTK_TYPE_HBOX) #define TRG_STATUS_BAR_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRG_TYPE_STATUS_BAR, TrgStatusBarPrivate)) diff --git a/src/trg-torrent-graph.c b/src/trg-torrent-graph.c index 6c189b9..99c5dad 100644 --- a/src/trg-torrent-graph.c +++ b/src/trg-torrent-graph.c @@ -21,6 +21,10 @@ * This graph drawing code was taken from gnome-system-monitor (load-graph.cpp) * Converted the class from C++ to GObject, substituted out some STL (C++) * functions, and removed the unecessary parts for memory/cpu. + * + * Would be nice if it supported configurable timespans. This could possibly + * be replaced with ubergraph, which is a graphing widget for GTK (C) also based + * on this widget but with some improvements I didn't do. */ #include <math.h> diff --git a/src/trg-torrent-model.c b/src/trg-torrent-model.c index b5d7d4c..f367e77 100644 --- a/src/trg-torrent-model.c +++ b/src/trg-torrent-model.c @@ -30,6 +30,27 @@ #include "trg-model.h" #include "util.h" +/* An extension of TrgModel (which is an extension of GtkListStore) which + * updates from a JSON torrent-get response. It handles a number of different + * update modes. + * 1) The first update. + * 2) A full update. + * 3) An active-only update. + * 4) Individual torrent updates. + * + * Other stuff it does. + * 1) Populates a stats struct with speeds/state counts as it works through the + * response. + * 2) Emits signals if something is added or removed. This is used by the state + * selector so it doesn't have to refresh itself on every update. + * 3) Added or completed signals, for libnotify notifications. + * 4) Maintains the torrent hash table (by ID). + * (and provide a lookup function which outputs an iter and/or JSON object.) + * 5) If the download directory is new/changed, create a short version if there + * is one (duplicate it not) for the state selector to filter/populate against. + * 6) Shorten the tracker announce URL. + */ + enum { TMODEL_TORRENT_COMPLETED, TMODEL_TORRENT_ADDED, @@ -486,6 +507,7 @@ static inline void update_torrent_iter(TrgTorrentModel * model, TrgClient *tc, if (firstTrackerHost) g_free(firstTrackerHost); + if (peerSources) g_free(peerSources); @@ -512,8 +534,10 @@ gboolean trg_model_find_removed_foreachfunc(GtkTreeModel * model, GtkTreePath * path G_GNUC_UNUSED, GtkTreeIter * iter, gpointer gdata) { struct TrgModelRemoveData *args = (struct TrgModelRemoveData *) gdata; gint64 rowSerial; + gtk_tree_model_get(model, iter, TORRENT_COLUMN_UPDATESERIAL, &rowSerial, -1); + if (rowSerial != args->currentSerial) { gint64 *id = g_new(gint64, 1); gtk_tree_model_get(model, iter, TORRENT_COLUMN_ID, id, -1); @@ -526,9 +550,9 @@ gboolean trg_model_find_removed_foreachfunc(GtkTreeModel * model, GList *trg_torrent_model_find_removed(GtkTreeModel * model, gint64 currentSerial) { struct TrgModelRemoveData args; - args.toRemove = NULL; args.currentSerial = currentSerial; + gtk_tree_model_foreach(GTK_TREE_MODEL(model), trg_model_find_removed_foreachfunc, &args); diff --git a/src/trg-torrent-props-dialog.c b/src/trg-torrent-props-dialog.c index c1fe493..8f650bf 100644 --- a/src/trg-torrent-props-dialog.c +++ b/src/trg-torrent-props-dialog.c @@ -34,6 +34,18 @@ #include "trg-main-window.h" #include "hig.h" +/* Pretty similar to remote preferences, also using the widget creation functions + * in trg-json-widgets.c. The torrent tree view is passed into here, which this + * gets the selection from. If there are multiple selections, use the first to + * populate the fields. + * + * Build the JSON array of torrent IDs when the dialog is created, in case the + * selection changes before clicking OK. + * + * When the user clicks OK, use trg-json-widgets to populate an object with the + * values and then send it with the IDs. + */ + G_DEFINE_TYPE(TrgTorrentPropsDialog, trg_torrent_props_dialog, GTK_TYPE_DIALOG) @@ -115,6 +127,7 @@ trg_torrent_props_response_cb(GtkDialog * dlg, gint res_id, if (res_id != GTK_RESPONSE_OK) { gtk_widget_destroy(GTK_WIDGET(dlg)); + json_array_unref(priv->targetIds); return; } diff --git a/src/trg-tree-view.c b/src/trg-tree-view.c index 069464f..4f091ea 100644 --- a/src/trg-tree-view.c +++ b/src/trg-tree-view.c @@ -32,6 +32,17 @@ #include "trg-cell-renderer-priority.h" #include "trg-cell-renderer-numgteqthan.h" +/* A subclass of GtkTreeView which allows the user to change column visibility + * by right clicking on any column for a menu to hide the clicked column, or + * insert any hidden column after. + * + * This class persists these choices to TrgConf, and restores them when it is + * initialised. Column widths are also saved/restored. + * + * All the columns must be preregistered so it knows what model column, + * renderers etc to use if it should be created, and what columns are available. + */ + enum { PROP_0, PROP_PREFS }; |