diff options
Diffstat (limited to 'src/trg-state-selector.c')
-rw-r--r-- | src/trg-state-selector.c | 251 |
1 files changed, 205 insertions, 46 deletions
diff --git a/src/trg-state-selector.c b/src/trg-state-selector.c index f20a407..b6447ee 100644 --- a/src/trg-state-selector.c +++ b/src/trg-state-selector.c @@ -25,6 +25,8 @@ #include "torrent.h" #include "trg-state-selector.h" #include "util.h" +#include "trg-preferences.h" +#include "trg-client.h" enum { SELECTOR_STATE_CHANGED, @@ -40,11 +42,15 @@ typedef struct _TrgStateSelectorPrivate TrgStateSelectorPrivate; struct _TrgStateSelectorPrivate { guint flag; + gboolean showDirs; + gboolean showTrackers; + trg_client *client; GHashTable *trackers; + GHashTable *directories; GRegex *urlHostRegex; }; -GRegex *trg_state_selector_get_url_host_regex(TrgStateSelector *s) +GRegex *trg_state_selector_get_url_host_regex(TrgStateSelector * s) { TrgStateSelectorPrivate *priv = TRG_STATE_SELECTOR_GET_PRIVATE(s); return priv->urlHostRegex; @@ -95,7 +101,8 @@ static void state_selection_changed(GtkTreeSelection * selection, signals[SELECTOR_STATE_CHANGED], 0, priv->flag); } -static GtkTreeRowReference *quick_tree_ref_new(GtkTreeModel *model, GtkTreeIter *iter) +static GtkTreeRowReference *quick_tree_ref_new(GtkTreeModel * model, + GtkTreeIter * iter) { GtkTreePath *path = gtk_tree_model_get_path(model, iter); GtkTreeRowReference *rr = gtk_tree_row_reference_new(model, path); @@ -108,10 +115,12 @@ struct cruft_remove_args { gint64 serial; }; -static gboolean trg_state_selector_remove_cruft(gpointer key, gpointer value, gpointer data) +static gboolean trg_state_selector_remove_cruft(gpointer key, + gpointer value, + gpointer data) { - struct cruft_remove_args *args = (struct cruft_remove_args*)data; - GtkTreeRowReference *rr = (GtkTreeRowReference*)value; + struct cruft_remove_args *args = (struct cruft_remove_args *) data; + GtkTreeRowReference *rr = (GtkTreeRowReference *) value; GtkTreeModel *model = gtk_tree_row_reference_get_model(rr); GtkTreePath *path = gtk_tree_row_reference_get_path(rr); gboolean remove; @@ -120,7 +129,8 @@ static gboolean trg_state_selector_remove_cruft(gpointer key, gpointer value, gp gint64 currentSerial; gtk_tree_model_get_iter(model, &iter, path); - gtk_tree_model_get(model, &iter, STATE_SELECTOR_SERIAL, ¤tSerial, -1); + gtk_tree_model_get(model, &iter, STATE_SELECTOR_SERIAL, ¤tSerial, + -1); remove = (args->serial != currentSerial); @@ -129,7 +139,7 @@ static gboolean trg_state_selector_remove_cruft(gpointer key, gpointer value, gp return remove; } -gchar *trg_state_selector_get_selected_text(TrgStateSelector *s) +gchar *trg_state_selector_get_selected_text(TrgStateSelector * s) { GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(s)); GtkTreeModel *model; @@ -142,55 +152,177 @@ gchar *trg_state_selector_get_selected_text(TrgStateSelector *s) return name; } -void trg_state_selector_update_trackers(TrgStateSelector *s, JsonArray *torrents, gint64 serial) +static void trg_state_selector_update_serial(GtkTreeModel * model, + GtkTreeRowReference * rr, + gint64 serial) { - TrgStateSelectorPrivate *priv = TRG_STATE_SELECTOR_GET_PRIVATE(s); - GtkTreeModel *model; GtkTreeIter iter; - int i, j; - struct cruft_remove_args cruft; + GtkTreePath *path = gtk_tree_row_reference_get_path(rr); + gtk_tree_model_get_iter(model, &iter, path); + gtk_list_store_set(GTK_LIST_STORE(model), &iter, + STATE_SELECTOR_SERIAL, serial, -1); + gtk_tree_path_free(path); +} - model = gtk_tree_view_get_model(GTK_TREE_VIEW(s)); +static void refresh_statelist_cb(GtkWidget * w, gpointer data) +{ + trg_state_selector_update(TRG_STATE_SELECTOR(data)); +} - for (i = 0; i < json_array_get_length(torrents); i++) { - JsonObject *t = json_array_get_object_element(torrents, i); - JsonArray *trackers = torrent_get_trackers(t); +static void +view_popup_menu(GtkWidget * treeview, GdkEventButton * event, + gpointer data G_GNUC_UNUSED) +{ + GtkWidget *menu, *item; - for (j = 0; j < json_array_get_length(trackers); j++) { - JsonObject *tracker = json_array_get_object_element(trackers, j); - const gchar *announceUrl = tracker_get_announce(tracker); - gchar *announceHost = trg_uri_host_extract(priv->urlHostRegex, announceUrl); - gpointer result; + menu = gtk_menu_new(); - if (!announceHost) - continue; + item = gtk_image_menu_item_new_with_label(GTK_STOCK_REFRESH); + gtk_image_menu_item_set_use_stock(GTK_IMAGE_MENU_ITEM(item), TRUE); + gtk_image_menu_item_set_always_show_image(GTK_IMAGE_MENU_ITEM + (item), TRUE); + g_signal_connect(item, "activate", G_CALLBACK(refresh_statelist_cb), + treeview); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - result = g_hash_table_lookup(priv->trackers, announceHost); + gtk_widget_show_all(menu); - if (result) - { - GtkTreeRowReference *rr = (GtkTreeRowReference*)result; - GtkTreePath *path = gtk_tree_row_reference_get_path(rr); - gtk_tree_model_get_iter(model, &iter, path); - gtk_list_store_set(GTK_LIST_STORE(model), &iter, - STATE_SELECTOR_SERIAL, serial, -1); - gtk_tree_path_free(path); + gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, + (event != NULL) ? event->button : 0, + gdk_event_get_time((GdkEvent *) event)); +} + +static gboolean view_onPopupMenu(GtkWidget * treeview, gpointer userdata) +{ + view_popup_menu(treeview, NULL, userdata); + return TRUE; +} + +static gboolean +view_onButtonPressed(GtkWidget * treeview, GdkEventButton * event, + gpointer userdata) +{ + if (event->type == GDK_BUTTON_PRESS && event->button == 3) { + view_popup_menu(treeview, event, userdata); + return TRUE; + } + + return FALSE; +} + +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; + GtkTreeIter iter; + int i, j; + struct cruft_remove_args cruft; + + for (i = 0; i < json_array_get_length(client->torrents); i++) { + JsonObject *t = json_array_get_object_element(client->torrents, i); + gpointer result; + + if (priv->showTrackers) { + JsonArray *trackers = torrent_get_trackers(t); + + for (j = 0; j < json_array_get_length(trackers); j++) { + JsonObject *tracker = + json_array_get_object_element(trackers, j); + const gchar *announceUrl = tracker_get_announce(tracker); + gchar *announceHost = + trg_gregex_get_first(priv->urlHostRegex, announceUrl); + + if (!announceHost) + continue; + + result = g_hash_table_lookup(priv->trackers, announceHost); + + if (result) { + trg_state_selector_update_serial(model, + (GtkTreeRowReference + *) + result, + client->updateSerial); + } else { + gtk_list_store_insert(GTK_LIST_STORE(model), &iter, + 9 + + g_hash_table_size(priv-> + trackers)); + gtk_list_store_set(GTK_LIST_STORE(model), &iter, + STATE_SELECTOR_ICON, + GTK_STOCK_NETWORK, + STATE_SELECTOR_NAME, announceHost, + STATE_SELECTOR_SERIAL, + client->updateSerial, + STATE_SELECTOR_BIT, + FILTER_FLAG_TRACKER, -1); + g_hash_table_insert(priv->trackers, announceHost, + quick_tree_ref_new(model, &iter)); + } + } + } + + if (priv->showDirs) { + const gchar *dir = torrent_get_download_dir(t); + result = g_hash_table_lookup(priv->directories, dir); + if (result) { + trg_state_selector_update_serial(model, + (GtkTreeRowReference *) + result, + client->updateSerial); } else { gtk_list_store_append(GTK_LIST_STORE(model), &iter); gtk_list_store_set(GTK_LIST_STORE(model), &iter, - STATE_SELECTOR_ICON, GTK_STOCK_NETWORK, - STATE_SELECTOR_NAME, announceHost, - STATE_SELECTOR_SERIAL, serial, - STATE_SELECTOR_BIT, FILTER_FLAG_TRACKER, -1); - g_hash_table_insert(priv->trackers, announceHost, quick_tree_ref_new(model, &iter)); + STATE_SELECTOR_ICON, + GTK_STOCK_DIRECTORY, + STATE_SELECTOR_NAME, dir, + STATE_SELECTOR_SERIAL, + client->updateSerial, + STATE_SELECTOR_BIT, FILTER_FLAG_DIR, + -1); + g_hash_table_insert(priv->directories, g_strdup(dir), + quick_tree_ref_new(model, &iter)); } } } - cruft.serial = serial; - cruft.table = priv->trackers; + cruft.serial = client->updateSerial; + + if (priv->showTrackers) { + cruft.table = priv->trackers; + g_hash_table_foreach_remove(priv->trackers, + trg_state_selector_remove_cruft, + &cruft); + } + + if (priv->showDirs) { + cruft.table = priv->directories; + g_hash_table_foreach_remove(priv->directories, + trg_state_selector_remove_cruft, + &cruft); + } +} + +void trg_state_selector_set_show_dirs(TrgStateSelector * s, gboolean show) +{ + TrgStateSelectorPrivate *priv = TRG_STATE_SELECTOR_GET_PRIVATE(s); + priv->showDirs = show; + if (!show) + g_hash_table_remove_all(priv->directories); + else + trg_state_selector_update(s); +} - g_hash_table_foreach_remove(priv->trackers, trg_state_selector_remove_cruft, &cruft); +void trg_state_selector_set_show_trackers(TrgStateSelector * s, + gboolean show) +{ + TrgStateSelectorPrivate *priv = TRG_STATE_SELECTOR_GET_PRIVATE(s); + priv->showTrackers = show; + if (!show) + g_hash_table_remove_all(priv->trackers); + else + trg_state_selector_update(s); } static void trg_state_selector_add_state(GtkListStore * model, @@ -204,7 +336,7 @@ static void trg_state_selector_add_state(GtkListStore * model, STATE_SELECTOR_BIT, flag, -1); } -static void remove_row_ref_and_free(GtkTreeRowReference *rr) +static void remove_row_ref_and_free(GtkTreeRowReference * rr) { GtkTreeModel *model = gtk_tree_row_reference_get_model(rr); GtkTreePath *path = gtk_tree_row_reference_get_path(rr); @@ -216,6 +348,14 @@ static void remove_row_ref_and_free(GtkTreeRowReference *rr) gtk_tree_row_reference_free(rr); } +void trg_state_selector_disconnect(TrgStateSelector * s) +{ + TrgStateSelectorPrivate *priv = TRG_STATE_SELECTOR_GET_PRIVATE(s); + + g_hash_table_remove_all(priv->trackers); + g_hash_table_remove_all(priv->directories); +} + static void trg_state_selector_init(TrgStateSelector * self) { TrgStateSelectorPrivate *priv; @@ -229,7 +369,12 @@ static void trg_state_selector_init(TrgStateSelector * self) priv->flag = 0; priv->urlHostRegex = trg_uri_host_regex_new(); - priv->trackers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)remove_row_ref_and_free); + priv->trackers = + g_hash_table_new_full(g_str_hash, g_str_equal, g_free, + (GDestroyNotify) remove_row_ref_and_free); + priv->directories = + g_hash_table_new_full(g_str_hash, g_str_equal, g_free, + (GDestroyNotify) remove_row_ref_and_free); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(self), FALSE); @@ -268,8 +413,7 @@ static void trg_state_selector_init(TrgStateSelector * self) _("Seeding"), TORRENT_FLAG_SEEDING); trg_state_selector_add_state(store, &iter, GTK_STOCK_DIALOG_WARNING, _("Error"), TORRENT_FLAG_ERROR); - trg_state_selector_add_state(store, &iter, NULL, - NULL, 0); + trg_state_selector_add_state(store, &iter, NULL, NULL, 0); gtk_tree_view_set_model(GTK_TREE_VIEW(self), GTK_TREE_MODEL(store)); gtk_tree_view_set_rubber_banding(GTK_TREE_VIEW(self), TRUE); @@ -280,9 +424,24 @@ static void trg_state_selector_init(TrgStateSelector * self) g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(state_selection_changed), self); + g_signal_connect(self, "button-press-event", + G_CALLBACK(view_onButtonPressed), NULL); + g_signal_connect(self, "popup-menu", G_CALLBACK(view_onPopupMenu), + NULL); } -TrgStateSelector *trg_state_selector_new(void) +TrgStateSelector *trg_state_selector_new(trg_client * client) { - return g_object_new(TRG_TYPE_STATE_SELECTOR, NULL); + GObject *obj = g_object_new(TRG_TYPE_STATE_SELECTOR, NULL); + TrgStateSelectorPrivate *priv = TRG_STATE_SELECTOR_GET_PRIVATE(obj); + + priv->client = client; + priv->showDirs = + gconf_client_get_bool_or_true(client->gconf, + TRG_GCONF_KEY_FILTER_DIRS); + priv->showTrackers = + gconf_client_get_bool_or_true(client->gconf, + TRG_GCONF_KEY_FILTER_TRACKERS); + + return TRG_STATE_SELECTOR(obj); } |