summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Alan Fitton <ajf@eth0.org.uk>2011-12-27 18:35:13 +0000
committerGravatar Alan Fitton <ajf@eth0.org.uk>2011-12-27 18:35:13 +0000
commit97830623478379916c723854e8cbb9473f8acd1f (patch)
treeeb9d1a1a81928a315cbac171ed5dd49aee4a84f2
parent42f593e062f1e444339edda7ea4e30f689b303ae (diff)
filter items (not trackers+dirs for now) show counts next to them. while doing this, I made the stats update loop something that happens only if something changes, which avoids a full iteration over all torrents (even in active only).
-rw-r--r--src/Makefile.am1
-rw-r--r--src/trg-cell-renderer-counter.c136
-rw-r--r--src/trg-cell-renderer-counter.h51
-rw-r--r--src/trg-main-window.c11
-rw-r--r--src/trg-peers-model.c5
-rw-r--r--src/trg-state-selector.c465
-rw-r--r--src/trg-state-selector.h3
-rw-r--r--src/trg-torrent-model.c501
-rw-r--r--src/trg-torrent-model.h10
9 files changed, 659 insertions, 524 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index c978ea5..9ec2231 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -79,6 +79,7 @@ transmission_remote_gtk_SOURCES = main.c \
trg-torrent-add-url-dialog.c \
trg-json-widgets.c \
trg-cell-renderer-speed.c \
+ trg-cell-renderer-counter.c \
trg-cell-renderer-size.c \
trg-cell-renderer-ratio.c \
trg-cell-renderer-eta.c \
diff --git a/src/trg-cell-renderer-counter.c b/src/trg-cell-renderer-counter.c
new file mode 100644
index 0000000..0548023
--- /dev/null
+++ b/src/trg-cell-renderer-counter.c
@@ -0,0 +1,136 @@
+/*
+ * 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.
+ */
+
+#include <stdint.h>
+#include <gtk/gtk.h>
+
+#include "trg-cell-renderer-counter.h"
+#include "util.h"
+
+enum {
+ PROP_0, PROP_STATE_LABEL, PROP_STATE_COUNT
+};
+
+G_DEFINE_TYPE(TrgCellRendererCounter, trg_cell_renderer_counter,
+ GTK_TYPE_CELL_RENDERER_TEXT)
+#define TRG_CELL_RENDERER_COUNTER_GET_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRG_TYPE_CELL_RENDERER_COUNTER, TrgCellRendererCounterPrivate))
+typedef struct _TrgCellRendererCounterPrivate TrgCellRendererCounterPrivate;
+
+struct _TrgCellRendererCounterPrivate {
+ gint count;
+ gchar *originalLabel;
+};
+
+static void trg_cell_renderer_counter_get_property(GObject * object,
+ guint property_id, GValue * value, GParamSpec * pspec) {
+ TrgCellRendererCounterPrivate *priv =
+ TRG_CELL_RENDERER_COUNTER_GET_PRIVATE(object);
+ switch (property_id) {
+ case PROP_STATE_COUNT:
+ g_value_set_int(value, priv->count);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+ break;
+ }
+}
+
+static void trg_cell_renderer_counter_refresh(TrgCellRendererCounter *cr) {
+ TrgCellRendererCounterPrivate *priv =
+ TRG_CELL_RENDERER_COUNTER_GET_PRIVATE(cr);
+ if (priv->originalLabel && priv->count > 0) {
+ gchar *counterLabel = g_strdup_printf("%s <span size=\"small\">(%d)</span>", priv->originalLabel,
+ priv->count);
+ g_object_set(cr, "markup", counterLabel, NULL);
+ g_free(counterLabel);
+ } else {
+ g_object_set(cr, "text", priv->originalLabel, NULL);
+ }
+}
+
+static void trg_cell_renderer_counter_set_property(GObject * object,
+ guint property_id, const GValue * value, GParamSpec * pspec) {
+ TrgCellRendererCounterPrivate *priv =
+ TRG_CELL_RENDERER_COUNTER_GET_PRIVATE(object);
+
+ if (property_id == PROP_STATE_LABEL) {
+ g_free(priv->originalLabel);
+ priv->originalLabel = g_strdup(g_value_get_string(value));
+ trg_cell_renderer_counter_refresh(TRG_CELL_RENDERER_COUNTER(object));
+ } else if (property_id == PROP_STATE_COUNT) {
+ gint newCount = g_value_get_int(value);
+ if (priv->count != newCount) {
+ priv->count = newCount;
+ trg_cell_renderer_counter_refresh(
+ TRG_CELL_RENDERER_COUNTER(object));
+ }
+ } else {
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+ }
+}
+
+static void trg_cell_renderer_counter_dispose(GObject * object) {
+ TrgCellRendererCounterPrivate *priv =
+ TRG_CELL_RENDERER_COUNTER_GET_PRIVATE(object);
+ g_free(priv->originalLabel);
+ G_OBJECT_CLASS(trg_cell_renderer_counter_parent_class)->dispose(object);
+}
+
+static void trg_cell_renderer_counter_class_init(
+ TrgCellRendererCounterClass * klass) {
+ GObjectClass *object_class = G_OBJECT_CLASS(klass);
+
+ object_class->get_property = trg_cell_renderer_counter_get_property;
+ object_class->set_property = trg_cell_renderer_counter_set_property;
+ object_class->dispose = trg_cell_renderer_counter_dispose;
+
+ g_object_class_install_property(
+ object_class,
+ PROP_STATE_COUNT,
+ g_param_spec_int(
+ "state-count",
+ "State Count",
+ "State Count",
+ -1,
+ INT_MAX,
+ -1,
+ G_PARAM_READWRITE | G_PARAM_STATIC_NAME
+ | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
+
+ g_object_class_install_property(
+ object_class,
+ PROP_STATE_LABEL,
+ g_param_spec_string(
+ "state-label",
+ "State Label",
+ "State Label",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_NAME
+ | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
+
+ g_type_class_add_private(klass, sizeof(TrgCellRendererCounterPrivate));
+}
+
+static void trg_cell_renderer_counter_init(TrgCellRendererCounter * self) {
+}
+
+GtkCellRenderer *trg_cell_renderer_counter_new(void) {
+ return GTK_CELL_RENDERER(g_object_new(TRG_TYPE_CELL_RENDERER_COUNTER, NULL));
+}
diff --git a/src/trg-cell-renderer-counter.h b/src/trg-cell-renderer-counter.h
new file mode 100644
index 0000000..5ecaba8
--- /dev/null
+++ b/src/trg-cell-renderer-counter.h
@@ -0,0 +1,51 @@
+/*
+ * 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_CELL_RENDERER_COUNTER_H_
+#define TRG_CELL_RENDERER_COUNTER_H_
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+#define TRG_TYPE_CELL_RENDERER_COUNTER trg_cell_renderer_counter_get_type()
+#define TRG_CELL_RENDERER_COUNTER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), TRG_TYPE_CELL_RENDERER_COUNTER, TrgCellRendererCounter))
+#define TRG_CELL_RENDERER_COUNTER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), TRG_TYPE_CELL_RENDERER_COUNTER, TrgCellRendererCounterClass))
+#define TRG_IS_CELL_RENDERER_COUNTER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TRG_TYPE_CELL_RENDERER_COUNTER))
+#define TRG_IS_CELL_RENDERER_COUNTER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), TRG_TYPE_CELL_RENDERER_COUNTER))
+#define TRG_CELL_RENDERER_COUNTER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), TRG_TYPE_CELL_RENDERER_COUNTER, TrgCellRendererCounterClass))
+ typedef struct {
+ GtkCellRendererText parent;
+} TrgCellRendererCounter;
+
+typedef struct {
+ GtkCellRendererTextClass parent_class;
+} TrgCellRendererCounterClass;
+
+GType trg_cell_renderer_counter_get_type(void);
+
+GtkCellRenderer *trg_cell_renderer_counter_new(void);
+
+G_END_DECLS
+#endif /* TRG_CELL_RENDERER_COUNTER_H_ */
diff --git a/src/trg-main-window.c b/src/trg-main-window.c
index 2e45d52..5461fb3 100644
--- a/src/trg-main-window.c
+++ b/src/trg-main-window.c
@@ -365,12 +365,6 @@ static void on_torrent_completed(TrgTorrentModel * model,
#endif
}
-static void on_update_filters(TrgTorrentModel * model, gpointer data)
-{
- TrgMainWindowPrivate *priv = TRG_MAIN_WINDOW_GET_PRIVATE(data);
- trg_state_selector_update(priv->stateSelector);
-}
-
static void on_torrent_added(TrgTorrentModel * model, GtkTreeIter * iter,
gpointer data)
{
@@ -1141,7 +1135,6 @@ static gboolean on_torrent_get(gpointer data, int mode)
stats =
trg_torrent_model_update(priv->torrentModel, client, response->obj,
mode);
- trg_state_selector_stats_update(priv->stateSelector, stats);
update_selected_torrent_notebook(win, mode, priv->selectedTorrentId);
trg_status_bar_update(priv->statusBar, stats, client);
update_whatever_statusicon(win,
@@ -2377,8 +2370,6 @@ static GObject *trg_main_window_constructor(GType type,
G_CALLBACK(on_torrent_completed), self);
g_signal_connect(priv->torrentModel, "torrent-added",
G_CALLBACK(on_torrent_added), self);
- g_signal_connect(priv->torrentModel, "update-filters",
- G_CALLBACK(on_update_filters), self);
priv->sortedTorrentModel =
gtk_tree_model_sort_new_with_model(GTK_TREE_MODEL
@@ -2435,7 +2426,7 @@ static GObject *trg_main_window_constructor(GType type,
gtk_box_pack_start(GTK_BOX(outerVbox), priv->vpaned, TRUE, TRUE, 0);
gtk_paned_pack1(GTK_PANED(priv->vpaned), priv->hpaned, TRUE, TRUE);
- priv->stateSelector = trg_state_selector_new(priv->client);
+ priv->stateSelector = trg_state_selector_new(priv->client, priv->torrentModel);
priv->stateSelectorScroller =
my_scrolledwin_new(GTK_WIDGET(priv->stateSelector));
gtk_paned_pack1(GTK_PANED(priv->hpaned), priv->stateSelectorScroller,
diff --git a/src/trg-peers-model.c b/src/trg-peers-model.c
index 86574fd..17df900 100644
--- a/src/trg-peers-model.c
+++ b/src/trg-peers-model.c
@@ -64,14 +64,17 @@ gboolean find_existing_peer_item_foreachfunc(GtkTreeModel * model,
gpointer data)
{
struct peerAndIter *pi = (struct peerAndIter *) data;
-
gchar *ip;
+
gtk_tree_model_get(model, iter, PEERSCOL_IP, &ip, -1);
+
if (g_strcmp0(ip, pi->ip) == 0) {
pi->iter = *iter;
pi->found = TRUE;
}
+
g_free(ip);
+
return pi->found;
}
diff --git a/src/trg-state-selector.c b/src/trg-state-selector.c
index 1fd0367..413c8fc 100644
--- a/src/trg-state-selector.c
+++ b/src/trg-state-selector.c
@@ -23,6 +23,7 @@
#include <gtk/gtk.h>
#include "torrent.h"
+#include "trg-cell-renderer-counter.h"
#include "trg-state-selector.h"
#include "trg-torrent-model.h"
#include "util.h"
@@ -30,13 +31,11 @@
#include "trg-client.h"
enum {
- SELECTOR_STATE_CHANGED,
- SELECTOR_SIGNAL_COUNT
+ SELECTOR_STATE_CHANGED, SELECTOR_SIGNAL_COUNT
};
enum {
- PROP_0,
- PROP_CLIENT
+ PROP_0, PROP_CLIENT
};
static guint signals[SELECTOR_SIGNAL_COUNT] = { 0 };
@@ -58,23 +57,29 @@ struct _TrgStateSelectorPrivate {
gint n_categories;
GtkListStore *store;
GtkTreeRowReference *error_rr;
+ GtkTreeRowReference *all_rr;
+ GtkTreeRowReference *paused_rr;
+ GtkTreeRowReference *down_rr;
+ GtkTreeRowReference *seeding_rr;
+ GtkTreeRowReference *complete_rr;
+ GtkTreeRowReference *incomplete_rr;
+ GtkTreeRowReference *checking_rr;
+ GtkTreeRowReference *active_rr;
+ GtkTreeRowReference *seed_wait_rr;
+ GtkTreeRowReference *down_wait_rr;
};
-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;
}
-guint32 trg_state_selector_get_flag(TrgStateSelector * s)
-{
+guint32 trg_state_selector_get_flag(TrgStateSelector * s) {
TrgStateSelectorPrivate *priv = TRG_STATE_SELECTOR_GET_PRIVATE(s);
return priv->flag;
}
-static void state_selection_changed(GtkTreeSelection * selection,
- gpointer data)
-{
+static void state_selection_changed(GtkTreeSelection * selection, gpointer data) {
TrgStateSelectorPrivate *priv;
GtkTreeIter iter;
GtkTreeModel *stateModel;
@@ -83,21 +88,20 @@ static void state_selection_changed(GtkTreeSelection * selection,
priv = TRG_STATE_SELECTOR_GET_PRIVATE(data);
if (gtk_tree_selection_get_selected(selection, &stateModel, &iter))
- gtk_tree_model_get(stateModel, &iter, STATE_SELECTOR_BIT,
- &priv->flag, STATE_SELECTOR_INDEX, &index, -1);
+ gtk_tree_model_get(stateModel, &iter, STATE_SELECTOR_BIT, &priv->flag,
+ STATE_SELECTOR_INDEX, &index, -1);
else
priv->flag = 0;
trg_prefs_set_int(priv->prefs, TRG_PREFS_STATE_SELECTOR_LAST, index,
- TRG_PREFS_GLOBAL);
+ TRG_PREFS_GLOBAL);
- g_signal_emit(TRG_STATE_SELECTOR(data),
- signals[SELECTOR_STATE_CHANGED], 0, priv->flag);
+ g_signal_emit(TRG_STATE_SELECTOR(data), signals[SELECTOR_STATE_CHANGED], 0,
+ priv->flag);
}
static GtkTreeRowReference *quick_tree_ref_new(GtkTreeModel * model,
- GtkTreeIter * iter)
-{
+ GtkTreeIter * iter) {
GtkTreePath *path = gtk_tree_model_get_path(model, iter);
GtkTreeRowReference *rr = gtk_tree_row_reference_new(model, path);
gtk_tree_path_free(path);
@@ -109,10 +113,8 @@ 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;
GtkTreeModel *model = gtk_tree_row_reference_get_model(rr);
@@ -123,8 +125,7 @@ static gboolean trg_state_selector_remove_cruft(gpointer key,
gint64 currentSerial;
gtk_tree_model_get_iter(model, &iter, path);
- gtk_tree_model_get(model, &iter, STATE_SELECTOR_SERIAL, &currentSerial,
- -1);
+ gtk_tree_model_get(model, &iter, STATE_SELECTOR_SERIAL, &currentSerial, -1);
remove = (args->serial != currentSerial);
@@ -133,8 +134,7 @@ static gboolean trg_state_selector_remove_cruft(gpointer key,
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;
GtkTreeIter iter;
@@ -147,25 +147,21 @@ gchar *trg_state_selector_get_selected_text(TrgStateSelector * s)
}
static void trg_state_selector_update_serial(GtkTreeModel * model,
- GtkTreeRowReference * rr,
- gint64 serial)
-{
+ GtkTreeRowReference * rr, gint64 serial) {
GtkTreeIter iter;
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);
+ serial, -1);
gtk_tree_path_free(path);
}
-static void refresh_statelist_cb(GtkWidget * w, gpointer data)
-{
+static void refresh_statelist_cb(GtkWidget * w, gpointer data) {
trg_state_selector_update(TRG_STATE_SELECTOR(data));
}
static void view_popup_menu(GtkWidget * treeview, GdkEventButton * event,
- gpointer data G_GNUC_UNUSED)
-{
+ gpointer data G_GNUC_UNUSED) {
GtkWidget *menu, *item;
menu = gtk_menu_new();
@@ -173,28 +169,25 @@ static void view_popup_menu(GtkWidget * treeview, GdkEventButton * event,
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);
+ (item), TRUE);
g_signal_connect(item, "activate", G_CALLBACK(refresh_statelist_cb),
- treeview);
+ treeview);
gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
gtk_widget_show_all(menu);
gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
- (event != NULL) ? event->button : 0,
- gdk_event_get_time((GdkEvent *) event));
-}
+ (event != NULL) ? event->button : 0,
+ gdk_event_get_time((GdkEvent *) event));
+ }
-static gboolean view_onPopupMenu(GtkWidget * treeview, gpointer userdata)
-{
+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)
-{
+ GdkEventButton * event, gpointer userdata) {
if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
view_popup_menu(treeview, event, userdata);
return TRUE;
@@ -211,10 +204,7 @@ struct state_find_pos {
};
static gboolean trg_state_selector_find_pos_foreach(GtkTreeModel * model,
- GtkTreePath * path,
- GtkTreeIter * iter,
- gpointer data)
-{
+ GtkTreePath * path, GtkTreeIter * iter, gpointer data) {
struct state_find_pos *args = (struct state_find_pos *) data;
gchar *name;
gboolean res;
@@ -222,8 +212,7 @@ static gboolean trg_state_selector_find_pos_foreach(GtkTreeModel * model,
if (args->pos < args->offset) {
args->pos++;
return FALSE;
- } else if (args->range >= 0
- && args->pos > args->offset + args->range - 1) {
+ } else if (args->range >= 0 && args->pos > args->offset + args->range - 1) {
return TRUE;
}
@@ -238,9 +227,7 @@ static gboolean trg_state_selector_find_pos_foreach(GtkTreeModel * model,
}
static void trg_state_selector_insert(TrgStateSelector * s, int offset,
- gint range, const gchar * name,
- GtkTreeIter * iter)
-{
+ gint range, const gchar * name, GtkTreeIter * iter) {
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(s));
struct state_find_pos args;
@@ -249,13 +236,11 @@ static void trg_state_selector_insert(TrgStateSelector * s, int offset,
args.range = range;
args.name = name;
- gtk_tree_model_foreach(model, trg_state_selector_find_pos_foreach,
- &args);
+ gtk_tree_model_foreach(model, trg_state_selector_find_pos_foreach, &args);
gtk_list_store_insert(GTK_LIST_STORE(model), iter, args.pos);
}
-void trg_state_selector_update(TrgStateSelector * s)
-{
+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));
TrgClient *client = priv->client;
@@ -272,8 +257,8 @@ void trg_state_selector_update(TrgStateSelector * s)
if (!trg_client_is_connected(client))
return;
- torrentItemRefs =
- g_hash_table_get_values(trg_client_get_torrent_table(client));
+ torrentItemRefs = g_hash_table_get_values(
+ trg_client_get_torrent_table(client));
for (li = torrentItemRefs; li; li = g_list_next(li)) {
JsonObject *t = NULL;
@@ -284,7 +269,7 @@ void trg_state_selector_update(TrgStateSelector * s)
if (path) {
if (gtk_tree_model_get_iter(torrentModel, &torrentIter, path)) {
gtk_tree_model_get(torrentModel, &torrentIter,
- TORRENT_COLUMN_JSON, &t, -1);
+ TORRENT_COLUMN_JSON, &t, -1);
}
gtk_tree_path_free(path);
}
@@ -293,17 +278,15 @@ void trg_state_selector_update(TrgStateSelector * s)
continue;
if (priv->showTrackers) {
- trackersList
- = json_array_get_elements(torrent_get_tracker_stats(t));
- for (trackerItem = trackersList; trackerItem; trackerItem
- = g_list_next(trackerItem)) {
- JsonObject *tracker = json_node_get_object((JsonNode *)
- trackerItem->data);
- const gchar *announceUrl =
- tracker_stats_get_announce(tracker);
- gchar *announceHost =
- trg_gregex_get_first(priv->urlHostRegex,
- announceUrl);
+ trackersList = json_array_get_elements(
+ torrent_get_tracker_stats(t));
+ for (trackerItem = trackersList; trackerItem;
+ trackerItem = g_list_next(trackerItem)) {
+ JsonObject *tracker = json_node_get_object(
+ (JsonNode *) trackerItem->data);
+ const gchar *announceUrl = tracker_stats_get_announce(tracker);
+ gchar *announceHost = trg_gregex_get_first(priv->urlHostRegex,
+ announceUrl);
if (!announceHost)
continue;
@@ -312,25 +295,20 @@ void trg_state_selector_update(TrgStateSelector * s)
if (result) {
trg_state_selector_update_serial(model,
- (GtkTreeRowReference
- *) result,
- updateSerial);
+ (GtkTreeRowReference *) result, updateSerial);
g_free(announceHost);
} else {
trg_state_selector_insert(s, priv->n_categories,
- g_hash_table_size
- (priv->trackers),
- announceHost, &iter);
+ g_hash_table_size(priv->trackers), announceHost,
+ &iter);
gtk_list_store_set(GTK_LIST_STORE(model), &iter,
- STATE_SELECTOR_ICON,
- GTK_STOCK_NETWORK,
- STATE_SELECTOR_NAME, announceHost,
- STATE_SELECTOR_SERIAL, updateSerial,
- STATE_SELECTOR_BIT,
- FILTER_FLAG_TRACKER,
- STATE_SELECTOR_INDEX, 0, -1);
+ STATE_SELECTOR_ICON, GTK_STOCK_NETWORK,
+ STATE_SELECTOR_NAME, announceHost,
+ STATE_SELECTOR_SERIAL, updateSerial,
+ STATE_SELECTOR_BIT, FILTER_FLAG_TRACKER,
+ STATE_SELECTOR_INDEX, 0, -1);
g_hash_table_insert(priv->trackers, announceHost,
- quick_tree_ref_new(model, &iter));
+ quick_tree_ref_new(model, &iter));
}
}
g_list_free(trackersList);
@@ -339,28 +317,23 @@ void trg_state_selector_update(TrgStateSelector * s)
if (priv->showDirs) {
gchar *dir;
gtk_tree_model_get(torrentModel, &torrentIter,
- TORRENT_COLUMN_DOWNLOADDIR_SHORT, &dir, -1);
+ TORRENT_COLUMN_DOWNLOADDIR_SHORT, &dir, -1);
result = g_hash_table_lookup(priv->directories, dir);
if (result) {
trg_state_selector_update_serial(model,
- (GtkTreeRowReference *)
- result, updateSerial);
+ (GtkTreeRowReference *) result, updateSerial);
} else {
trg_state_selector_insert(s,
- priv->n_categories +
- g_hash_table_size
- (priv->trackers), -1, dir,
- &iter);
+ priv->n_categories + g_hash_table_size(priv->trackers),
+ -1, dir, &iter);
gtk_list_store_set(GTK_LIST_STORE(model), &iter,
- STATE_SELECTOR_ICON,
- GTK_STOCK_DIRECTORY,
- STATE_SELECTOR_NAME, dir,
- STATE_SELECTOR_SERIAL, updateSerial,
- STATE_SELECTOR_BIT, FILTER_FLAG_DIR,
- STATE_SELECTOR_INDEX, 0, -1);
+ STATE_SELECTOR_ICON, GTK_STOCK_DIRECTORY,
+ STATE_SELECTOR_NAME, dir, STATE_SELECTOR_SERIAL,
+ updateSerial, STATE_SELECTOR_BIT, FILTER_FLAG_DIR,
+ STATE_SELECTOR_INDEX, 0, -1);
g_hash_table_insert(priv->directories, g_strdup(dir),
- quick_tree_ref_new(model, &iter));
+ quick_tree_ref_new(model, &iter));
}
g_free(dir);
@@ -374,20 +347,17 @@ void trg_state_selector_update(TrgStateSelector * s)
if (priv->showTrackers) {
cruft.table = priv->trackers;
g_hash_table_foreach_remove(priv->trackers,
- trg_state_selector_remove_cruft,
- &cruft);
+ 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);
+ trg_state_selector_remove_cruft, &cruft);
}
}
-void trg_state_selector_set_show_dirs(TrgStateSelector * s, gboolean show)
-{
+void trg_state_selector_set_show_dirs(TrgStateSelector * s, gboolean show) {
TrgStateSelectorPrivate *priv = TRG_STATE_SELECTOR_GET_PRIVATE(s);
priv->showDirs = show;
if (!show)
@@ -396,9 +366,15 @@ void trg_state_selector_set_show_dirs(TrgStateSelector * s, gboolean show)
trg_state_selector_update(s);
}
-void trg_state_selector_set_show_trackers(TrgStateSelector * s,
- gboolean show)
-{
+static void on_torrents_state_change(TrgTorrentModel * model,
+ guint whatsChanged, gpointer data) {
+ TrgStateSelector *selector = TRG_STATE_SELECTOR(data);
+ trg_state_selector_update(selector);
+ trg_state_selector_stats_update(selector,
+ trg_torrent_model_get_stats(model));
+}
+
+void trg_state_selector_set_show_trackers(TrgStateSelector * s, gboolean show) {
TrgStateSelectorPrivate *priv = TRG_STATE_SELECTOR_GET_PRIVATE(s);
priv->showTrackers = show;
if (!show)
@@ -408,14 +384,11 @@ void trg_state_selector_set_show_trackers(TrgStateSelector * s,
}
static void trg_state_selector_add_state(TrgStateSelector * selector,
- GtkTreeIter * iter, gint pos,
- gchar * icon, gchar * name,
- guint32 flag)
-{
- TrgStateSelectorPrivate *priv =
- TRG_STATE_SELECTOR_GET_PRIVATE(selector);
+ GtkTreeIter * iter, gint pos, gchar * icon, gchar * name, guint32 flag,
+ GtkTreeRowReference **rr) {
+ TrgStateSelectorPrivate *priv = TRG_STATE_SELECTOR_GET_PRIVATE(selector);
GtkListStore *model =
- GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(selector)));
+ GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(selector)));
if (pos < 0)
gtk_list_store_append(priv->store, iter);
@@ -423,17 +396,17 @@ static void trg_state_selector_add_state(TrgStateSelector * selector,
gtk_list_store_insert(priv->store, iter, pos);
gtk_list_store_set(model, iter, STATE_SELECTOR_ICON, icon,
- STATE_SELECTOR_NAME, name, STATE_SELECTOR_BIT, flag,
- STATE_SELECTOR_INDEX,
- gtk_tree_model_iter_n_children(GTK_TREE_MODEL
- (model), NULL) - 1,
- -1);
+ STATE_SELECTOR_NAME, name, STATE_SELECTOR_BIT, flag,
+ STATE_SELECTOR_INDEX, gtk_tree_model_iter_n_children(GTK_TREE_MODEL
+ (model), NULL) - 1, -1);
+
+ if (rr)
+ *rr = quick_tree_ref_new(GTK_TREE_MODEL(model), iter);
priv->n_categories++;
}
-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);
GtkTreeIter iter;
@@ -444,27 +417,53 @@ static void remove_row_ref_and_free(GtkTreeRowReference * rr)
gtk_tree_row_reference_free(rr);
}
+static void trg_state_selector_update_stat(GtkTreeRowReference *rr, gint count) {
+ if (rr) {
+ GValue gvalue = { 0 };
+ GtkTreeIter iter;
+ GtkTreePath *path = gtk_tree_row_reference_get_path(rr);
+ GtkTreeModel *model = gtk_tree_row_reference_get_model(rr);
+
+ gtk_tree_model_get_iter(model, &iter, path);
+
+ g_value_init(&gvalue, G_TYPE_INT);
+ g_value_set_int(&gvalue, count);
+ gtk_list_store_set_value(GTK_LIST_STORE(model), &iter,
+ STATE_SELECTOR_COUNT, &gvalue);
+
+ gtk_tree_path_free(path);
+ }
+}
+
void trg_state_selector_stats_update(TrgStateSelector * s,
- trg_torrent_model_update_stats *
- stats)
-{
+ trg_torrent_model_update_stats * stats) {
TrgStateSelectorPrivate *priv = TRG_STATE_SELECTOR_GET_PRIVATE(s);
GtkTreeIter iter;
if (stats->error > 0 && !priv->error_rr) {
trg_state_selector_add_state(s, &iter, priv->n_categories - 1,
- GTK_STOCK_DIALOG_WARNING, _("Error"),
- TORRENT_FLAG_ERROR);
- priv->error_rr =
- quick_tree_ref_new(GTK_TREE_MODEL(priv->store), &iter);
+ GTK_STOCK_DIALOG_WARNING, _("Error"), TORRENT_FLAG_ERROR,
+ &priv->error_rr);
+
} else if (stats->error < 1 && priv->error_rr) {
remove_row_ref_and_free(priv->error_rr);
priv->error_rr = NULL;
priv->n_categories--;
}
+
+ trg_state_selector_update_stat(priv->all_rr, stats->count);
+ trg_state_selector_update_stat(priv->down_rr, stats->down);
+ trg_state_selector_update_stat(priv->seeding_rr, stats->seeding);
+ trg_state_selector_update_stat(priv->error_rr, stats->error);
+ trg_state_selector_update_stat(priv->paused_rr, stats->paused);
+ trg_state_selector_update_stat(priv->complete_rr, stats->complete);
+ trg_state_selector_update_stat(priv->incomplete_rr, stats->incomplete);
+ trg_state_selector_update_stat(priv->active_rr, stats->active);
+ trg_state_selector_update_stat(priv->checking_rr, stats->checking);
+ trg_state_selector_update_stat(priv->down_wait_rr, stats->down_wait);
+ trg_state_selector_update_stat(priv->seed_wait_rr, stats->seed_wait);
}
-void trg_state_selector_disconnect(TrgStateSelector * s)
-{
+void trg_state_selector_disconnect(TrgStateSelector * s) {
TrgStateSelectorPrivate *priv = TRG_STATE_SELECTOR_GET_PRIVATE(s);
if (priv->error_rr) {
@@ -475,23 +474,32 @@ void trg_state_selector_disconnect(TrgStateSelector * s)
g_hash_table_remove_all(priv->trackers);
g_hash_table_remove_all(priv->directories);
+
+ trg_state_selector_update_stat(priv->all_rr, -1);
+ trg_state_selector_update_stat(priv->down_rr, -1);
+ trg_state_selector_update_stat(priv->seeding_rr, -1);
+ trg_state_selector_update_stat(priv->error_rr, -1);
+ trg_state_selector_update_stat(priv->paused_rr, -1);
+ trg_state_selector_update_stat(priv->complete_rr, -1);
+ trg_state_selector_update_stat(priv->incomplete_rr, -1);
+ trg_state_selector_update_stat(priv->active_rr, -1);
+ trg_state_selector_update_stat(priv->checking_rr, -1);
}
-static void trg_state_selector_init(TrgStateSelector * self)
-{
+static void trg_state_selector_init(TrgStateSelector * self) {
}
-TrgStateSelector *trg_state_selector_new(TrgClient * client)
-{
- return g_object_new(TRG_TYPE_STATE_SELECTOR, "client", client, NULL);
+TrgStateSelector *trg_state_selector_new(TrgClient * client,
+ TrgTorrentModel *tmodel) {
+ TrgStateSelector *selector = g_object_new(TRG_TYPE_STATE_SELECTOR, "client",
+ client, NULL);
+ g_signal_connect(tmodel, "torrents-state-change",
+ G_CALLBACK(on_torrents_state_change), selector);
+ return selector;
}
static GObject *trg_state_selector_constructor(GType type,
- guint
- n_construct_properties,
- GObjectConstructParam *
- construct_params)
-{
+ guint n_construct_properties, GObjectConstructParam * construct_params) {
GObject *object;
TrgStateSelector *selector;
TrgStateSelectorPrivate *priv;
@@ -503,20 +511,17 @@ static GObject *trg_state_selector_constructor(GType type,
GtkTreeSelection *selection;
object = G_OBJECT_CLASS
- (trg_state_selector_parent_class)->constructor(type,
- n_construct_properties,
- construct_params);
+ (trg_state_selector_parent_class)->constructor(type,
+ n_construct_properties, construct_params);
selector = TRG_STATE_SELECTOR(object);
priv = TRG_STATE_SELECTOR_GET_PRIVATE(object);
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->directories =
- g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
- (GDestroyNotify) remove_row_ref_and_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(object), FALSE);
@@ -525,110 +530,95 @@ static GObject *trg_state_selector_constructor(GType type,
renderer = gtk_cell_renderer_pixbuf_new();
gtk_tree_view_column_pack_start(column, renderer, FALSE);
g_object_set(renderer, "stock-size", 4, NULL);
- gtk_tree_view_column_set_attributes(column, renderer, "stock-id", STATE_SELECTOR_ICON,
- NULL);
+ gtk_tree_view_column_set_attributes(column, renderer, "stock-id",
+ STATE_SELECTOR_ICON, NULL);
- renderer = gtk_cell_renderer_text_new();
+ renderer = trg_cell_renderer_counter_new();
gtk_tree_view_column_pack_start(column, renderer, TRUE);
- gtk_tree_view_column_set_attributes(column, renderer, "text", STATE_SELECTOR_NAME, NULL);
+ gtk_tree_view_column_set_attributes(column, renderer, "state-label",
+ STATE_SELECTOR_NAME, "state-count", STATE_SELECTOR_COUNT, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(object), column);
- store = priv->store =
- gtk_list_store_new(STATE_SELECTOR_COLUMNS, G_TYPE_STRING,
- G_TYPE_STRING, G_TYPE_UINT, G_TYPE_INT64,
- G_TYPE_UINT);
+ store = priv->store = gtk_list_store_new(STATE_SELECTOR_COLUMNS,
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_UINT, G_TYPE_INT64,
+ G_TYPE_UINT);
gtk_tree_view_set_model(GTK_TREE_VIEW(object), GTK_TREE_MODEL(store));
- trg_state_selector_add_state(selector, &iter, -1, GTK_STOCK_ABOUT,
- _("All"), 0);
+ trg_state_selector_add_state(selector, &iter, -1, GTK_STOCK_ABOUT, _("All"),
+ 0, &priv->all_rr);
trg_state_selector_add_state(selector, &iter, -1, GTK_STOCK_GO_DOWN,
- _("Downloading"),
- TORRENT_FLAG_DOWNLOADING);
- trg_state_selector_add_state(selector, &iter, -1,
- GTK_STOCK_MEDIA_REWIND, _("Queue Down"),
- TORRENT_FLAG_DOWNLOADING_WAIT);
+ _("Downloading"), TORRENT_FLAG_DOWNLOADING, &priv->down_rr);
+ trg_state_selector_add_state(selector, &iter, -1, GTK_STOCK_MEDIA_REWIND,
+ _("Queue Down"), TORRENT_FLAG_DOWNLOADING_WAIT, &priv->down_wait_rr);
trg_state_selector_add_state(selector, &iter, -1, GTK_STOCK_GO_UP,
- _("Seeding"), TORRENT_FLAG_SEEDING);
- trg_state_selector_add_state(selector, &iter, -1,
- GTK_STOCK_MEDIA_FORWARD, _("Queue Up"),
- TORRENT_FLAG_SEEDING_WAIT);
- trg_state_selector_add_state(selector, &iter, -1,
- GTK_STOCK_MEDIA_PAUSE, _("Paused"),
- TORRENT_FLAG_PAUSED);
+ _("Seeding"), TORRENT_FLAG_SEEDING, &priv->seeding_rr);
+ trg_state_selector_add_state(selector, &iter, -1, GTK_STOCK_MEDIA_FORWARD,
+ _("Queue Up"), TORRENT_FLAG_SEEDING_WAIT, &priv->seed_wait_rr);
+ trg_state_selector_add_state(selector, &iter, -1, GTK_STOCK_MEDIA_PAUSE,
+ _("Paused"), TORRENT_FLAG_PAUSED, &priv->paused_rr);
trg_state_selector_add_state(selector, &iter, -1, GTK_STOCK_APPLY,
- _("Complete"), TORRENT_FLAG_COMPLETE);
+ _("Complete"), TORRENT_FLAG_COMPLETE, &priv->complete_rr);
trg_state_selector_add_state(selector, &iter, -1, GTK_STOCK_SELECT_ALL,
- _("Incomplete"), TORRENT_FLAG_INCOMPLETE);
+ _("Incomplete"), TORRENT_FLAG_INCOMPLETE, &priv->incomplete_rr);
trg_state_selector_add_state(selector, &iter, -1, GTK_STOCK_NETWORK,
- _("Active"), TORRENT_FLAG_ACTIVE);
+ _("Active"), TORRENT_FLAG_ACTIVE, &priv->active_rr);
trg_state_selector_add_state(selector, &iter, -1, GTK_STOCK_REFRESH,
- _("Checking"), TORRENT_FLAG_CHECKING_ANY);
- trg_state_selector_add_state(selector, &iter, -1, NULL, NULL, 0);
+ _("Checking"), TORRENT_FLAG_CHECKING_ANY, &priv->checking_rr);
+ trg_state_selector_add_state(selector, &iter, -1, NULL, NULL, 0, NULL);
gtk_tree_view_set_rubber_banding(GTK_TREE_VIEW(object), TRUE);
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(object));
g_signal_connect(G_OBJECT(selection), "changed",
- G_CALLBACK(state_selection_changed), object);
+ G_CALLBACK(state_selection_changed), object);
g_signal_connect(object, "button-press-event",
- G_CALLBACK(view_onButtonPressed), NULL);
- g_signal_connect(object, "popup-menu", G_CALLBACK(view_onPopupMenu),
- NULL);
+ G_CALLBACK(view_onButtonPressed), NULL);
+ g_signal_connect(object, "popup-menu", G_CALLBACK(view_onPopupMenu), NULL);
- gtk_tree_view_set_search_column(GTK_TREE_VIEW(object),
- STATE_SELECTOR_NAME);
+ gtk_tree_view_set_search_column(GTK_TREE_VIEW(object), STATE_SELECTOR_NAME);
index = trg_prefs_get_int(priv->prefs, TRG_PREFS_STATE_SELECTOR_LAST,
- TRG_PREFS_GLOBAL);
- if (index > 0 && gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store),
- &iter, NULL, index)) {
- GtkTreeSelection *selection =
- gtk_tree_view_get_selection(GTK_TREE_VIEW(object));
+ TRG_PREFS_GLOBAL);
+ if (index > 0
+ && gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &iter, NULL,
+ index)) {
+ GtkTreeSelection *selection = gtk_tree_view_get_selection(
+ GTK_TREE_VIEW(object));
gtk_tree_selection_select_iter(selection, &iter);
}
- priv->showDirs =
- trg_prefs_get_bool(priv->prefs, TRG_PREFS_KEY_FILTER_DIRS,
- TRG_PREFS_GLOBAL);
- priv->showTrackers =
- trg_prefs_get_bool(priv->prefs, TRG_PREFS_KEY_FILTER_TRACKERS,
- TRG_PREFS_GLOBAL);
+ priv->showDirs = trg_prefs_get_bool(priv->prefs, TRG_PREFS_KEY_FILTER_DIRS,
+ TRG_PREFS_GLOBAL);
+ priv->showTrackers = trg_prefs_get_bool(priv->prefs,
+ TRG_PREFS_KEY_FILTER_TRACKERS, TRG_PREFS_GLOBAL);
return object;
}
void trg_state_selector_set_queues_enabled(TrgStateSelector * s,
- gboolean enabled)
-{
+ gboolean enabled) {
TrgStateSelectorPrivate *priv = TRG_STATE_SELECTOR_GET_PRIVATE(s);
- GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(s));
GtkTreeIter iter;
if (enabled) {
trg_state_selector_add_state(s, &iter, 2, GTK_STOCK_MEDIA_REWIND,
- _("Queue Down"),
- TORRENT_FLAG_DOWNLOADING_WAIT);
+ _("Queue Down"), TORRENT_FLAG_DOWNLOADING_WAIT, &priv->down_wait_rr);
trg_state_selector_add_state(s, &iter, 4, GTK_STOCK_MEDIA_FORWARD,
- _("Queue Up"),
- TORRENT_FLAG_SEEDING_WAIT);
+ _("Queue Up"), TORRENT_FLAG_SEEDING_WAIT, &priv->seed_wait_rr);
} else {
- gtk_tree_model_iter_nth_child(model, &iter, NULL, 4);
- gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
-
- gtk_tree_model_iter_nth_child(model, &iter, NULL, 2);
- gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
+ remove_row_ref_and_free(priv->seed_wait_rr);
+ remove_row_ref_and_free(priv->down_wait_rr);
+ priv->down_wait_rr = NULL;
+ priv->seed_wait_rr = NULL;
priv->n_categories -= 2;
}
}
-static void trg_state_selector_get_property(GObject * object,
- guint property_id,
- GValue * value,
- GParamSpec * pspec)
-{
+static void trg_state_selector_get_property(GObject * object, guint property_id,
+ GValue * value, GParamSpec * pspec) {
TrgStateSelectorPrivate *priv = TRG_STATE_SELECTOR_GET_PRIVATE(object);
switch (property_id) {
case PROP_CLIENT:
@@ -640,12 +630,8 @@ static void trg_state_selector_get_property(GObject * object,
}
}
-static void trg_state_selector_set_property(GObject * object,
- guint prop_id,
- const GValue * value,
- GParamSpec *
- pspec G_GNUC_UNUSED)
-{
+static void trg_state_selector_set_property(GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec G_GNUC_UNUSED) {
TrgStateSelectorPrivate *priv = TRG_STATE_SELECTOR_GET_PRIVATE(object);
switch (prop_id) {
@@ -656,40 +642,31 @@ static void trg_state_selector_set_property(GObject * object,
}
}
-static void trg_state_selector_class_init(TrgStateSelectorClass * klass)
-{
+static void trg_state_selector_class_init(TrgStateSelectorClass * klass) {
GObjectClass *object_class = G_OBJECT_CLASS(klass);
object_class->constructor = trg_state_selector_constructor;
object_class->set_property = trg_state_selector_set_property;
object_class->get_property = trg_state_selector_get_property;
signals[SELECTOR_STATE_CHANGED] = g_signal_new("torrent-state-changed",
- G_TYPE_FROM_CLASS
- (object_class),
- G_SIGNAL_RUN_LAST |
- G_SIGNAL_ACTION,
- G_STRUCT_OFFSET
- (TrgStateSelectorClass,
- torrent_state_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__UINT,
- G_TYPE_NONE, 1,
- G_TYPE_UINT);
-
- g_object_class_install_property(object_class,
- PROP_CLIENT,
- g_param_spec_object("client",
- "Client",
- "Client",
- TRG_TYPE_CLIENT,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY
- |
- G_PARAM_STATIC_NAME
- |
- G_PARAM_STATIC_NICK
- |
- G_PARAM_STATIC_BLURB));
+ G_TYPE_FROM_CLASS
+ (object_class), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET
+ (TrgStateSelectorClass,
+ torrent_state_changed), NULL, NULL,
+ g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT);
+
+ g_object_class_install_property(
+ object_class,
+ PROP_CLIENT,
+ g_param_spec_object(
+ "client",
+ "Client",
+ "Client",
+ TRG_TYPE_CLIENT,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY
+ | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK
+ | G_PARAM_STATIC_BLURB));
g_type_class_add_private(klass, sizeof(TrgStateSelectorPrivate));
}
diff --git a/src/trg-state-selector.h b/src/trg-state-selector.h
index 11b97a4..f002b3b 100644
--- a/src/trg-state-selector.h
+++ b/src/trg-state-selector.h
@@ -29,6 +29,7 @@
enum {
STATE_SELECTOR_ICON,
STATE_SELECTOR_NAME,
+ STATE_SELECTOR_COUNT,
STATE_SELECTOR_BIT,
STATE_SELECTOR_SERIAL,
STATE_SELECTOR_INDEX,
@@ -60,7 +61,7 @@ typedef struct {
} TrgStateSelectorClass;
GType trg_state_selector_get_type(void);
-TrgStateSelector *trg_state_selector_new(TrgClient * client);
+TrgStateSelector *trg_state_selector_new(TrgClient * client, TrgTorrentModel *tmodel);
G_END_DECLS guint32 trg_state_selector_get_flag(TrgStateSelector * s);
void trg_state_selector_update(TrgStateSelector * s);
diff --git a/src/trg-torrent-model.c b/src/trg-torrent-model.c
index 3dd7f9f..e46b876 100644
--- a/src/trg-torrent-model.c
+++ b/src/trg-torrent-model.c
@@ -54,7 +54,7 @@
enum {
TMODEL_TORRENT_COMPLETED,
TMODEL_TORRENT_ADDED,
- TMODEL_UPDATE_FILTERS,
+ TMODEL_STATE_CHANGED,
TMODEL_SIGNAL_COUNT
};
@@ -73,8 +73,7 @@ struct _TrgTorrentModelPrivate {
trg_torrent_model_update_stats stats;
};
-static void trg_torrent_model_dispose(GObject * object)
-{
+static void trg_torrent_model_dispose(GObject * object) {
TrgTorrentModelPrivate *priv = TRG_TORRENT_MODEL_GET_PRIVATE(object);
g_hash_table_destroy(priv->ht);
G_OBJECT_CLASS(trg_torrent_model_parent_class)->dispose(object);
@@ -82,69 +81,49 @@ static void trg_torrent_model_dispose(GObject * object)
static void
update_torrent_iter(TrgTorrentModel * model, TrgClient * tc, gint64 rpcv,
- gint64 serial, GtkTreeIter * iter, JsonObject * t,
- trg_torrent_model_update_stats * stats,
- gboolean * updateFilters);
+ gint64 serial, GtkTreeIter * iter, JsonObject * t,
+ trg_torrent_model_update_stats * stats, guint *whatsChanged);
-static void trg_torrent_model_class_init(TrgTorrentModelClass * klass)
-{
+static void trg_torrent_model_class_init(TrgTorrentModelClass * klass) {
GObjectClass *object_class = G_OBJECT_CLASS(klass);
g_type_class_add_private(klass, sizeof(TrgTorrentModelPrivate));
object_class->dispose = trg_torrent_model_dispose;
signals[TMODEL_TORRENT_COMPLETED] = g_signal_new("torrent-completed",
- G_TYPE_FROM_CLASS
- (object_class),
- G_SIGNAL_RUN_LAST |
- G_SIGNAL_ACTION,
- G_STRUCT_OFFSET
- (TrgTorrentModelClass,
- torrent_completed),
- NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1,
- G_TYPE_POINTER);
+ G_TYPE_FROM_CLASS
+ (object_class), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET
+ (TrgTorrentModelClass,
+ torrent_completed), NULL, NULL,
+ g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER);
signals[TMODEL_TORRENT_ADDED] = g_signal_new("torrent-added",
- G_TYPE_FROM_CLASS
- (object_class),
- G_SIGNAL_RUN_LAST |
- G_SIGNAL_ACTION,
- G_STRUCT_OFFSET
- (TrgTorrentModelClass,
- torrent_added), NULL,
- NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1,
- G_TYPE_POINTER);
-
- signals[TMODEL_UPDATE_FILTERS] = g_signal_new("update-filters",
- G_TYPE_FROM_CLASS
- (object_class),
- G_SIGNAL_RUN_LAST |
- G_SIGNAL_ACTION,
- G_STRUCT_OFFSET
- (TrgTorrentModelClass,
- torrent_removed), NULL,
- NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
+ G_TYPE_FROM_CLASS
+ (object_class), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET
+ (TrgTorrentModelClass,
+ torrent_added), NULL, NULL,
+ g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER);
+
+ signals[TMODEL_STATE_CHANGED] = g_signal_new("torrents-state-change",
+ G_TYPE_FROM_CLASS
+ (object_class), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET
+ (TrgTorrentModelClass,
+ torrent_removed), NULL, NULL, g_cclosure_marshal_VOID__UINT,
+ G_TYPE_NONE, 1, G_TYPE_UINT);
}
-trg_torrent_model_update_stats *trg_torrent_model_get_stats(TrgTorrentModel
- * model)
-{
+trg_torrent_model_update_stats *trg_torrent_model_get_stats(
+ TrgTorrentModel * model) {
TrgTorrentModelPrivate *priv = TRG_TORRENT_MODEL_GET_PRIVATE(model);
return &(priv->stats);
}
static void trg_torrent_model_count_peers(TrgTorrentModel * model,
- GtkTreeIter * iter,
- JsonObject * t)
-{
- GList *trackersList =
- json_array_get_elements(torrent_get_tracker_stats(t));
+ GtkTreeIter * iter, JsonObject * t) {
+ GList *trackersList = json_array_get_elements(torrent_get_tracker_stats(t));
gint seeders = 0;
gint leechers = 0;
gint downloads = 0;
@@ -161,12 +140,11 @@ static void trg_torrent_model_count_peers(TrgTorrentModel * model,
g_list_free(trackersList);
gtk_list_store_set(GTK_LIST_STORE(model), iter, TORRENT_COLUMN_SEEDS,
- seeders, TORRENT_COLUMN_LEECHERS, leechers,
- TORRENT_COLUMN_DOWNLOADS, downloads, -1);
+ seeders, TORRENT_COLUMN_LEECHERS, leechers,
+ TORRENT_COLUMN_DOWNLOADS, downloads, -1);
}
-static void trg_torrent_model_ref_free(gpointer data)
-{
+static void trg_torrent_model_ref_free(gpointer data) {
GtkTreeRowReference *rr = (GtkTreeRowReference *) data;
GtkTreeModel *model = gtk_tree_row_reference_get_model(rr);
GtkTreePath *path = gtk_tree_row_reference_get_path(rr);
@@ -174,14 +152,13 @@ static void trg_torrent_model_ref_free(gpointer data)
GtkTreeIter iter;
JsonObject *json;
if (gtk_tree_model_get_iter(model, &iter, path)) {
- gtk_tree_model_get(model, &iter, TORRENT_COLUMN_JSON, &json,
- -1);
+ gtk_tree_model_get(model, &iter, TORRENT_COLUMN_JSON, &json, -1);
json_object_unref(json);
g_object_set_data(G_OBJECT(model), PROP_REMOVE_IN_PROGRESS,
- GINT_TO_POINTER(TRUE));
+ GINT_TO_POINTER(TRUE));
gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
g_object_set_data(G_OBJECT(model), PROP_REMOVE_IN_PROGRESS,
- GINT_TO_POINTER(FALSE));
+ GINT_TO_POINTER(FALSE));
}
gtk_tree_path_free(path);
@@ -190,8 +167,7 @@ static void trg_torrent_model_ref_free(gpointer data)
gtk_tree_row_reference_free(rr);
}
-static void trg_torrent_model_init(TrgTorrentModel * self)
-{
+static void trg_torrent_model_init(TrgTorrentModel * self) {
TrgTorrentModelPrivate *priv = TRG_TORRENT_MODEL_GET_PRIVATE(self);
GType column_types[TORRENT_COLUMN_COLUMNS];
@@ -234,43 +210,35 @@ static void trg_torrent_model_init(TrgTorrentModel * self)
column_types[TORRENT_COLUMN_LASTACTIVE] = G_TYPE_INT64;
gtk_list_store_set_column_types(GTK_LIST_STORE(self),
- TORRENT_COLUMN_COLUMNS, column_types);
+ TORRENT_COLUMN_COLUMNS, column_types);
priv->ht = g_hash_table_new_full(g_int64_hash, g_int64_equal,
- (GDestroyNotify) g_free,
- trg_torrent_model_ref_free);
+ (GDestroyNotify) g_free, trg_torrent_model_ref_free);
g_object_set_data(G_OBJECT(self), PROP_REMOVE_IN_PROGRESS,
- GINT_TO_POINTER(FALSE));
+ GINT_TO_POINTER(FALSE));
priv->urlHostRegex = trg_uri_host_regex_new();
}
-gboolean trg_torrent_model_is_remove_in_progress(TrgTorrentModel * model)
-{
+gboolean trg_torrent_model_is_remove_in_progress(TrgTorrentModel * model) {
return (gboolean) GPOINTER_TO_INT(g_object_get_data
- (G_OBJECT(model),
- PROP_REMOVE_IN_PROGRESS));
+ (G_OBJECT(model),
+ PROP_REMOVE_IN_PROGRESS));
}
-static gboolean
-trg_torrent_model_reload_dir_aliases_foreachfunc(GtkTreeModel * model,
- GtkTreePath *
- path G_GNUC_UNUSED,
- GtkTreeIter * iter,
- gpointer gdata)
-{
+static gboolean trg_torrent_model_reload_dir_aliases_foreachfunc(
+ GtkTreeModel * model, GtkTreePath * path G_GNUC_UNUSED,
+ GtkTreeIter * iter, gpointer gdata) {
gchar *downloadDir, *shortDownloadDir;
- gtk_tree_model_get(model, iter, TORRENT_COLUMN_DOWNLOADDIR,
- &downloadDir, -1);
+ gtk_tree_model_get(model, iter, TORRENT_COLUMN_DOWNLOADDIR, &downloadDir,
+ -1);
- shortDownloadDir =
- shorten_download_dir((TrgClient *) gdata, downloadDir);
+ shortDownloadDir = shorten_download_dir((TrgClient *) gdata, downloadDir);
gtk_list_store_set(GTK_LIST_STORE(model), iter,
- TORRENT_COLUMN_DOWNLOADDIR_SHORT, shortDownloadDir,
- -1);
+ TORRENT_COLUMN_DOWNLOADDIR_SHORT, shortDownloadDir, -1);
g_free(downloadDir);
g_free(shortDownloadDir);
@@ -278,57 +246,68 @@ trg_torrent_model_reload_dir_aliases_foreachfunc(GtkTreeModel * model,
return FALSE;
}
-void trg_torrent_model_reload_dir_aliases(TrgClient * tc,
- GtkTreeModel * model)
-{
+void trg_torrent_model_reload_dir_aliases(TrgClient * tc, GtkTreeModel * model) {
gtk_tree_model_foreach(model,
- trg_torrent_model_reload_dir_aliases_foreachfunc,
- tc);
+ trg_torrent_model_reload_dir_aliases_foreachfunc, tc);
}
-static gboolean trg_torrent_model_stats_scan_foreachfunc(GtkTreeModel *
- model,
- GtkTreePath *
- path
- G_GNUC_UNUSED,
- GtkTreeIter *
- iter,
- gpointer gdata)
-{
+static gboolean trg_torrent_model_stats_scan_foreachfunc(GtkTreeModel * model,
+ GtkTreePath * path G_GNUC_UNUSED, GtkTreeIter * iter, gpointer gdata) {
trg_torrent_model_update_stats *stats =
- (trg_torrent_model_update_stats *) gdata;
+ (trg_torrent_model_update_stats *) gdata;
guint flags;
gtk_tree_model_get(model, iter, TORRENT_COLUMN_FLAGS, &flags, -1);
- if (flags & TORRENT_FLAG_SEEDING)
+ if (flags & TORRENT_FLAG_SEEDING
+ )
stats->seeding++;
- else if (flags & TORRENT_FLAG_DOWNLOADING)
+ else if (flags & TORRENT_FLAG_DOWNLOADING
+ )
stats->down++;
- else if (flags & TORRENT_FLAG_PAUSED)
+ else if (flags & TORRENT_FLAG_PAUSED
+ )
stats->paused++;
- if (flags & TORRENT_FLAG_ERROR)
+ if (flags & TORRENT_FLAG_ERROR
+ )
stats->error++;
+ if (flags & TORRENT_FLAG_COMPLETE
+ )
+ stats->complete++;
+ else
+ stats->incomplete++;
+
+ if (flags & TORRENT_FLAG_CHECKING
+ )
+ stats->checking++;
+
+ if (flags & TORRENT_FLAG_ACTIVE
+ )
+ stats->active++;
+
+ if (flags & TORRENT_FLAG_SEEDING_WAIT)
+ stats->seed_wait++;
+
+ if (flags & TORRENT_FLAG_DOWNLOADING_WAIT)
+ stats->down_wait++;
+
stats->count++;
return FALSE;
}
-void trg_torrent_model_remove_all(TrgTorrentModel * model)
-{
+void trg_torrent_model_remove_all(TrgTorrentModel * model) {
TrgTorrentModelPrivate *priv = TRG_TORRENT_MODEL_GET_PRIVATE(model);
g_hash_table_remove_all(priv->ht);
gtk_list_store_clear(GTK_LIST_STORE(model));
}
-gchar *shorten_download_dir(TrgClient * tc, const gchar * downloadDir)
-{
+gchar *shorten_download_dir(TrgClient * tc, const gchar * downloadDir) {
TrgPrefs *prefs = trg_client_get_prefs(tc);
- JsonArray *labels =
- trg_prefs_get_array(prefs, TRG_PREFS_KEY_DESTINATIONS,
- TRG_PREFS_CONNECTION);
+ JsonArray *labels = trg_prefs_get_array(prefs, TRG_PREFS_KEY_DESTINATIONS,
+ TRG_PREFS_CONNECTION);
JsonObject *session = trg_client_get_session(tc);
const gchar *defaultDownloadDir = session_get_download_dir(session);
gchar *shortDownloadDir = NULL;
@@ -338,15 +317,13 @@ gchar *shorten_download_dir(TrgClient * tc, const gchar * downloadDir)
if (labelsList) {
GList *li;
for (li = labelsList; li; li = g_list_next(li)) {
- JsonObject *labelObj = json_node_get_object((JsonNode *)
- li->data);
- const gchar *labelDir =
- json_object_get_string_member(labelObj,
- TRG_PREFS_KEY_DESTINATIONS_SUBKEY_DIR);
+ JsonObject *labelObj = json_node_get_object(
+ (JsonNode *) li->data);
+ const gchar *labelDir = json_object_get_string_member(labelObj,
+ TRG_PREFS_KEY_DESTINATIONS_SUBKEY_DIR);
if (!g_strcmp0(downloadDir, labelDir)) {
- const gchar *labelLabel =
- json_object_get_string_member(labelObj,
- TRG_PREFS_SUBKEY_LABEL);
+ const gchar *labelLabel = json_object_get_string_member(
+ labelObj, TRG_PREFS_SUBKEY_LABEL);
shortDownloadDir = g_strdup(labelLabel);
break;
}
@@ -374,13 +351,9 @@ gchar *shorten_download_dir(TrgClient * tc, const gchar * downloadDir)
return g_strdup(downloadDir);
}
-static inline void update_torrent_iter(TrgTorrentModel * model,
- TrgClient * tc, gint64 rpcv,
- gint64 serial, GtkTreeIter * iter,
- JsonObject * t,
- trg_torrent_model_update_stats *
- stats, gboolean * updateFilters)
-{
+static inline void update_torrent_iter(TrgTorrentModel * model, TrgClient * tc,
+ gint64 rpcv, gint64 serial, GtkTreeIter * iter, JsonObject * t,
+ trg_torrent_model_update_stats * stats, guint *whatsChanged) {
TrgTorrentModelPrivate *priv = TRG_TORRENT_MODEL_GET_PRIVATE(model);
GtkListStore *ls = GTK_LIST_STORE(model);
guint lastFlags, newFlags;
@@ -413,165 +386,161 @@ static inline void update_torrent_iter(TrgTorrentModel * model,
trackerStats = torrent_get_tracker_stats(t);
gtk_tree_model_get(GTK_TREE_MODEL(model), iter, TORRENT_COLUMN_FLAGS,
- &lastFlags, TORRENT_COLUMN_JSON, &lastJson,
- TORRENT_COLUMN_DOWNLOADDIR, &lastDownloadDir, -1);
+ &lastFlags, TORRENT_COLUMN_JSON, &lastJson,
+ TORRENT_COLUMN_DOWNLOADDIR, &lastDownloadDir, -1);
json_object_ref(t);
if (json_array_get_length(trackerStats) > 0) {
- JsonObject *firstTracker =
- json_array_get_object_element(trackerStats,
- 0);
+ JsonObject *firstTracker = json_array_get_object_element(trackerStats,
+ 0);
firstTrackerHost = trg_gregex_get_first(priv->urlHostRegex,
- tracker_stats_get_host
- (firstTracker));
+ tracker_stats_get_host(firstTracker));
}
lpd = peerfrom_get_lpd(pf);
if (newFlags & TORRENT_FLAG_ACTIVE) {
if (lpd >= 0) {
- peerSources =
- g_strdup_printf("%ld / %ld / %ld / %ld / %ld / %ld / %ld",
- peerfrom_get_trackers(pf),
- peerfrom_get_incoming(pf),
- peerfrom_get_ltep(pf),
- peerfrom_get_dht(pf), peerfrom_get_pex(pf),
- lpd, peerfrom_get_resume(pf));
+ peerSources = g_strdup_printf(
+ "%ld / %ld / %ld / %ld / %ld / %ld / %ld",
+ peerfrom_get_trackers(pf), peerfrom_get_incoming(pf),
+ peerfrom_get_ltep(pf), peerfrom_get_dht(pf),
+ peerfrom_get_pex(pf), lpd, peerfrom_get_resume(pf));
} else {
- peerSources =
- g_strdup_printf("%ld / %ld / %ld / %ld / %ld / N/A / %ld",
- peerfrom_get_trackers(pf),
- peerfrom_get_incoming(pf),
- peerfrom_get_ltep(pf),
- peerfrom_get_dht(pf), peerfrom_get_pex(pf),
- peerfrom_get_resume(pf));
+ peerSources = g_strdup_printf(
+ "%ld / %ld / %ld / %ld / %ld / N/A / %ld",
+ peerfrom_get_trackers(pf), peerfrom_get_incoming(pf),
+ peerfrom_get_ltep(pf), peerfrom_get_dht(pf),
+ peerfrom_get_pex(pf), peerfrom_get_resume(pf));
}
}
#ifdef DEBUG
gtk_list_store_set(ls, iter, TORRENT_COLUMN_ICON, statusIcon, -1);
gtk_list_store_set(ls, iter,
- TORRENT_COLUMN_NAME, torrent_get_name(t), -1);
+ TORRENT_COLUMN_NAME, torrent_get_name(t), -1);
gtk_list_store_set(ls, iter,
- TORRENT_COLUMN_SIZE, torrent_get_size(t), -1);
+ TORRENT_COLUMN_SIZE, torrent_get_size(t), -1);
gtk_list_store_set(ls, iter,
- TORRENT_COLUMN_DONE,
- (newFlags & TORRENT_FLAG_CHECKING) ?
- torrent_get_recheck_progress(t)
- : torrent_get_percent_done(t), -1);
+ TORRENT_COLUMN_DONE,
+ (newFlags & TORRENT_FLAG_CHECKING) ?
+ torrent_get_recheck_progress(t)
+ : torrent_get_percent_done(t), -1);
gtk_list_store_set(ls, iter, TORRENT_COLUMN_STATUS, statusString, -1);
gtk_list_store_set(ls, iter, TORRENT_COLUMN_DOWNSPEED, downRate, -1);
gtk_list_store_set(ls, iter, TORRENT_COLUMN_FLAGS, newFlags, -1);
gtk_list_store_set(ls, iter, TORRENT_COLUMN_UPSPEED, upRate, -1);
gtk_list_store_set(ls, iter, TORRENT_COLUMN_ETA,
- torrent_get_eta(t), -1);
+ torrent_get_eta(t), -1);
gtk_list_store_set(ls, iter, TORRENT_COLUMN_UPLOADED, uploaded, -1);
gtk_list_store_set(ls, iter,
- TORRENT_COLUMN_DOWNLOADED, downloaded, -1);
+ TORRENT_COLUMN_DOWNLOADED, downloaded, -1);
gtk_list_store_set(ls, iter, TORRENT_COLUMN_RATIO,
- uploaded > 0
- && downloaded >
- 0 ? (double) uploaded / (double) downloaded : 0,
- -1);
+ uploaded > 0
+ && downloaded >
+ 0 ? (double) uploaded / (double) downloaded : 0,
+ -1);
gtk_list_store_set(ls, iter, TORRENT_COLUMN_ID, id, -1);
gtk_list_store_set(ls, iter, TORRENT_COLUMN_JSON, t, -1);
gtk_list_store_set(ls, iter, TORRENT_COLUMN_UPDATESERIAL, serial, -1);
gtk_list_store_set(ls, iter,
- TORRENT_COLUMN_ADDED, torrent_get_added_date(t),
- -1);
+ TORRENT_COLUMN_ADDED, torrent_get_added_date(t),
+ -1);
gtk_list_store_set(ls, iter, TORRENT_COLUMN_DOWNLOADDIR,
- downloadDir, -1);
+ downloadDir, -1);
gtk_list_store_set(ls, iter, TORRENT_COLUMN_BANDWIDTH_PRIORITY,
- torrent_get_bandwidth_priority(t), -1);
+ torrent_get_bandwidth_priority(t), -1);
gtk_list_store_set(ls, iter, TORRENT_COLUMN_DONE_DATE,
- torrent_get_done_date(t), -1);
+ torrent_get_done_date(t), -1);
gtk_list_store_set(ls, iter, TORRENT_COLUMN_FROMPEX,
- peerfrom_get_pex(pf), -1);
+ peerfrom_get_pex(pf), -1);
gtk_list_store_set(ls, iter, TORRENT_COLUMN_FROMDHT,
- peerfrom_get_dht(pf), -1);
+ peerfrom_get_dht(pf), -1);
gtk_list_store_set(ls, iter, TORRENT_COLUMN_FROMTRACKERS,
- peerfrom_get_trackers(pf), -1);
+ peerfrom_get_trackers(pf), -1);
gtk_list_store_set(ls, iter, TORRENT_COLUMN_FROMLTEP,
- peerfrom_get_ltep(pf), -1);
+ peerfrom_get_ltep(pf), -1);
gtk_list_store_set(ls, iter, TORRENT_COLUMN_FROMRESUME,
- peerfrom_get_resume(pf), -1);
+ peerfrom_get_resume(pf), -1);
gtk_list_store_set(ls, iter, TORRENT_COLUMN_FROMINCOMING,
- peerfrom_get_incoming(pf), -1);
+ peerfrom_get_incoming(pf), -1);
gtk_list_store_set(ls, iter, TORRENT_COLUMN_PEER_SOURCES,
- peerSources, -1);
+ peerSources, -1);
gtk_list_store_set(ls, iter, TORRENT_COLUMN_PEERS_CONNECTED,
- torrent_get_peers_connected(t), -1);
+ torrent_get_peers_connected(t), -1);
gtk_list_store_set(ls, iter, TORRENT_COLUMN_PEERS_TO_US,
- torrent_get_peers_sending_to_us(t), -1);
+ torrent_get_peers_sending_to_us(t), -1);
gtk_list_store_set(ls, iter, TORRENT_COLUMN_PEERS_FROM_US,
- torrent_get_peers_getting_from_us(t), -1);
+ torrent_get_peers_getting_from_us(t), -1);
gtk_list_store_set(ls, iter, TORRENT_COLUMN_TRACKERHOST,
- firstTrackerHost ? firstTrackerHost : "", -1);
+ firstTrackerHost ? firstTrackerHost : "", -1);
gtk_list_store_set(ls, iter, TORRENT_COLUMN_QUEUE_POSITION,
- torrent_get_queue_position(t), -1);
+ torrent_get_queue_position(t), -1);
gtk_list_store_set(ls, iter, TORRENT_COLUMN_LASTACTIVE,
- torrent_get_activity_date(t), -1);
+ torrent_get_activity_date(t), -1);
#else
gtk_list_store_set(ls, iter, TORRENT_COLUMN_ICON, statusIcon,
- TORRENT_COLUMN_ADDED, torrent_get_added_date(t),
- TORRENT_COLUMN_DONE_DATE, torrent_get_done_date(t),
- TORRENT_COLUMN_NAME, torrent_get_name(t),
- TORRENT_COLUMN_SIZE, torrent_get_size(t),
- TORRENT_COLUMN_DONE,
- (newFlags & TORRENT_FLAG_CHECKING) ?
- torrent_get_recheck_progress(t)
- : torrent_get_percent_done(t),
- TORRENT_COLUMN_STATUS, statusString,
- TORRENT_COLUMN_DOWNSPEED, downRate,
- TORRENT_COLUMN_FLAGS, newFlags,
- TORRENT_COLUMN_UPSPEED, upRate, TORRENT_COLUMN_ETA,
- torrent_get_eta(t), TORRENT_COLUMN_UPLOADED,
- uploaded, TORRENT_COLUMN_DOWNLOADED, downloaded,
- TORRENT_COLUMN_FROMPEX, peerfrom_get_pex(pf),
- TORRENT_COLUMN_FROMDHT, peerfrom_get_dht(pf),
- TORRENT_COLUMN_FROMTRACKERS,
- peerfrom_get_trackers(pf), TORRENT_COLUMN_FROMLTEP,
- peerfrom_get_ltep(pf), TORRENT_COLUMN_FROMRESUME,
- peerfrom_get_resume(pf),
- TORRENT_COLUMN_FROMINCOMING,
- peerfrom_get_incoming(pf),
- TORRENT_COLUMN_PEER_SOURCES, peerSources,
- TORRENT_COLUMN_PEERS_CONNECTED,
- torrent_get_peers_connected(t),
- TORRENT_COLUMN_PEERS_TO_US,
- torrent_get_peers_sending_to_us(t),
- TORRENT_COLUMN_PEERS_FROM_US,
- torrent_get_peers_getting_from_us(t),
- TORRENT_COLUMN_QUEUE_POSITION,
- torrent_get_queue_position(t),
- TORRENT_COLUMN_LASTACTIVE,
- torrent_get_activity_date(t), TORRENT_COLUMN_RATIO,
- uploaded > 0
- && downloaded >
- 0 ? (double) uploaded / (double) downloaded : 0,
- TORRENT_COLUMN_DOWNLOADDIR, downloadDir,
- TORRENT_COLUMN_BANDWIDTH_PRIORITY,
- torrent_get_bandwidth_priority(t),
- TORRENT_COLUMN_ID, id, TORRENT_COLUMN_JSON, t,
- TORRENT_COLUMN_TRACKERHOST,
- firstTrackerHost ? firstTrackerHost : "",
- TORRENT_COLUMN_UPDATESERIAL, serial, -1);
+ TORRENT_COLUMN_ADDED, torrent_get_added_date(t),
+ TORRENT_COLUMN_DONE_DATE, torrent_get_done_date(t),
+ TORRENT_COLUMN_NAME, torrent_get_name(t), TORRENT_COLUMN_SIZE,
+ torrent_get_size(t), TORRENT_COLUMN_DONE,
+ (newFlags & TORRENT_FLAG_CHECKING) ?
+ torrent_get_recheck_progress(t)
+ : torrent_get_percent_done(t),
+ TORRENT_COLUMN_STATUS, statusString,
+ TORRENT_COLUMN_DOWNSPEED, downRate,
+ TORRENT_COLUMN_FLAGS, newFlags,
+ TORRENT_COLUMN_UPSPEED, upRate, TORRENT_COLUMN_ETA,
+ torrent_get_eta(t), TORRENT_COLUMN_UPLOADED,
+ uploaded, TORRENT_COLUMN_DOWNLOADED, downloaded,
+ TORRENT_COLUMN_FROMPEX, peerfrom_get_pex(pf),
+ TORRENT_COLUMN_FROMDHT, peerfrom_get_dht(pf),
+ TORRENT_COLUMN_FROMTRACKERS,
+ peerfrom_get_trackers(pf), TORRENT_COLUMN_FROMLTEP,
+ peerfrom_get_ltep(pf), TORRENT_COLUMN_FROMRESUME,
+ peerfrom_get_resume(pf),
+ TORRENT_COLUMN_FROMINCOMING,
+ peerfrom_get_incoming(pf),
+ TORRENT_COLUMN_PEER_SOURCES, peerSources,
+ TORRENT_COLUMN_PEERS_CONNECTED,
+ torrent_get_peers_connected(t),
+ TORRENT_COLUMN_PEERS_TO_US,
+ torrent_get_peers_sending_to_us(t),
+ TORRENT_COLUMN_PEERS_FROM_US,
+ torrent_get_peers_getting_from_us(t),
+ TORRENT_COLUMN_QUEUE_POSITION,
+ torrent_get_queue_position(t),
+ TORRENT_COLUMN_LASTACTIVE,
+ torrent_get_activity_date(t), TORRENT_COLUMN_RATIO,
+ uploaded > 0
+ && downloaded >
+ 0 ? (double) uploaded / (double) downloaded : 0,
+ TORRENT_COLUMN_DOWNLOADDIR, downloadDir,
+ TORRENT_COLUMN_BANDWIDTH_PRIORITY,
+ torrent_get_bandwidth_priority(t),
+ TORRENT_COLUMN_ID, id, TORRENT_COLUMN_JSON, t,
+ TORRENT_COLUMN_TRACKERHOST,
+ firstTrackerHost ? firstTrackerHost : "",
+ TORRENT_COLUMN_UPDATESERIAL, serial, -1);
#endif
if (!lastDownloadDir || g_strcmp0(downloadDir, lastDownloadDir)) {
gchar *shortDownloadDir = shorten_download_dir(tc, downloadDir);
gtk_list_store_set(ls, iter, TORRENT_COLUMN_DOWNLOADDIR_SHORT,
- shortDownloadDir, -1);
+ shortDownloadDir, -1);
g_free(shortDownloadDir);
- *updateFilters = TRUE;
+ *whatsChanged |= TORRENT_UPDATE_PATH_CHANGE;
}
if (lastJson)
json_object_unref(lastJson);
if ((lastFlags & TORRENT_FLAG_DOWNLOADING)
- && (newFlags & TORRENT_FLAG_COMPLETE))
+ && (newFlags & TORRENT_FLAG_COMPLETE))
g_signal_emit(model, signals[TMODEL_TORRENT_COMPLETED], 0, iter);
+ if (lastFlags != newFlags)
+ *whatsChanged |= TORRENT_UPDATE_STATE_CHANGE;
+
trg_torrent_model_count_peers(model, iter, t);
if (firstTrackerHost)
@@ -585,8 +554,7 @@ static inline void update_torrent_iter(TrgTorrentModel * model,
g_free(statusIcon);
}
-TrgTorrentModel *trg_torrent_model_new(void)
-{
+TrgTorrentModel *trg_torrent_model_new(void) {
return g_object_new(TRG_TYPE_TORRENT_MODEL, NULL);
}
@@ -595,23 +563,18 @@ struct TrgModelRemoveData {
gint64 currentSerial;
};
-GHashTable *get_torrent_table(TrgTorrentModel * model)
-{
+GHashTable *get_torrent_table(TrgTorrentModel * model) {
TrgTorrentModelPrivate *priv = TRG_TORRENT_MODEL_GET_PRIVATE(model);
return priv->ht;
}
gboolean trg_model_find_removed_foreachfunc(GtkTreeModel * model,
- GtkTreePath *
- path G_GNUC_UNUSED,
- GtkTreeIter * iter,
- gpointer gdata)
-{
+ 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);
+ gtk_tree_model_get(model, iter, TORRENT_COLUMN_UPDATESERIAL, &rowSerial,
+ -1);
if (rowSerial != args->currentSerial) {
gint64 *id = g_new(gint64, 1);
@@ -623,21 +586,19 @@ gboolean trg_model_find_removed_foreachfunc(GtkTreeModel * model,
}
GList *trg_torrent_model_find_removed(GtkTreeModel * model,
- gint64 currentSerial)
-{
+ 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);
+ trg_model_find_removed_foreachfunc, &args);
return args.toRemove;
}
gboolean get_torrent_data(GHashTable * table, gint64 id, JsonObject ** t,
- GtkTreeIter * out_iter)
-{
+ GtkTreeIter * out_iter) {
gpointer result = g_hash_table_lookup(table, &id);
gboolean found = FALSE;
@@ -651,8 +612,7 @@ gboolean get_torrent_data(GHashTable * table, gint64 id, JsonObject ** t,
if (out_iter)
*out_iter = iter;
if (t)
- gtk_tree_model_get(model, &iter, TORRENT_COLUMN_JSON, t,
- -1);
+ gtk_tree_model_get(model, &iter, TORRENT_COLUMN_JSON, t, -1);
found = TRUE;
gtk_tree_path_free(path);
}
@@ -661,13 +621,16 @@ gboolean get_torrent_data(GHashTable * table, gint64 id, JsonObject ** t,
return found;
}
-trg_torrent_model_update_stats *trg_torrent_model_update(TrgTorrentModel *
- model,
- TrgClient * tc,
- JsonObject *
- response,
- gint mode)
-{
+static void trg_torrent_model_stat_counts_clear(
+ trg_torrent_model_update_stats *stats) {
+ stats->count = stats->down = stats->error = stats->paused = stats->seeding =
+ stats->complete = stats->incomplete = stats->active =
+ stats->checking = stats->seed_wait = stats->down_wait = 0;
+}
+
+trg_torrent_model_update_stats *trg_torrent_model_update(
+ TrgTorrentModel * model, TrgClient * tc, JsonObject * response,
+ gint mode) {
TrgTorrentModelPrivate *priv = TRG_TORRENT_MODEL_GET_PRIVATE(model);
GList *torrentList;
@@ -680,28 +643,30 @@ trg_torrent_model_update_stats *trg_torrent_model_update(TrgTorrentModel *
GtkTreePath *path;
GtkTreeRowReference *rr;
gpointer *result;
- gboolean updateFilters = FALSE;
+ guint whatsChanged = 0;
gint64 rpcv = trg_client_get_rpc_version(tc);
args = get_arguments(response);
torrentList = json_array_get_elements(get_torrents(args));
- memset(&(priv->stats), 0, sizeof(trg_torrent_model_update_stats));
+ priv->stats.downRateTotal = 0;
+ priv->stats.upRateTotal = 0;
for (li = torrentList; li; li = g_list_next(li)) {
t = json_node_get_object((JsonNode *) li->data);
id = torrent_get_id(t);
result =
- mode == TORRENT_GET_MODE_FIRST ? NULL :
- g_hash_table_lookup(priv->ht, &id);
+ mode == TORRENT_GET_MODE_FIRST ? NULL :
+ g_hash_table_lookup(priv->ht, &id);
if (!result) {
gtk_list_store_append(GTK_LIST_STORE(model), &iter);
+ whatsChanged |= TORRENT_UPDATE_ADDREMOVE;
update_torrent_iter(model, tc, rpcv, trg_client_get_serial(tc),
- &iter, t, &(priv->stats), &updateFilters);
+ &iter, t, &(priv->stats), &whatsChanged);
path = gtk_tree_model_get_path(GTK_TREE_MODEL(model), &iter);
rr = gtk_tree_row_reference_new(GTK_TREE_MODEL(model), path);
@@ -709,18 +674,19 @@ trg_torrent_model_update_stats *trg_torrent_model_update(TrgTorrentModel *
*idCopy = id;
g_hash_table_insert(priv->ht, idCopy, rr);
gtk_tree_path_free(path);
- if (mode != TORRENT_GET_MODE_FIRST)
- g_signal_emit(model, signals[TMODEL_TORRENT_ADDED], 0,
- &iter);
+
+ if (mode != TORRENT_GET_MODE_FIRST
+ )
+ g_signal_emit(model, signals[TMODEL_TORRENT_ADDED], 0, &iter);
} else {
- path = gtk_tree_row_reference_get_path((GtkTreeRowReference *)
- result);
+ path = gtk_tree_row_reference_get_path(
+ (GtkTreeRowReference *) result);
if (path) {
if (gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter,
- path)) {
+ path)) {
update_torrent_iter(model, tc, rpcv,
- trg_client_get_serial(tc), &iter,
- t, &(priv->stats), &updateFilters);
+ trg_client_get_serial(tc), &iter, t, &(priv->stats),
+ &whatsChanged);
}
gtk_tree_path_free(path);
}
@@ -730,15 +696,14 @@ trg_torrent_model_update_stats *trg_torrent_model_update(TrgTorrentModel *
g_list_free(torrentList);
if (mode == TORRENT_GET_MODE_UPDATE) {
- GList *hitlist =
- trg_torrent_model_find_removed(GTK_TREE_MODEL(model),
- trg_client_get_serial(tc));
+ GList *hitlist = trg_torrent_model_find_removed(GTK_TREE_MODEL(model),
+ trg_client_get_serial(tc));
if (hitlist) {
for (li = hitlist; li; li = g_list_next(li)) {
g_hash_table_remove(priv->ht, li->data);
g_free(li->data);
}
- updateFilters = TRUE;
+ whatsChanged |= TORRENT_UPDATE_ADDREMOVE;
g_list_free(hitlist);
}
} else if (mode > TORRENT_GET_MODE_FIRST) {
@@ -748,18 +713,18 @@ trg_torrent_model_update_stats *trg_torrent_model_update(TrgTorrentModel *
for (li = hitlist; li; li = g_list_next(li)) {
id = json_node_get_int((JsonNode *) li->data);
g_hash_table_remove(priv->ht, &id);
- updateFilters = TRUE;
+ whatsChanged |= TORRENT_UPDATE_ADDREMOVE;
}
g_list_free(hitlist);
}
}
- if (updateFilters)
- g_signal_emit(model, signals[TMODEL_UPDATE_FILTERS], 0);
-
- gtk_tree_model_foreach(GTK_TREE_MODEL(model),
- trg_torrent_model_stats_scan_foreachfunc,
- &(priv->stats));
+ if (whatsChanged != 0) {
+ trg_torrent_model_stat_counts_clear(&priv->stats);
+ gtk_tree_model_foreach(GTK_TREE_MODEL(model),
+ trg_torrent_model_stats_scan_foreachfunc, &(priv->stats));
+ g_signal_emit(model, signals[TMODEL_STATE_CHANGED], 0, whatsChanged);
+ }
return &(priv->stats);
}
diff --git a/src/trg-torrent-model.h b/src/trg-torrent-model.h
index 2a108c9..f245455 100644
--- a/src/trg-torrent-model.h
+++ b/src/trg-torrent-model.h
@@ -59,8 +59,18 @@ typedef struct {
gint paused;
gint count;
gint error;
+ gint complete;
+ gint incomplete;
+ gint checking;
+ gint active;
+ gint seed_wait;
+ gint down_wait;
} trg_torrent_model_update_stats;
+#define TORRENT_UPDATE_STATE_CHANGE (1 << 0)
+#define TORRENT_UPDATE_PATH_CHANGE (1 << 1)
+#define TORRENT_UPDATE_ADDREMOVE (1 << 2)
+
GType trg_torrent_model_get_type(void);
TrgTorrentModel *trg_torrent_model_new();