summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Alan Fitton <ajf@eth0.org.uk>2011-12-21 00:32:54 +0000
committerGravatar Alan Fitton <ajf@eth0.org.uk>2011-12-21 00:32:54 +0000
commitec64e995ab1467596e75fb0aebda63bb047aefa5 (patch)
tree07d4d1f73b33085b8f87d9c0ae56a2548a1bc9be
parent980ecb422cb29f93f5fe51b633be46cde36cedc6 (diff)
file trees :D may do cascading priority changes sometime, but this is a start. also use GTK_STOCK_FILE if mime/extension detection fails.
-rw-r--r--src/Makefile.am1
-rw-r--r--src/torrent.c5
-rw-r--r--src/torrent.h2
-rw-r--r--src/trg-cell-renderer-file-icon.c157
-rw-r--r--src/trg-cell-renderer-file-icon.h51
-rw-r--r--src/trg-cell-renderer-priority.c11
-rw-r--r--src/trg-cell-renderer-size.c1
-rw-r--r--src/trg-files-model.c267
-rw-r--r--src/trg-files-model.h6
-rw-r--r--src/trg-files-tree-view.c52
-rw-r--r--src/trg-main-window.c18
-rw-r--r--src/trg-peers-tree-view.c2
-rw-r--r--src/trg-torrent-tree-view.c2
-rw-r--r--src/trg-trackers-tree-view.c2
-rw-r--r--src/trg-tree-view.c28
-rw-r--r--src/trg-tree-view.h4
-rw-r--r--src/util.c20
17 files changed, 481 insertions, 148 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 7345485..a2243b6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -83,6 +83,7 @@ transmission_remote_gtk_SOURCES = main.c \
trg-cell-renderer-eta.c \
trg-remote-prefs-dialog.c \
trg-cell-renderer-priority.c \
+ trg-cell-renderer-file-icon.c \
trg-cell-renderer-epoch.c \
trg-cell-renderer-numgteqthan.c \
trg-torrent-move-dialog.c \
diff --git a/src/torrent.c b/src/torrent.c
index c7562a4..ab123c3 100644
--- a/src/torrent.c
+++ b/src/torrent.c
@@ -606,11 +606,10 @@ gint64 peerfrom_get_lpd(JsonObject * pf)
/* files */
-gdouble file_get_progress(JsonObject * f)
+gdouble file_get_progress(gint64 length, gint64 completed)
{
- gint64 length = file_get_length(f);
if (length > 0) {
- return ((gdouble) file_get_bytes_completed(f) /
+ return ((gdouble) completed /
(gdouble) length) * 100.0;
} else {
return 0.0;
diff --git a/src/torrent.h b/src/torrent.h
index daca8c2..7270d6d 100644
--- a/src/torrent.h
+++ b/src/torrent.h
@@ -118,7 +118,7 @@ gint64 tracker_stats_get_last_scrape_time(JsonObject * t);
gint64 file_get_length(JsonObject * f);
gint64 file_get_bytes_completed(JsonObject * f);
const gchar *file_get_name(JsonObject * f);
-gdouble file_get_progress(JsonObject * f);
+gdouble file_get_progress(gint64 length, gint64 completed);
/* peers */
diff --git a/src/trg-cell-renderer-file-icon.c b/src/trg-cell-renderer-file-icon.c
new file mode 100644
index 0000000..de29cb9
--- /dev/null
+++ b/src/trg-cell-renderer-file-icon.c
@@ -0,0 +1,157 @@
+/*
+ * transmission-remote-gtk - Transmission RPC client for GTK
+ * Copyright (C) 2011 Alan Fitton
+
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdint.h>
+#include <gtk/gtk.h>
+
+#include "trg-cell-renderer-file-icon.h"
+#include "util.h"
+
+enum {
+ PROP_0,
+ PROP_FILE_ID,
+ PROP_FILE_NAME
+};
+
+G_DEFINE_TYPE(TrgCellRendererFileIcon, trg_cell_renderer_file_icon,
+ GTK_TYPE_CELL_RENDERER_PIXBUF)
+#define TRG_CELL_RENDERER_FILE_ICON_GET_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRG_TYPE_CELL_RENDERER_FILE_ICON, TrgCellRendererFileIconPrivate))
+typedef struct _TrgCellRendererFileIconPrivate TrgCellRendererFileIconPrivate;
+
+struct _TrgCellRendererFileIconPrivate {
+ gint64 file_id;
+ gchar *text;
+};
+
+static void
+trg_cell_renderer_file_icon_get_property(GObject * object, guint property_id,
+ GValue * value, GParamSpec * pspec)
+{
+ TrgCellRendererFileIconPrivate *priv =
+ TRG_CELL_RENDERER_FILE_ICON_GET_PRIVATE(object);
+ switch (property_id) {
+ case PROP_FILE_ID:
+ g_value_set_int64(value, priv->file_id);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+ break;
+ }
+}
+
+static void trg_cell_renderer_file_icon_refresh(TrgCellRendererFileIcon *fi)
+{
+ TrgCellRendererFileIconPrivate *priv =
+ TRG_CELL_RENDERER_FILE_ICON_GET_PRIVATE(fi);
+
+ if (priv->file_id == -2) {
+ return;
+ } else if (priv->file_id == -1) {
+ g_object_set(fi, "stock-id", GTK_STOCK_DIRECTORY, NULL);
+ } else if (priv->text) {
+ gboolean uncertain;
+ gchar *mimetype = g_content_type_guess(priv->text, NULL, 0, &uncertain);
+ GIcon *icon = NULL;
+
+ if (!uncertain && mimetype)
+ icon = g_content_type_get_icon(mimetype);
+
+ g_free(mimetype);
+
+ if (icon) {
+ g_object_set(fi, "gicon", icon, NULL);
+ g_object_unref(icon);
+ } else {
+ g_object_set(fi, "stock-id", GTK_STOCK_FILE, NULL);
+ }
+ }
+}
+
+static void
+trg_cell_renderer_file_icon_set_property(GObject * object, guint property_id,
+ const GValue * value,
+ GParamSpec * pspec)
+{
+ TrgCellRendererFileIconPrivate *priv =
+ TRG_CELL_RENDERER_FILE_ICON_GET_PRIVATE(object);
+ if (property_id == PROP_FILE_ID) {
+ priv->file_id = g_value_get_int64(value);
+ trg_cell_renderer_file_icon_refresh(TRG_CELL_RENDERER_FILE_ICON(object));
+ } else if (property_id == PROP_FILE_NAME) {
+ if (priv->file_id != -1) {
+ g_free(priv->text);
+ priv->text = g_strdup(g_value_get_string(value));
+ trg_cell_renderer_file_icon_refresh(TRG_CELL_RENDERER_FILE_ICON(object));
+ }
+ } else {
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+ }
+}
+
+static void
+trg_cell_renderer_file_icon_class_init(TrgCellRendererFileIconClass * klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS(klass);
+
+ object_class->get_property = trg_cell_renderer_file_icon_get_property;
+ object_class->set_property = trg_cell_renderer_file_icon_set_property;
+
+ g_object_class_install_property(object_class,
+ PROP_FILE_ID,
+ g_param_spec_int64("file-id",
+ "File ID",
+ "File ID",
+ -2,
+ INT64_MAX,
+ -2,
+ G_PARAM_READWRITE
+ |
+ G_PARAM_STATIC_NAME
+ |
+ G_PARAM_STATIC_NICK
+ |
+ G_PARAM_STATIC_BLURB));
+
+ g_object_class_install_property(object_class,
+ PROP_FILE_NAME,
+ g_param_spec_string("file-name",
+ "Filename",
+ "Filename",
+ NULL,
+ G_PARAM_READWRITE
+ |
+ G_PARAM_STATIC_NAME
+ |
+ G_PARAM_STATIC_NICK
+ |
+ G_PARAM_STATIC_BLURB));
+
+ g_type_class_add_private(klass, sizeof(TrgCellRendererFileIconPrivate));
+}
+
+static void trg_cell_renderer_file_icon_init(TrgCellRendererFileIcon * self)
+{
+}
+
+GtkCellRenderer *trg_cell_renderer_file_icon_new(void)
+{
+ return
+ GTK_CELL_RENDERER(g_object_new(TRG_TYPE_CELL_RENDERER_FILE_ICON, NULL));
+}
diff --git a/src/trg-cell-renderer-file-icon.h b/src/trg-cell-renderer-file-icon.h
new file mode 100644
index 0000000..11ef2de
--- /dev/null
+++ b/src/trg-cell-renderer-file-icon.h
@@ -0,0 +1,51 @@
+/*
+ * transmission-remote-gtk - Transmission RPC client for GTK
+ * Copyright (C) 2011 Alan Fitton
+
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef TRG_CELL_RENDERER_FILE_ICON_H_
+#define TRG_CELL_RENDERER_FILE_ICON_H_
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+#define TRG_TYPE_CELL_RENDERER_FILE_ICON trg_cell_renderer_file_icon_get_type()
+#define TRG_CELL_RENDERER_FILE_ICON(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), TRG_TYPE_CELL_RENDERER_FILE_ICON, TrgCellRendererFileIcon))
+#define TRG_CELL_RENDERER_FILE_ICON_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), TRG_TYPE_CELL_RENDERER_FILE_ICON, TrgCellRendererFileIconClass))
+#define TRG_IS_CELL_RENDERER_FILE_ICON(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TRG_TYPE_CELL_RENDERER_FILE_ICON))
+#define TRG_IS_CELL_RENDERER_FILE_ICON_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), TRG_TYPE_CELL_RENDERER_FILE_ICON))
+#define TRG_CELL_RENDERER_FILE_ICON_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), TRG_TYPE_CELL_RENDERER_FILE_ICON, TrgCellRendererFileIconClass))
+ typedef struct {
+ GtkCellRendererPixbuf parent;
+} TrgCellRendererFileIcon;
+
+typedef struct {
+ GtkCellRendererPixbufClass parent_class;
+} TrgCellRendererFileIconClass;
+
+GType trg_cell_renderer_file_icon_get_type(void);
+
+GtkCellRenderer *trg_cell_renderer_file_icon_new(void);
+
+G_END_DECLS
+#endif /* TRG_CELL_RENDERER_FILE_ICON_H_ */
diff --git a/src/trg-cell-renderer-priority.c b/src/trg-cell-renderer-priority.c
index 14d4763..3a80322 100644
--- a/src/trg-cell-renderer-priority.c
+++ b/src/trg-cell-renderer-priority.c
@@ -55,6 +55,7 @@ trg_cell_renderer_priority_get_property(GObject * object,
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+ break;
}
}
@@ -68,13 +69,15 @@ trg_cell_renderer_priority_set_property(GObject * object,
TRG_CELL_RENDERER_PRIORITY_GET_PRIVATE(object);
if (property_id == PROP_PRIORITY_VALUE) {
- priv->priority_value = g_value_get_int64(value);
+ priv->priority_value = g_value_get_int(value);
if (priv->priority_value == TR_PRI_LOW) {
g_object_set(object, "text", _("Low"), NULL);
} else if (priv->priority_value == TR_PRI_HIGH) {
g_object_set(object, "text", _("High"), NULL);
- } else {
+ } else if (priv->priority_value == TR_PRI_NORMAL){
g_object_set(object, "text", _("Normal"), NULL);
+ } else {
+ g_object_set(object, "text", "", NULL);
}
} else {
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
@@ -91,10 +94,10 @@ trg_cell_renderer_priority_class_init(TrgCellRendererPriorityClass * klass)
g_object_class_install_property(object_class,
PROP_PRIORITY_VALUE,
- g_param_spec_int64
+ g_param_spec_int
("priority-value",
"Priority Value",
- "Priority Value", TR_PRI_LOW,
+ "Priority Value", -2,
TR_PRI_HIGH, TR_PRI_NORMAL,
G_PARAM_READWRITE |
G_PARAM_STATIC_NAME |
diff --git a/src/trg-cell-renderer-size.c b/src/trg-cell-renderer-size.c
index 2271d2e..d6d07cb 100644
--- a/src/trg-cell-renderer-size.c
+++ b/src/trg-cell-renderer-size.c
@@ -50,6 +50,7 @@ trg_cell_renderer_size_get_property(GObject * object, guint property_id,
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+ break;
}
}
diff --git a/src/trg-files-model.c b/src/trg-files-model.c
index 990c89b..e1f4d6a 100644
--- a/src/trg-files-model.c
+++ b/src/trg-files-model.c
@@ -1,5 +1,5 @@
/*
- * transmission-remote-gtk - Transmission RPC client for GTK
+ * 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
@@ -27,120 +27,239 @@
#include "trg-files-model.h"
-G_DEFINE_TYPE(TrgFilesModel, trg_files_model, GTK_TYPE_LIST_STORE)
+G_DEFINE_TYPE(TrgFilesModel, trg_files_model, GTK_TYPE_TREE_STORE)
#define TRG_FILES_MODEL_GET_PRIVATE(o) \
(G_TYPE_INSTANCE_GET_PRIVATE ((o), TRG_TYPE_FILES_MODEL, TrgFilesModelPrivate))
typedef struct _TrgFilesModelPrivate TrgFilesModelPrivate;
struct _TrgFilesModelPrivate {
gint64 torrentId;
+ guint n_items;
JsonArray *wanted;
JsonArray *priorities;
gboolean accept;
};
-static void trg_files_model_iter_new(TrgFilesModel * model,
- GtkTreeIter * iter, JsonObject * file,
- int id)
-{
- gchar *mimetype;
-
- gtk_list_store_append(GTK_LIST_STORE(model), iter);
- gtk_list_store_set(GTK_LIST_STORE(model), iter,
- FILESCOL_NAME, file_get_name(file),
- FILESCOL_SIZE, file_get_length(file),
- FILESCOL_ID, id, -1);
-
- mimetype = g_content_type_guess(file_get_name(file), NULL, 0, NULL);
- if (mimetype) {
- GIcon *icon = g_content_type_get_icon(mimetype);
- if (icon) {
- gtk_list_store_set(GTK_LIST_STORE(model), iter,
- FILESCOL_ICON, icon, -1);
- g_object_unref(icon);
+static void iter_to_row_reference(GtkTreeModel *model, GtkTreeIter *iter,
+ GtkTreeRowReference **rr) {
+ GtkTreePath *path = gtk_tree_model_get_path(model, iter);
+
+ if (*rr)
+ gtk_tree_row_reference_free(*rr);
+
+ *rr = gtk_tree_row_reference_new(model, path);
+ gtk_tree_path_free(path);
+}
+
+static void rowref_to_iter(GtkTreeModel *model, GtkTreeRowReference *rr,
+ GtkTreeIter *iter) {
+ GtkTreePath *path = gtk_tree_row_reference_get_path(rr);
+ gtk_tree_model_get_iter(model, iter, path);
+ gtk_tree_path_free(path);
+}
+
+static gboolean trg_files_update_new_parents(GtkTreeModel *model,
+ GtkTreePath *path, GtkTreeIter *iter, gpointer data) {
+ GtkTreeIter *descendentIter = (GtkTreeIter*) data;
+ GtkTreePath *descendentPath = gtk_tree_model_get_path(model,
+ descendentIter);
+
+ if (gtk_tree_path_is_ancestor(path, descendentPath)
+ && gtk_tree_model_get_iter(model, descendentIter, descendentPath)) {
+ gint64 size, oldSize;
+ gtk_tree_model_get(model, descendentIter, FILESCOL_SIZE, &size, -1);
+ gtk_tree_model_get(model, iter, FILESCOL_SIZE, &oldSize, -1);
+ gtk_tree_store_set(GTK_TREE_STORE(model), iter, FILESCOL_SIZE,
+ size + oldSize, -1);
+ }
+
+ gtk_tree_path_free(descendentPath);
+
+ return FALSE;
+}
+
+struct updateAllArgs {
+ GtkTreeIter *descendentIter;
+ gint64 increment;
+};
+
+static gboolean trg_files_update_all_parents(GtkTreeModel *model,
+ GtkTreePath *path, GtkTreeIter *iter, gpointer data) {
+ struct updateAllArgs *args = (struct updateAllArgs*) data;
+ GtkTreePath *descendentPath = gtk_tree_model_get_path(model,
+ args->descendentIter);
+
+ if (gtk_tree_path_is_ancestor(path, descendentPath)) {
+ gint64 lastCompleted, newCompleted, length;
+ gtk_tree_model_get(model, iter, FILESCOL_BYTESCOMPLETED, &lastCompleted,
+ FILESCOL_SIZE, &length, -1);
+ newCompleted = lastCompleted + args->increment;
+ gtk_tree_store_set(GTK_TREE_STORE(model), iter, FILESCOL_BYTESCOMPLETED,
+ newCompleted, FILESCOL_PROGRESS,
+ file_get_progress(length, newCompleted), -1);
+ }
+
+ gtk_tree_path_free(descendentPath);
+
+ return FALSE;
+}
+
+static void trg_files_model_iter_new(TrgFilesModel * model, GtkTreeIter * iter,
+ JsonObject * file, gint id) {
+ TrgFilesModelPrivate *priv = TRG_FILES_MODEL_GET_PRIVATE(model);
+ gchar **elements = g_strsplit(file_get_name(file), "/", -1);
+ gchar *existingName;
+ gint i, existingId;
+ GtkTreeRowReference *parentRowRef = NULL;
+ GtkTreeIter parentIter;
+
+ for (i = 0; elements[i]; i++) {
+ GtkTreeIter *found = NULL;
+
+ if (parentRowRef)
+ rowref_to_iter(GTK_TREE_MODEL(model), parentRowRef, &parentIter);
+
+ /* If this is the last component of the path, create a file node. */
+
+ if (!elements[i + 1]) {
+ gtk_tree_store_append(GTK_TREE_STORE(model), iter,
+ parentRowRef ? &parentIter : NULL);
+ gtk_tree_store_set(GTK_TREE_STORE(model), iter, FILESCOL_NAME,
+ elements[i], FILESCOL_SIZE, file_get_length(file),
+ FILESCOL_ID, id, -1);
+
+ if (parentRowRef) {
+ gtk_tree_model_foreach(GTK_TREE_MODEL(model),
+ trg_files_update_new_parents, iter);
+ }
+
+ break;
+ }
+
+ /* Search for the directory this files goes under, under the saved
+ * GtkTreeRowReferece *parent. */
+
+ if (gtk_tree_model_iter_children(GTK_TREE_MODEL(model), iter,
+ parentRowRef ? &parentIter : NULL)) {
+ do {
+ gtk_tree_model_get(GTK_TREE_MODEL(model), iter, FILESCOL_NAME,
+ &existingName, FILESCOL_ID, &existingId, -1);
+
+ if (existingId == -1 && !g_strcmp0(elements[i], existingName)) {
+ found = iter;
+ iter_to_row_reference(GTK_TREE_MODEL(model), iter,
+ &parentRowRef);
+ }
+
+ g_free(existingName);
+
+ if (found)
+ break;
+ } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(model), iter));
+ }
+
+ if (!found) {
+ gtk_tree_store_append(GTK_TREE_STORE(model), iter,
+ parentRowRef ? &parentIter : NULL);
+ gtk_tree_store_set(GTK_TREE_STORE(model), iter, FILESCOL_PRIORITY,
+ -2, FILESCOL_ID, -1, FILESCOL_NAME, elements[i], -1);
+ iter_to_row_reference(GTK_TREE_MODEL(model), iter, &parentRowRef);
}
}
- g_free(mimetype);
+ if (parentRowRef)
+ gtk_tree_row_reference_free(parentRowRef);
+
+ g_strfreev(elements);
+ priv->n_items++;
}
-void trg_files_model_set_accept(TrgFilesModel * model, gboolean accept)
-{
+void trg_files_model_set_accept(TrgFilesModel * model, gboolean accept) {
TrgFilesModelPrivate *priv = TRG_FILES_MODEL_GET_PRIVATE(model);
priv->accept = accept;
}
-static void
-trg_files_model_iter_update(TrgFilesModel * model,
- GtkTreeIter * filesIter, JsonObject * file,
- JsonArray * wantedArray,
- JsonArray * prioritiesArray, int id)
-{
+static void trg_files_model_iter_update(TrgFilesModel * model,
+ GtkTreeIter * filesIter, gboolean isFirst, JsonObject * file,
+ JsonArray * wantedArray, JsonArray * prioritiesArray, int id) {
TrgFilesModelPrivate *priv = TRG_FILES_MODEL_GET_PRIVATE(model);
- gboolean wanted = json_node_get_int(json_array_get_element
- (wantedArray, id)) == 1;
- gint64 priority =
- json_node_get_int(json_array_get_element(prioritiesArray, id));
- gdouble progress = file_get_progress(file);
+ gint64 fileLength = file_get_length(file);
+ gint64 fileCompleted = file_get_bytes_completed(file);
+
+ gboolean wanted = json_node_get_int(json_array_get_element(wantedArray, id))
+ == 1;
+ gint64 priority = json_node_get_int(
+ json_array_get_element(prioritiesArray, id));
+ gdouble progress = file_get_progress(fileLength, fileCompleted);
+
+ struct updateAllArgs args;
+ args.descendentIter = filesIter;
+
+ if (isFirst) {
+ args.increment = fileLength;
+ } else {
+ gint64 lastCompleted;
+ gtk_tree_model_get(GTK_TREE_MODEL(model), filesIter,
+ FILESCOL_BYTESCOMPLETED, &lastCompleted, -1);
+ args.increment = fileCompleted - lastCompleted;
+ }
+
+ gtk_tree_store_set(GTK_TREE_STORE(model), filesIter, FILESCOL_PROGRESS,
+ progress, FILESCOL_BYTESCOMPLETED, fileCompleted, -1);
- gtk_list_store_set(GTK_LIST_STORE(model), filesIter,
- FILESCOL_PROGRESS, progress, -1);
+ gtk_tree_model_foreach(GTK_TREE_MODEL(model), trg_files_update_all_parents,
+ &args);
if (priv->accept) {
- gtk_list_store_set(GTK_LIST_STORE(model), filesIter,
- FILESCOL_WANTED,
- wanted ? GTK_STOCK_APPLY : GTK_STOCK_CANCEL,
- FILESCOL_PRIORITY, priority, -1);
+ gtk_tree_store_set(GTK_TREE_STORE(model), filesIter, FILESCOL_WANTED,
+ wanted ? GTK_STOCK_APPLY : GTK_STOCK_CANCEL
+ , FILESCOL_PRIORITY, priority, -1);
+
}
}
-static void trg_files_model_class_init(TrgFilesModelClass * klass)
-{
+static void trg_files_model_class_init(TrgFilesModelClass * klass) {
g_type_class_add_private(klass, sizeof(TrgFilesModelPrivate));
}
-static void trg_files_model_init(TrgFilesModel * self)
-{
+static void trg_files_model_init(TrgFilesModel * self) {
TrgFilesModelPrivate *priv = TRG_FILES_MODEL_GET_PRIVATE(self);
GType column_types[FILESCOL_COLUMNS];
priv->accept = TRUE;
- column_types[FILESCOL_ICON] = G_TYPE_ICON;
column_types[FILESCOL_NAME] = G_TYPE_STRING;
column_types[FILESCOL_SIZE] = G_TYPE_INT64;
column_types[FILESCOL_PROGRESS] = G_TYPE_DOUBLE;
column_types[FILESCOL_ID] = G_TYPE_INT;
column_types[FILESCOL_WANTED] = G_TYPE_STRING;
column_types[FILESCOL_PRIORITY] = G_TYPE_INT64;
+ column_types[FILESCOL_BYTESCOMPLETED] = G_TYPE_INT64;
- gtk_list_store_set_column_types(GTK_LIST_STORE(self),
- FILESCOL_COLUMNS, column_types);
+ gtk_tree_store_set_column_types(GTK_TREE_STORE(self), FILESCOL_COLUMNS,
+ column_types);
}
-gboolean
-trg_files_model_update_foreach(GtkListStore * model,
- GtkTreePath * path G_GNUC_UNUSED,
- GtkTreeIter * iter, GList * files)
-{
+gboolean trg_files_model_update_foreach(GtkListStore * model,
+ GtkTreePath * path G_GNUC_UNUSED, GtkTreeIter * iter, GList * files) {
TrgFilesModelPrivate *priv = TRG_FILES_MODEL_GET_PRIVATE(model);
JsonObject *file;
gint id;
gtk_tree_model_get(GTK_TREE_MODEL(model), iter, FILESCOL_ID, &id, -1);
- file = json_node_get_object(g_list_nth_data(files, id));
- trg_files_model_iter_update(TRG_FILES_MODEL(model), iter, file,
- priv->wanted, priv->priorities, id);
+ if (id >= 0) {
+ file = json_node_get_object(g_list_nth_data(files, id));
+ trg_files_model_iter_update(TRG_FILES_MODEL(model), iter, FALSE, file,
+ priv->wanted, priv->priorities, id);
+ }
return FALSE;
}
-void
-trg_files_model_update(TrgFilesModel * model, gint64 updateSerial,
- JsonObject * t, gint mode)
-{
+void trg_files_model_update(TrgFilesModel * model, gint64 updateSerial,
+ JsonObject * t, gint mode) {
TrgFilesModelPrivate *priv = TRG_FILES_MODEL_GET_PRIVATE(model);
GList *filesList, *li;
GtkTreeIter filesIter;
@@ -154,32 +273,28 @@ trg_files_model_update(TrgFilesModel * model, gint64 updateSerial,
filesList = json_array_get_elements(torrent_get_files(t));
if (mode == TORRENT_GET_MODE_FIRST) {
- gtk_list_store_clear(GTK_LIST_STORE(model));
+ gtk_tree_store_clear(GTK_TREE_STORE(model));
priv->accept = TRUE;
for (li = filesList; li; li = g_list_next(li)) {
file = json_node_get_object((JsonNode *) li->data);
trg_files_model_iter_new(model, &filesIter, file, j);
- trg_files_model_iter_update(model, &filesIter,
- file, priv->wanted,
- priv->priorities, j);
+ trg_files_model_iter_update(model, &filesIter, TRUE, file,
+ priv->wanted, priv->priorities, j);
j++;
}
} else {
- gint n_existing =
- gtk_tree_model_iter_n_children(GTK_TREE_MODEL(model), NULL);
guint n_updates = g_list_length(filesList);
gtk_tree_model_foreach(GTK_TREE_MODEL(model),
- (GtkTreeModelForeachFunc)
- trg_files_model_update_foreach, filesList);
- if (n_updates > n_existing) {
- gint n_new = n_updates - n_existing;
+ (GtkTreeModelForeachFunc) trg_files_model_update_foreach,
+ filesList);
+ if (n_updates > priv->n_items) {
+ gint n_new = n_updates - priv->n_items;
for (j = n_updates - n_new; j < n_updates; j++) {
file = json_node_get_object(g_list_nth_data(filesList, j));
trg_files_model_iter_new(model, &filesIter, file, j);
- trg_files_model_iter_update(model, &filesIter,
- file, priv->wanted,
- priv->priorities, j);
+ trg_files_model_iter_update(model, &filesIter, TRUE, file,
+ priv->wanted, priv->priorities, j);
}
}
}
@@ -187,13 +302,11 @@ trg_files_model_update(TrgFilesModel * model, gint64 updateSerial,
g_list_free(filesList);
}
-gint64 trg_files_model_get_torrent_id(TrgFilesModel * model)
-{
+gint64 trg_files_model_get_torrent_id(TrgFilesModel * model) {
TrgFilesModelPrivate *priv = TRG_FILES_MODEL_GET_PRIVATE(model);
return priv->torrentId;
}
-TrgFilesModel *trg_files_model_new(void)
-{
+TrgFilesModel *trg_files_model_new(void) {
return g_object_new(TRG_TYPE_FILES_MODEL, NULL);
}
diff --git a/src/trg-files-model.h b/src/trg-files-model.h
index c47c361..1a68d3b 100644
--- a/src/trg-files-model.h
+++ b/src/trg-files-model.h
@@ -38,11 +38,11 @@ G_BEGIN_DECLS
#define TRG_FILES_MODEL_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), TRG_TYPE_FILES_MODEL, TrgFilesModelClass))
typedef struct {
- GtkListStore parent;
+ GtkTreeStore parent;
} TrgFilesModel;
typedef struct {
- GtkListStoreClass parent_class;
+ GtkTreeStoreClass parent_class;
} TrgFilesModelClass;
GType trg_files_model_get_type(void);
@@ -50,13 +50,13 @@ GType trg_files_model_get_type(void);
TrgFilesModel *trg_files_model_new(void);
G_END_DECLS enum {
- FILESCOL_ICON,
FILESCOL_NAME,
FILESCOL_SIZE,
FILESCOL_PROGRESS,
FILESCOL_ID,
FILESCOL_WANTED,
FILESCOL_PRIORITY,
+ FILESCOL_BYTESCOMPLETED,
FILESCOL_COLUMNS
};
diff --git a/src/trg-files-tree-view.c b/src/trg-files-tree-view.c
index b3e4011..4755e5b 100644
--- a/src/trg-files-tree-view.c
+++ b/src/trg-files-tree-view.c
@@ -45,34 +45,36 @@ static void trg_files_tree_view_class_init(TrgFilesTreeViewClass * klass)
g_type_class_add_private(klass, sizeof(TrgFilesTreeViewPrivate));
}
-static void set_unwanted_foreachfunc(GtkTreeModel * model,
+static void set_wanted_foreachfunc(GtkTreeModel * model,
GtkTreePath * path G_GNUC_UNUSED,
GtkTreeIter * iter,
- gpointer data G_GNUC_UNUSED)
+ gpointer data)
{
- gtk_list_store_set(GTK_LIST_STORE(model), iter, FILESCOL_WANTED,
- GTK_STOCK_CANCEL, -1);
-}
+ gint id;
+ gtk_tree_model_get(model, iter, FILESCOL_ID, &id, -1);
-static void set_wanted_foreachfunc(GtkTreeModel * model,
- GtkTreePath * path G_GNUC_UNUSED,
- GtkTreeIter * iter,
- gpointer data G_GNUC_UNUSED)
-{
- gtk_list_store_set(GTK_LIST_STORE(model), iter,
- FILESCOL_WANTED, GTK_STOCK_APPLY, -1);
+ if (id >= 0) {
+ gtk_tree_store_set(GTK_TREE_STORE(model), iter, FILESCOL_WANTED,
+ (gchar*)data, -1);
+ }
}
static void set_priority_foreachfunc(GtkTreeModel * model,
GtkTreePath * path G_GNUC_UNUSED,
GtkTreeIter * iter, gpointer data)
{
+ gint id;
GValue value = { 0 };
- g_value_init(&value, G_TYPE_INT64);
- g_value_set_int64(&value, (gint64) GPOINTER_TO_INT(data));
- gtk_list_store_set_value(GTK_LIST_STORE(model), iter,
- FILESCOL_PRIORITY, &value);
+ gtk_tree_model_get(model, iter, FILESCOL_ID, &id, -1);
+
+ if(id >= 0) {
+ g_value_init(&value, G_TYPE_INT64);
+ g_value_set_int64(&value, (gint64) GPOINTER_TO_INT(data));
+
+ gtk_tree_store_set_value(GTK_TREE_STORE(model), iter,
+ FILESCOL_PRIORITY, &value);
+ }
}
static void send_updated_file_prefs_foreachfunc(GtkTreeModel * model,
@@ -82,11 +84,17 @@ static void send_updated_file_prefs_foreachfunc(GtkTreeModel * model,
gpointer data)
{
JsonObject *args = (JsonObject *) data;
- gint64 priority, id;
+ gint64 priority;
+ gint id;
gchar *wanted;
+ gtk_tree_model_get(model, iter, FILESCOL_ID, &id, -1);
+
+ if (id < 0)
+ return;
+
gtk_tree_model_get(model, iter, FILESCOL_WANTED, &wanted,
- FILESCOL_PRIORITY, &priority, FILESCOL_ID, &id, -1);
+ FILESCOL_PRIORITY, &priority, -1);
if (!g_strcmp0(wanted, GTK_STOCK_CANCEL))
add_file_id_to_array(args, FIELD_FILES_UNWANTED, id);
@@ -185,7 +193,7 @@ static void set_unwanted(GtkWidget * w G_GNUC_UNUSED, gpointer data)
GtkTreeSelection *selection =
gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
gtk_tree_selection_selected_foreach(selection,
- set_unwanted_foreachfunc, NULL);
+ set_wanted_foreachfunc, GTK_STOCK_CANCEL);
send_updated_file_prefs(tv);
}
@@ -195,7 +203,7 @@ static void set_wanted(GtkWidget * w G_GNUC_UNUSED, gpointer data)
GtkTreeSelection *selection =
gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
gtk_tree_selection_selected_foreach(selection,
- set_wanted_foreachfunc, NULL);
+ set_wanted_foreachfunc, GTK_STOCK_APPLY);
send_updated_file_prefs(tv);
}
@@ -288,9 +296,9 @@ static void trg_files_tree_view_init(TrgFilesTreeView * self)
trg_column_description *desc;
desc =
- trg_tree_view_reg_column(ttv, TRG_COLTYPE_GICONTEXT, FILESCOL_NAME,
+ trg_tree_view_reg_column(ttv, TRG_COLTYPE_FILEICONTEXT, FILESCOL_NAME,
_("Name"), "name", 0);
- desc->model_column_icon = FILESCOL_ICON;
+ desc->model_column_extra = FILESCOL_ID;
trg_tree_view_reg_column(ttv, TRG_COLTYPE_SIZE, FILESCOL_SIZE,
_("Size"), "size", 0);
diff --git a/src/trg-main-window.c b/src/trg-main-window.c
index d55b845..6db4e19 100644
--- a/src/trg-main-window.c
+++ b/src/trg-main-window.c
@@ -275,12 +275,6 @@ static void trg_main_window_init(TrgMainWindow * self G_GNUC_UNUSED)
{
}
-GtkTreeModel *trg_main_window_get_torrent_model(TrgMainWindow * win)
-{
- TrgMainWindowPrivate *priv = TRG_MAIN_WINDOW_GET_PRIVATE(win);
- return GTK_TREE_MODEL(priv->torrentModel);
-}
-
gint trg_mw_get_selected_torrent_id(TrgMainWindow * win)
{
TrgMainWindowPrivate *priv = TRG_MAIN_WINDOW_GET_PRIVATE(win);
@@ -308,6 +302,10 @@ static void update_selected_torrent_notebook(TrgMainWindow * win,
trg_peers_model_update(priv->peersModel,
TRG_TREE_VIEW(priv->peersTreeView),
trg_client_get_serial(client), t, mode);
+
+ if (mode == TORRENT_GET_MODE_FIRST)
+ gtk_tree_view_expand_all(GTK_TREE_VIEW(priv->filesTreeView));
+
} else if (id < 0) {
trg_main_window_torrent_scrub(win);
}
@@ -1079,9 +1077,9 @@ static void update_whatever_statusicon(TrgMainWindow * win,
#endif
}
- /*
- * The callback for a torrent-get response.
- */
+/*
+ * The callback for a torrent-get response.
+ */
static gboolean on_torrent_get(gpointer data, int mode)
{
@@ -1424,7 +1422,7 @@ void trg_main_window_torrent_scrub(TrgMainWindow * win)
{
TrgMainWindowPrivate *priv = TRG_MAIN_WINDOW_GET_PRIVATE(win);
- gtk_list_store_clear(GTK_LIST_STORE(priv->filesModel));
+ gtk_tree_store_clear(GTK_TREE_STORE(priv->filesModel));
gtk_list_store_clear(GTK_LIST_STORE(priv->trackersModel));
gtk_list_store_clear(GTK_LIST_STORE(priv->peersModel));
trg_general_panel_clear(priv->genDetails);
diff --git a/src/trg-peers-tree-view.c b/src/trg-peers-tree-view.c
index ab86d69..20eae98 100644
--- a/src/trg-peers-tree-view.c
+++ b/src/trg-peers-tree-view.c
@@ -49,7 +49,7 @@ static void trg_peers_tree_view_init(TrgPeersTreeView * self)
desc =
trg_tree_view_reg_column(ttv, TRG_COLTYPE_STOCKICONTEXT,
PEERSCOL_IP, _("IP"), "ip", 0);
- desc->model_column_icon = PEERSCOL_ICON;
+ desc->model_column_extra = PEERSCOL_ICON;
trg_tree_view_reg_column(ttv, TRG_COLTYPE_TEXT, PEERSCOL_HOST,
_("Host"), "host", 0);
diff --git a/src/trg-torrent-tree-view.c b/src/trg-torrent-tree-view.c
index a359dff..89885d7 100644
--- a/src/trg-torrent-tree-view.c
+++ b/src/trg-torrent-tree-view.c
@@ -43,7 +43,7 @@ static void trg_torrent_tree_view_init(TrgTorrentTreeView * tttv)
trg_tree_view_reg_column(ttv, TRG_COLTYPE_STOCKICONTEXT,
TORRENT_COLUMN_NAME, _("Name"), "name",
0);
- desc->model_column_icon = TORRENT_COLUMN_ICON;
+ desc->model_column_extra = TORRENT_COLUMN_ICON;
trg_tree_view_reg_column(ttv, TRG_COLTYPE_SIZE, TORRENT_COLUMN_SIZE,
_("Size"), "size", 0);
diff --git a/src/trg-trackers-tree-view.c b/src/trg-trackers-tree-view.c
index 334b35c..d481f53 100644
--- a/src/trg-trackers-tree-view.c
+++ b/src/trg-trackers-tree-view.c
@@ -166,7 +166,7 @@ static void trg_trackers_tree_view_init(TrgTrackersTreeView * self)
trg_tree_view_reg_column(ttv, TRG_COLTYPE_STOCKICONTEXT,
TRACKERCOL_TIER, _("Tier"), "tier",
TRG_COLUMN_UNREMOVABLE);
- desc->model_column_icon = TRACKERCOL_ICON;
+ desc->model_column_extra = TRACKERCOL_ICON;
desc =
trg_tree_view_reg_column(ttv, TRG_COLTYPE_TEXT,
diff --git a/src/trg-tree-view.c b/src/trg-tree-view.c
index 30db56e..d6c7b93 100644
--- a/src/trg-tree-view.c
+++ b/src/trg-tree-view.c
@@ -31,6 +31,7 @@
#include "trg-cell-renderer-epoch.h"
#include "trg-cell-renderer-priority.h"
#include "trg-cell-renderer-numgteqthan.h"
+#include "trg-cell-renderer-file-icon.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
@@ -264,7 +265,28 @@ static GtkTreeViewColumn
gtk_tree_view_column_pack_start(column, renderer, FALSE);
gtk_tree_view_column_set_attributes(column, renderer,
renderer_property,
- desc->model_column_icon, NULL);
+ desc->model_column_extra, NULL);
+
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_column_pack_start(column, renderer, TRUE);
+ gtk_tree_view_column_set_attributes(column, renderer, "text",
+ desc->model_column, NULL);
+
+ return column;
+}
+
+static GtkTreeViewColumn
+ * trg_tree_view_fileicontext_column_new(trg_column_description * desc)
+{
+ GtkTreeViewColumn *column = gtk_tree_view_column_new();
+ GtkCellRenderer *renderer = trg_cell_renderer_file_icon_new();
+
+ gtk_tree_view_column_set_title(column, desc->header);
+ gtk_tree_view_column_pack_start(column, renderer, FALSE);
+ gtk_tree_view_column_set_attributes(column, renderer,
+ "file-id",
+ desc->model_column_extra,
+ "file-name", desc->model_column, NULL);
renderer = gtk_cell_renderer_text_new();
gtk_tree_view_column_pack_start(column, renderer, TRUE);
@@ -354,8 +376,8 @@ static void trg_tree_view_add_column_after(TrgTreeView * tv,
case TRG_COLTYPE_STOCKICONTEXT:
column = trg_tree_view_icontext_column_new(desc, "stock-id");
break;
- case TRG_COLTYPE_GICONTEXT:
- column = trg_tree_view_icontext_column_new(desc, "gicon");
+ case TRG_COLTYPE_FILEICONTEXT:
+ column = trg_tree_view_fileicontext_column_new(desc);
break;
case TRG_COLTYPE_PRIO:
renderer = trg_cell_renderer_priority_new();
diff --git a/src/trg-tree-view.h b/src/trg-tree-view.h
index 7332ad6..3460e3c 100644
--- a/src/trg-tree-view.h
+++ b/src/trg-tree-view.h
@@ -52,7 +52,7 @@ G_END_DECLS GList *trg_tree_view_get_selected_refs_list(GtkTreeView * tv);
enum {
TRG_COLTYPE_STOCKICONTEXT,
- TRG_COLTYPE_GICONTEXT,
+ TRG_COLTYPE_FILEICONTEXT,
TRG_COLTYPE_ICON,
TRG_COLTYPE_TEXT,
TRG_COLTYPE_SIZE,
@@ -68,7 +68,7 @@ enum {
typedef struct {
gint model_column;
- gint model_column_icon;
+ gint model_column_extra;
gchar *header;
gchar *id;
gint flags;
diff --git a/src/util.c b/src/util.c
index 8b31487..b103cff 100644
--- a/src/util.c
+++ b/src/util.c
@@ -176,31 +176,11 @@ char *tr_strlsize(char *buf, guint64 size, size_t buflen)
{
if (!size)
g_strlcpy(buf, _("None"), buflen);
-#if GLIB_CHECK_VERSION( 2, 16, 0 )
else {
char *tmp = g_format_size_for_display(size);
g_strlcpy(buf, tmp, buflen);
g_free(tmp);
}
-#else
- else if (size < (guint64) KILOBYTE_FACTOR)
- g_snprintf(buf, buflen,
- ngettext("%'u byte", "%'u bytes", (guint) size),
- (guint) size);
- else {
- gdouble displayed_size;
- if (size < (guint64) MEGABYTE_FACTOR) {
- displayed_size = (gdouble) size / KILOBYTE_FACTOR;
- g_snprintf(buf, buflen, _("%'.1f KB"), displayed_size);
- } else if (size < (guint64) GIGABYTE_FACTOR) {
- displayed_size = (gdouble) size / MEGABYTE_FACTOR;
- g_snprintf(buf, buflen, _("%'.1f MB"), displayed_size);
- } else {
- displayed_size = (gdouble) size / GIGABYTE_FACTOR;
- g_snprintf(buf, buflen, _("%'.1f GB"), displayed_size);
- }
- }
-#endif
return buf;
}