summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Alan Fitton <ajf@eth0.org.uk>2011-10-21 23:12:21 +0000
committerGravatar Alan Fitton <ajf@eth0.org.uk>2011-10-21 23:12:21 +0000
commit34c56c7db7c57f5db0184489d01866902e992300 (patch)
tree8707a14ac8f786ff684279be77e66946f235b751
parent3b8fd9e7274477cfad98d66e41a43417ce8d21bf (diff)
make the execute command tree view in preferences a generic widget, the "persistent tree view"
-rw-r--r--src/Makefile.am1
-rw-r--r--src/trg-client.c12
-rw-r--r--src/trg-client.h2
-rw-r--r--src/trg-destination-combo.c22
-rw-r--r--src/trg-destination-combo.h1
-rw-r--r--src/trg-persistent-tree-view.c368
-rw-r--r--src/trg-persistent-tree-view.h77
-rw-r--r--src/trg-preferences-dialog.c220
-rw-r--r--src/trg-preferences-dialog.h3
-rw-r--r--src/trg-prefs.h5
-rw-r--r--src/trg-torrent-add-dialog.c4
-rw-r--r--src/trg-torrent-move-dialog.c4
12 files changed, 534 insertions, 185 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 476bab0..5c5741d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -39,6 +39,7 @@ transmission_remote_gtk_SOURCES = main.c \
trg-peers-model.c \
trg-peers-tree-view.c \
trg-model.c \
+ trg-persistent-tree-view.c \
trg-files-model.c \
trg-files-tree-view.c \
trg-state-selector.c \
diff --git a/src/trg-client.c b/src/trg-client.c
index 2d3fbe6..2f42d99 100644
--- a/src/trg-client.c
+++ b/src/trg-client.c
@@ -386,6 +386,12 @@ void trg_client_updatelock(TrgClient *tc)
g_mutex_lock(priv->updateMutex);
}
+void trg_client_configlock(TrgClient *tc)
+{
+ TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc);
+ g_mutex_lock(priv->configMutex);
+}
+
guint trg_client_get_failcount(TrgClient *tc)
{
TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc);
@@ -410,6 +416,12 @@ void trg_client_updateunlock(TrgClient *tc)
g_mutex_unlock(priv->updateMutex);
}
+void trg_client_configunlock(TrgClient *tc)
+{
+ TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc);
+ g_mutex_unlock(priv->configMutex);
+}
+
/* formerly http.c */
void trg_response_free(trg_response *response)
diff --git a/src/trg-client.h b/src/trg-client.h
index 0091598..cf3e04f 100644
--- a/src/trg-client.h
+++ b/src/trg-client.h
@@ -159,6 +159,8 @@ void trg_client_status_change(TrgClient *tc, gboolean connected);
gboolean trg_client_is_connected(TrgClient *tc);
void trg_client_updateunlock(TrgClient *tc);
void trg_client_updatelock(TrgClient *tc);
+void trg_client_configunlock(TrgClient *tc);
+void trg_client_configlock(TrgClient *tc);
guint trg_client_inc_failcount(TrgClient *tc);
guint trg_client_get_failcount(TrgClient *tc);
void trg_client_reset_failcount(TrgClient *tc);
diff --git a/src/trg-destination-combo.c b/src/trg-destination-combo.c
index 976e3bb..5fe32b0 100644
--- a/src/trg-destination-combo.c
+++ b/src/trg-destination-combo.c
@@ -26,7 +26,7 @@
#include "util.h"
G_DEFINE_TYPE(TrgDestinationCombo, trg_destination_combo,
- GTK_TYPE_COMBO_BOX_ENTRY)
+ GTK_TYPE_COMBO_BOX)
#define TRG_DESTINATION_COMBO_GET_PRIVATE(o) \
(G_TYPE_INSTANCE_GET_PRIVATE ((o), TRG_TYPE_DESTINATION_COMBO, TrgDestinationComboPrivate))
typedef struct _TrgDestinationComboPrivate TrgDestinationComboPrivate;
@@ -104,7 +104,7 @@ static GObject *trg_destination_combo_constructor(GType type,
GSList *sli;
GList *li;
GList *torrentItemRefs;
-
+ GtkCellRenderer *renderer;
GtkTreeRowReference *rr;
GtkTreeModel *model;
GtkTreePath *path;
@@ -115,7 +115,7 @@ static GObject *trg_destination_combo_constructor(GType type,
g_strdup(session_get_download_dir(trg_client_get_session(client)));
rm_trailing_slashes(defaultDownDir);
- comboModel = gtk_list_store_new(1, G_TYPE_STRING);
+ comboModel = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
trg_client_updatelock(client);
torrentItemRefs = g_hash_table_get_values(trg_client_get_torrent_table(client));
@@ -150,12 +150,15 @@ static GObject *trg_destination_combo_constructor(GType type,
for (sli = dirs; sli; sli = g_slist_next(sli))
gtk_list_store_insert_with_values(comboModel, NULL, INT_MAX, 0,
- (gchar *) sli->data, -1);
+ (gchar *) sli->data,
+ 1, (gchar *) sli->data, -1);
gtk_combo_box_set_model(GTK_COMBO_BOX(object),
GTK_TREE_MODEL(comboModel));
- gtk_combo_box_entry_set_text_column(GTK_COMBO_BOX_ENTRY(object), 0);
+ renderer = gtk_cell_renderer_text_new();
+ gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(object), renderer, TRUE);
+ gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(object), renderer, "text", 0, NULL);
g_object_unref(comboModel);
g_slist_foreach(dirs, (GFunc)g_free, NULL);
@@ -164,6 +167,15 @@ static GObject *trg_destination_combo_constructor(GType type,
return object;
}
+gchar *trg_destination_combo_get_dir(TrgDestinationCombo *combo)
+{
+ GtkTreeIter iter;
+ gchar *value;
+ gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter);
+ gtk_tree_model_get(gtk_combo_box_get_model(GTK_COMBO_BOX(combo)), &iter, 1, &value, -1);
+ return value;
+}
+
static void
trg_destination_combo_class_init(TrgDestinationComboClass * klass)
{
diff --git a/src/trg-destination-combo.h b/src/trg-destination-combo.h
index c5926a9..6412018 100644
--- a/src/trg-destination-combo.h
+++ b/src/trg-destination-combo.h
@@ -48,6 +48,7 @@ typedef struct {
GType trg_destination_combo_get_type(void);
GtkWidget *trg_destination_combo_new(TrgClient * client);
+gchar *trg_destination_combo_get_dir(TrgDestinationCombo *combo);
G_END_DECLS
#endif /* TRG_DESTINATION_COMBO_H_ */
diff --git a/src/trg-persistent-tree-view.c b/src/trg-persistent-tree-view.c
new file mode 100644
index 0000000..48cf908
--- /dev/null
+++ b/src/trg-persistent-tree-view.c
@@ -0,0 +1,368 @@
+/*
+ * 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 <gtk/gtk.h>
+
+#include "trg-prefs.h"
+#include "trg-persistent-tree-view.h"
+#include "trg-preferences-dialog.h"
+#include "util.h"
+
+G_DEFINE_TYPE (TrgPersistentTreeView, trg_persistent_tree_view, GTK_TYPE_VBOX)
+
+#define GET_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRG_TYPE_PERSISTENT_TREE_VIEW, TrgPersistentTreeViewPrivate))
+
+typedef struct _TrgPersistentTreeViewPrivate TrgPersistentTreeViewPrivate;
+
+enum {
+ PROP_0, PROP_PREFS, PROP_KEY, PROP_MODEL
+};
+
+struct _TrgPersistentTreeViewPrivate {
+ TrgPrefs *prefs;
+ gchar *key;
+ GSList *columns;
+ GtkTreeView *tv;
+ JsonArray *ja;
+ GtkWidget *delButton;
+ trg_pref_widget_desc *wd;
+ GtkTreeModel *model;
+ trg_persistent_tree_view_column *addSelect;
+};
+
+static void selection_changed(GtkTreeSelection *selection, gpointer data) {
+ TrgPersistentTreeViewPrivate *priv = GET_PRIVATE(data);
+
+ if (gtk_tree_selection_get_selected(selection, NULL, NULL))
+ gtk_widget_set_sensitive(priv->delButton, TRUE);
+ else
+ gtk_widget_set_sensitive(priv->delButton, FALSE);
+}
+
+static void trg_persistent_tree_view_edit(GtkCellRendererText * renderer,
+ gchar * path, gchar * new_text, gpointer user_data) {
+ trg_persistent_tree_view_column *cd =
+ (trg_persistent_tree_view_column*) user_data;
+ TrgPersistentTreeViewPrivate *priv = GET_PRIVATE(cd->tv);
+ GtkTreeModel *model = gtk_tree_view_get_model(priv->tv);
+ GtkTreeIter iter;
+
+ gtk_tree_model_get_iter_from_string(model, &iter, path);
+ gtk_list_store_set(GTK_LIST_STORE(model), &iter, cd->index, new_text, -1);
+}
+
+static void trg_persistent_tree_view_refresh(TrgPrefs *prefs, void *wdp) {
+ trg_pref_widget_desc *wd = (trg_pref_widget_desc*) wdp;
+ TrgPersistentTreeViewPrivate *priv = GET_PRIVATE(wd->widget);
+ GtkListStore *model = GTK_LIST_STORE(gtk_tree_view_get_model(priv->tv));
+ GtkTreeIter iter;
+ JsonArray *ja;
+ GList *ja_list, *li;
+ GSList *sli;
+
+ ja = trg_prefs_get_array(prefs, wd->key, wd->flags);
+
+ gtk_list_store_clear(model);
+
+ if (!ja)
+ return;
+
+ ja_list = json_array_get_elements(ja);
+
+ for (li = ja_list; li; li = g_list_next(li)) {
+ JsonNode *ja_node = (JsonNode*) li->data;
+ JsonObject *jobj = json_node_get_object(ja_node);
+ gtk_list_store_append(model, &iter);
+ for (sli = priv->columns; sli; sli = g_slist_next(sli)) {
+ trg_persistent_tree_view_column *cd =
+ (trg_persistent_tree_view_column*) sli->data;
+ gtk_list_store_set(model, &iter, cd->index,
+ json_object_get_string_member(jobj, cd->key), -1);
+ }
+ }
+
+ g_list_free(ja_list);
+}
+
+static gboolean trg_persistent_tree_view_save_foreachfunc(GtkTreeModel *model,
+ GtkTreePath *path, GtkTreeIter *iter, gpointer data) {
+ TrgPersistentTreeViewPrivate *priv = GET_PRIVATE(data);
+ JsonObject *new = json_object_new();
+ gchar *value;
+ GSList *li;
+
+ for (li = priv->columns; li; li = g_slist_next(li)) {
+ trg_persistent_tree_view_column *cd =
+ (trg_persistent_tree_view_column*) li->data;
+ gtk_tree_model_get(model, iter, cd->index, &value, -1);
+ json_object_set_string_member(new, cd->key, value);
+ g_free(value);
+ }
+
+ json_array_add_object_element(priv->ja, new);
+
+ return FALSE;
+}
+
+static void trg_persistent_tree_view_save(TrgPrefs *prefs, void *wdp) {
+ trg_pref_widget_desc *wd = (trg_pref_widget_desc*) wdp;
+ TrgPersistentTreeViewPrivate *priv = GET_PRIVATE(wd->widget);
+ GtkTreeModel *model = gtk_tree_view_get_model(priv->tv);
+
+ JsonNode *node = trg_prefs_get_value(prefs, wd->key, JSON_NODE_ARRAY,
+ wd->flags | TRG_PREFS_REPLACENODE);
+
+ priv->ja = json_array_new();
+
+ gtk_tree_model_foreach(model, trg_persistent_tree_view_save_foreachfunc,
+ wd->widget);
+ json_node_take_array(node, priv->ja);
+
+ trg_prefs_changed_emit_signal(prefs, wd->key);
+}
+
+void trg_persistent_tree_view_build(TrgPersistentTreeView *ptv) {
+ TrgPersistentTreeViewPrivate *priv = GET_PRIVATE(ptv);
+ GSList *li;
+ GtkCellRenderer *renderer;
+
+ for (li = priv->columns; li; li = g_slist_next(li)) {
+ trg_persistent_tree_view_column *cd =
+ (trg_persistent_tree_view_column*) li->data;
+ renderer = gtk_cell_renderer_text_new();
+ g_object_set(G_OBJECT(renderer), "editable", TRUE, NULL);
+ g_signal_connect(renderer, "edited",
+ G_CALLBACK(trg_persistent_tree_view_edit), cd);
+ cd->column = gtk_tree_view_column_new_with_attributes(cd->label,
+ renderer, "text", cd->index, NULL);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(priv->tv), cd->column);
+ }
+}
+
+trg_persistent_tree_view_column *trg_persistent_tree_view_add_column(
+ TrgPersistentTreeView *ptv, gint index, const gchar *key,
+ const gchar *label) {
+ TrgPersistentTreeViewPrivate *priv = GET_PRIVATE(ptv);
+ trg_persistent_tree_view_column *cd =
+ g_new0(trg_persistent_tree_view_column, 1);
+
+ cd->key = g_strdup(key);
+ cd->label = g_strdup(label);
+ cd->index = index;
+ cd->tv = ptv;
+
+ priv->columns = g_slist_append(priv->columns, cd);
+
+ return cd;
+}
+
+static GtkTreeView *trg_persistent_tree_view_tree_view_new(
+ TrgPersistentTreeView *ptv, GtkTreeModel *model) {
+ GtkTreeView *tv = GTK_TREE_VIEW(gtk_tree_view_new_with_model(model));
+ GtkTreeSelection *selection;
+
+ g_object_unref(G_OBJECT(model));
+
+ gtk_tree_view_set_rubber_banding(tv, TRUE);
+ //gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tv), FALSE);
+
+ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv));
+
+ g_signal_connect(G_OBJECT(selection), "changed",
+ G_CALLBACK(selection_changed), ptv);
+
+ return tv;
+}
+
+static void trg_persistent_tree_view_add_cb(GtkWidget *w, gpointer data) {
+ TrgPersistentTreeViewPrivate *priv = GET_PRIVATE(data);
+ GtkTreeModel *model = gtk_tree_view_get_model(priv->tv);
+ GtkTreeIter iter;
+ GtkTreePath *path;
+
+ gtk_list_store_append(GTK_LIST_STORE(model), &iter);
+ path = gtk_tree_model_get_path(model, &iter);
+
+ if (priv->addSelect)
+ gtk_tree_view_set_cursor(priv->tv, path, priv->addSelect->column, TRUE);
+
+ gtk_tree_path_free(path);
+}
+
+static void trg_persistent_tree_view_del_cb(GtkWidget *w, gpointer data) {
+ TrgPersistentTreeViewPrivate *priv = GET_PRIVATE(data);
+ GtkTreeSelection *selection = gtk_tree_view_get_selection(priv->tv);
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ if (gtk_tree_selection_get_selected(selection, &model, &iter))
+ gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
+}
+
+static void trg_persistent_tree_view_get_property(GObject *object,
+ guint property_id, GValue *value, GParamSpec *pspec) {
+ switch (property_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void trg_persistent_tree_view_set_property(GObject *object,
+ guint property_id, const GValue *value, GParamSpec *pspec) {
+ TrgPersistentTreeViewPrivate *priv = GET_PRIVATE(object);
+ switch (property_id) {
+ case PROP_PREFS:
+ priv->prefs = g_value_get_object(value);
+ break;
+ case PROP_KEY:
+ priv->key = g_value_get_pointer(value);
+ break;
+ case PROP_MODEL:
+ priv->model = g_value_get_object(value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void trg_persistent_tree_view_finalize(GObject *object) {
+ TrgPersistentTreeViewPrivate *priv = GET_PRIVATE(object);
+ GSList *li;
+ for (li = priv->columns; li; li = g_slist_next(li)) {
+ trg_persistent_tree_view_column *cd =
+ (trg_persistent_tree_view_column*) li->data;
+ g_free(cd->key);
+ g_free(cd->label);
+ g_free(cd);
+ }
+ g_slist_free(priv->columns);
+ G_OBJECT_CLASS (trg_persistent_tree_view_parent_class)->finalize(object);
+}
+
+trg_pref_widget_desc* trg_persistent_tree_view_get_widget_desc(
+ TrgPersistentTreeView* ptv) {
+ TrgPersistentTreeViewPrivate *priv = GET_PRIVATE(ptv);
+ return priv->wd;
+}
+
+void trg_persistent_tree_view_set_add_select(TrgPersistentTreeView *ptv,
+ trg_persistent_tree_view_column *cd) {
+ TrgPersistentTreeViewPrivate *priv = GET_PRIVATE(ptv);
+ priv->addSelect = cd;
+}
+
+static GObject *trg_persistent_tree_view_constructor(GType type,
+ guint n_construct_properties, GObjectConstructParam * construct_params) {
+ GObject *object;
+ TrgPersistentTreeViewPrivate *priv;
+ GtkWidget *hbox, *w;
+
+ object = G_OBJECT_CLASS
+ (trg_persistent_tree_view_parent_class)->constructor(type,
+ n_construct_properties, construct_params);
+ priv = GET_PRIVATE(object);
+
+ hbox = gtk_hbox_new(FALSE, 0);
+
+ w = gtk_button_new_from_stock(GTK_STOCK_ADD);
+ g_signal_connect(w, "clicked", G_CALLBACK(trg_persistent_tree_view_add_cb), object);
+ gtk_box_pack_start(GTK_BOX(hbox), w, FALSE, FALSE, 4);
+
+ w = priv->delButton = gtk_button_new_from_stock(GTK_STOCK_DELETE);
+ gtk_widget_set_sensitive(w, FALSE);
+ g_signal_connect(w, "clicked", G_CALLBACK(trg_persistent_tree_view_del_cb), object);
+ gtk_box_pack_start(GTK_BOX(hbox), w, FALSE, FALSE, 4);
+
+ priv->tv = trg_persistent_tree_view_tree_view_new(
+ TRG_PERSISTENT_TREE_VIEW(object), priv->model);
+ gtk_box_pack_start(GTK_BOX(object),
+ my_scrolledwin_new(GTK_WIDGET(priv->tv)), TRUE, TRUE, 4);
+ gtk_box_pack_start(GTK_BOX(object), hbox, FALSE, FALSE, 4);
+
+ priv->wd = trg_pref_widget_desc_new(GTK_WIDGET(priv->tv), priv->key,
+ TRG_PREFS_PROFILE);
+ priv->wd->widget = GTK_WIDGET(object);
+ priv->wd->saveFunc = &trg_persistent_tree_view_save;
+ priv->wd->refreshFunc = &trg_persistent_tree_view_refresh;
+
+ //trg_persistent_tree_view_refresh(priv->prefs, wd);
+
+ return object;
+}
+
+static void trg_persistent_tree_view_class_init(
+ TrgPersistentTreeViewClass *klass) {
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private(klass, sizeof(TrgPersistentTreeViewPrivate));
+
+ object_class->get_property = trg_persistent_tree_view_get_property;
+ object_class->set_property = trg_persistent_tree_view_set_property;
+ object_class->finalize = trg_persistent_tree_view_finalize;
+ object_class->constructor = trg_persistent_tree_view_constructor;
+
+ g_object_class_install_property(
+ object_class,
+ PROP_KEY,
+ g_param_spec_pointer(
+ "conf-key",
+ "Conf Key",
+ "Conf Key",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY
+ | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK
+ | G_PARAM_STATIC_BLURB));
+
+ g_object_class_install_property(
+ object_class,
+ PROP_PREFS,
+ g_param_spec_object(
+ "prefs",
+ "Prefs",
+ "Prefs",
+ TRG_TYPE_PREFS,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY
+ | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK
+ | G_PARAM_STATIC_BLURB));
+
+ g_object_class_install_property(
+ object_class,
+ PROP_MODEL,
+ g_param_spec_object(
+ "persistent-model",
+ "Persistent Model",
+ "Persistent Model",
+ GTK_TYPE_LIST_STORE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY
+ | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK
+ | G_PARAM_STATIC_BLURB));
+}
+
+static void trg_persistent_tree_view_init(TrgPersistentTreeView *self) {
+}
+
+TrgPersistentTreeView*
+trg_persistent_tree_view_new(TrgPrefs *prefs, GtkListStore *model,
+ const gchar *key) {
+ GObject *obj = g_object_new(TRG_TYPE_PERSISTENT_TREE_VIEW, "prefs", prefs,
+ "conf-key", key, "persistent-model", model, NULL);
+
+ return TRG_PERSISTENT_TREE_VIEW(obj);
+}
diff --git a/src/trg-persistent-tree-view.h b/src/trg-persistent-tree-view.h
new file mode 100644
index 0000000..2664946
--- /dev/null
+++ b/src/trg-persistent-tree-view.h
@@ -0,0 +1,77 @@
+/*
+ * 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_PERSISTENT_TREE_VIEW
+#define _TRG_PERSISTENT_TREE_VIEW
+
+#include <gtk/gtk.h>
+#include <glib-object.h>
+
+#include "trg-preferences-dialog.h"
+
+G_BEGIN_DECLS
+
+#define TRG_TYPE_PERSISTENT_TREE_VIEW trg_persistent_tree_view_get_type()
+
+#define TRG_PERSISTENT_TREE_VIEW(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), TRG_TYPE_PERSISTENT_TREE_VIEW, TrgPersistentTreeView))
+
+#define TRG_PERSISTENT_TREE_VIEW_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), TRG_TYPE_PERSISTENT_TREE_VIEW, TrgPersistentTreeViewClass))
+
+#define TRG_IS_PERSISTENT_TREE_VIEW(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TRG_TYPE_PERSISTENT_TREE_VIEW))
+
+#define TRG_IS_PERSISTENT_TREE_VIEW_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), TRG_TYPE_PERSISTENT_TREE_VIEW))
+
+#define TRG_PERSISTENT_TREE_VIEW_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), TRG_TYPE_PERSISTENT_TREE_VIEW, TrgPersistentTreeViewClass))
+
+typedef struct {
+ GtkVBox parent;
+} TrgPersistentTreeView;
+
+typedef struct {
+ GtkTreeViewClass parent_class;
+} TrgPersistentTreeViewClass;
+
+GType trg_persistent_tree_view_get_type (void);
+
+typedef struct {
+ GtkTreeViewColumn *column;
+ gchar *key;
+ gchar *label;
+ TrgPersistentTreeView *tv;
+ gint index;
+} trg_persistent_tree_view_column;
+
+TrgPersistentTreeView*
+trg_persistent_tree_view_new (TrgPrefs *prefs, GtkListStore *model, const gchar *key);
+trg_pref_widget_desc* trg_persistent_tree_view_get_widget_desc(TrgPersistentTreeView* ptv);
+void trg_persistent_tree_view_set_add_select(TrgPersistentTreeView *ptv, trg_persistent_tree_view_column *cd);
+trg_persistent_tree_view_column *trg_persistent_tree_view_add_column(TrgPersistentTreeView *ptv,
+ gint index,
+ const gchar *key,
+ const gchar *label);
+void trg_persistent_tree_view_build(TrgPersistentTreeView *ptv);
+
+G_END_DECLS
+
+#endif /* _TRG_PERSISTENT_TREE_VIEW */
diff --git a/src/trg-preferences-dialog.c b/src/trg-preferences-dialog.c
index 91b36ebb..e729300 100644
--- a/src/trg-preferences-dialog.c
+++ b/src/trg-preferences-dialog.c
@@ -30,6 +30,7 @@
#include "hig.h"
#include "trg-json-widgets.h"
#include "trg-preferences-dialog.h"
+#include "trg-persistent-tree-view.h"
#include "trg-main-window.h"
#include "trg-prefs.h"
#include "util.h"
@@ -52,9 +53,6 @@ struct _TrgPreferencesDialogPrivate {
GtkWidget *profileComboBox;
GtkWidget *profileNameEntry;
GtkWidget *fullUpdateCheck;
- GtkWidget *execDelButton;
- GtkWidget *etv;
- GtkTreeViewColumn *etvLabelColumn;
GList *widgets;
};
@@ -65,7 +63,7 @@ static void trg_pref_widget_desc_free(trg_pref_widget_desc *wd) {
g_free(wd);
}
-static trg_pref_widget_desc* trg_pref_widget_desc_new(GtkWidget *w, gchar *key,
+trg_pref_widget_desc* trg_pref_widget_desc_new(GtkWidget *w, gchar *key,
int flags) {
trg_pref_widget_desc *desc = g_new0(trg_pref_widget_desc, 1);
desc->widget = w;
@@ -98,15 +96,17 @@ static void trg_pref_widget_save(TrgPreferencesDialog *dlg,
static void trg_pref_widget_save_all(TrgPreferencesDialog *dlg) {
TrgPreferencesDialogPrivate *priv = TRG_PREFERENCES_DIALOG_GET_PRIVATE(dlg);
+ GList *li;
if (trg_prefs_get_profile(priv->prefs) == NULL)
return;
- GList *li;
+ trg_client_configlock(priv->client);
for (li = priv->widgets; li; li = g_list_next(li)) {
trg_pref_widget_desc* wd = (trg_pref_widget_desc*) li->data;
trg_pref_widget_save(dlg, wd);
}
+ trg_client_configunlock(priv->client);
}
static void trg_preferences_dialog_set_property(GObject * object,
@@ -545,200 +545,64 @@ static void trgp_double_special_dependent(GtkWidget *widget, gpointer data) {
GTK_TOGGLE_BUTTON(priv->fullUpdateCheck)));
}
-static void exec_selection_changed(GtkTreeSelection *selection, gpointer data) {
- TrgPreferencesDialogPrivate *priv =
- TRG_PREFERENCES_DIALOG_GET_PRIVATE(data);
-
- if (gtk_tree_selection_get_selected(selection, NULL, NULL))
- gtk_widget_set_sensitive(priv->execDelButton, TRUE);
- else
- gtk_widget_set_sensitive(priv->execDelButton, FALSE);
-}
-
-static void trg_etc_edited(GtkCellRendererText * renderer, gchar * path,
- gchar * new_text, gint model_column, gpointer user_data) {
- GtkTreeModel *model = GTK_TREE_MODEL(user_data);
- GtkTreeIter iter;
-
- gtk_tree_model_get_iter_from_string(model, &iter, path);
- gtk_list_store_set(GTK_LIST_STORE(model), &iter, model_column, new_text, -1);
-}
-
-static void trg_etv_label_edited(GtkCellRendererText * renderer, gchar * path,
- gchar * new_text, gpointer user_data) {
- trg_etc_edited(renderer, path, new_text, 0, user_data);
-}
-
-static void trg_etv_cmd_edited(GtkCellRendererText * renderer, gchar * path,
- gchar * new_text, gpointer user_data) {
- trg_etc_edited(renderer, path, new_text, 1, user_data);
-}
-
-static void trg_prefs_etv_refresh(TrgPrefs *prefs, void *wdp) {
- trg_pref_widget_desc *wd = (trg_pref_widget_desc*) wdp;
- GtkListStore *model =
- GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(wd->widget)));
- GtkTreeIter iter;
- JsonArray *ja;
- GList *ja_list, *li;
-
- ja = trg_prefs_get_array(prefs, wd->key, wd->flags);
- gtk_list_store_clear(model);
-
- if (!ja)
- return;
-
- ja_list = json_array_get_elements(ja);
-
- for (li = ja_list; li; li = g_list_next(li)) {
- JsonNode *ja_node = (JsonNode*) li->data;
- JsonObject *jobj = json_node_get_object(ja_node);
- gtk_list_store_append(model, &iter);
- gtk_list_store_set(model, &iter, 0,
- json_object_get_string_member(jobj, TRG_PREFS_KEY_EXEC_COMMANDS_SUBKEY_LABEL), 1,
- json_object_get_string_member(jobj, TRG_PREFS_KEY_EXEC_COMMANDS_SUBKEY_CMD), -1);
- }
-
- g_list_free(ja_list);
-}
-
-static gboolean trg_prefs_etc_save_foreachfunc(GtkTreeModel *model,
- GtkTreePath *path, GtkTreeIter *iter, gpointer data) {
- gchar *label, *cmd;
- JsonArray *ja = (JsonArray*) data;
- JsonObject *new = json_object_new();
-
- gtk_tree_model_get(model, iter, 0, &label, 1, &cmd, -1);
-
- json_object_set_string_member(new, TRG_PREFS_KEY_EXEC_COMMANDS_SUBKEY_LABEL, label);
- json_object_set_string_member(new, TRG_PREFS_KEY_EXEC_COMMANDS_SUBKEY_CMD, cmd);
-
- json_array_add_object_element(ja, new);
-
- g_free(label);
- g_free(cmd);
-
- return FALSE;
-}
-
-static void trg_prefs_etv_save(TrgPrefs *prefs, void *wdp) {
- trg_pref_widget_desc *wd = (trg_pref_widget_desc*) wdp;
- JsonNode *node = trg_prefs_get_value(prefs, wd->key, JSON_NODE_ARRAY,
- wd->flags | TRG_PREFS_REPLACENODE);
- JsonArray *ja = json_array_new();
- GtkTreeView *tv = GTK_TREE_VIEW(wd->widget);
- GtkTreeModel *model = gtk_tree_view_get_model(tv);
-
- gtk_tree_model_foreach(model, trg_prefs_etc_save_foreachfunc, ja);
- json_node_take_array(node, ja);
- trg_prefs_changed_emit_signal(prefs, wd->key);
-}
-
-static GtkWidget *trg_prefs_execTreeView(TrgPreferencesDialog *dlg) {
+static GtkWidget *trg_prefs_openExecPage(TrgPreferencesDialog *dlg) {
TrgPreferencesDialogPrivate *priv = TRG_PREFERENCES_DIALOG_GET_PRIVATE(dlg);
- GtkListStore *model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
- GtkWidget *tv = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model));
- GtkTreeViewColumn *column;
- GtkCellRenderer *renderer;
- GtkTreeSelection *selection;
+ GtkWidget *t;
+ TrgPersistentTreeView *ptv;
+ GtkListStore *model;
trg_pref_widget_desc *wd;
+ gint row = 0;
- g_object_unref(G_OBJECT(model));
-
- gtk_tree_view_set_rubber_banding(GTK_TREE_VIEW(tv), TRUE);
- //gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tv), FALSE);
-
- renderer = gtk_cell_renderer_text_new();
- g_object_set(G_OBJECT(renderer), "editable", TRUE, NULL);
- g_signal_connect(renderer, "edited",
- G_CALLBACK(trg_etv_label_edited), model);
- column = priv->etvLabelColumn = gtk_tree_view_column_new_with_attributes(
- _("Label"), renderer, "text", 0, NULL);
- gtk_tree_view_append_column(GTK_TREE_VIEW(tv), column);
-
- renderer = gtk_cell_renderer_text_new();
- g_object_set(G_OBJECT(renderer), "editable", TRUE, NULL);
- g_signal_connect(renderer, "edited",
- G_CALLBACK(trg_etv_cmd_edited), model);
- column = gtk_tree_view_column_new_with_attributes(_("Command"), renderer,
- "text", 1, NULL);
- gtk_tree_view_append_column(GTK_TREE_VIEW(tv), column);
+ t = hig_workarea_create();
- selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv));
+ hig_workarea_add_section_title(t, &row, _("Remote Commands"));
- g_signal_connect(G_OBJECT(selection), "changed",
- G_CALLBACK(exec_selection_changed), dlg);
+ model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
- wd = trg_pref_widget_desc_new(tv, TRG_PREFS_KEY_EXEC_COMMANDS,
- TRG_PREFS_PROFILE);
- wd->saveFunc = &trg_prefs_etv_save;
- wd->refreshFunc = &trg_prefs_etv_refresh;
+ ptv = trg_persistent_tree_view_new(priv->prefs, model, TRG_PREFS_KEY_EXEC_COMMANDS);
+ trg_persistent_tree_view_set_add_select(ptv,
+ trg_persistent_tree_view_add_column(ptv, 0, TRG_PREFS_SUBKEY_LABEL, _("Label")));
+ trg_persistent_tree_view_add_column(ptv, 1, TRG_PREFS_KEY_EXEC_COMMANDS_SUBKEY_CMD, _("Command"));
+ wd = trg_persistent_tree_view_get_widget_desc(ptv);
+ trg_persistent_tree_view_build(ptv);
+ trg_pref_widget_refresh(dlg, wd);
priv->widgets = g_list_append(priv->widgets, wd);
- trg_prefs_etv_refresh(priv->prefs, wd);
-
- return tv;
-}
-
-static void trg_prefs_add_exec_cb(GtkWidget *w, gpointer data) {
- TrgPreferencesDialogPrivate *priv =
- TRG_PREFERENCES_DIALOG_GET_PRIVATE(data);
- GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(priv->etv));
- GtkTreeIter iter;
- GtkTreePath *path;
-
- gtk_list_store_append(GTK_LIST_STORE(model), &iter);
- path = gtk_tree_model_get_path(model, &iter);
- gtk_tree_view_set_cursor(GTK_TREE_VIEW(priv->etv), path,
- priv->etvLabelColumn, TRUE);
- gtk_tree_path_free(path);
-}
-
-static void trg_prefs_del_exec_cb(GtkWidget *w, gpointer data) {
- GtkTreeView *tv = GTK_TREE_VIEW(data);
- GtkTreeSelection *selection = gtk_tree_view_get_selection(tv);
- GtkTreeModel *model;
- GtkTreeIter iter;
+ gtk_table_attach(GTK_TABLE(t), GTK_WIDGET(ptv), 1, 2, row,
+ row + 1, GTK_EXPAND | GTK_SHRINK | GTK_FILL,
+ GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0);
- if (gtk_tree_selection_get_selected(selection, &model, &iter))
- gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
+ return t;
}
-static GtkWidget *trg_prefs_openExecPage(TrgPreferencesDialog *dlg) {
+static GtkWidget *trg_prefs_dirsPage(TrgPreferencesDialog *dlg) {
TrgPreferencesDialogPrivate *priv = TRG_PREFERENCES_DIALOG_GET_PRIVATE(dlg);
- GtkWidget *t, *hbox, *w;
+ GtkWidget *t;
+ TrgPersistentTreeView *ptv;
+ GtkListStore *model;
+ trg_pref_widget_desc *wd;
gint row = 0;
t = hig_workarea_create();
- //frame = gtk_frame_new("Profile name...");
+ hig_workarea_add_section_title(t, &row, _("Destinations"));
- hig_workarea_add_section_title(t, &row, _("Remote Commands"));
+ model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
- priv->etv = trg_prefs_execTreeView(dlg);
+ ptv = trg_persistent_tree_view_new(priv->prefs, model, TRG_PREFS_KEY_DESTINATIONS);
+ trg_persistent_tree_view_set_add_select(ptv,
+ trg_persistent_tree_view_add_column(ptv, 0, TRG_PREFS_SUBKEY_LABEL, _("Label")));
+ trg_persistent_tree_view_add_column(ptv, 1, TRG_PREFS_KEY_DESTINATIONS_SUBKEY_DIR, _("Directory"));
+ wd = trg_persistent_tree_view_get_widget_desc(ptv);
+ trg_persistent_tree_view_build(ptv);
+ trg_pref_widget_refresh(dlg, wd);
+ priv->widgets = g_list_append(priv->widgets, wd);
- gtk_table_attach(GTK_TABLE(t), my_scrolledwin_new(priv->etv), 1, 2, row,
+ gtk_table_attach(GTK_TABLE(t), GTK_WIDGET(ptv), 1, 2, row,
row + 1, GTK_EXPAND | GTK_SHRINK | GTK_FILL,
GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0);
- row++;
-
- hbox = gtk_hbox_new(FALSE, 0);
- w = gtk_button_new_from_stock(GTK_STOCK_ADD);
- g_signal_connect(w, "clicked", G_CALLBACK(trg_prefs_add_exec_cb), dlg);
- gtk_box_pack_start(GTK_BOX(hbox), w, FALSE, FALSE, 4);
-
- w = priv->execDelButton = gtk_button_new_from_stock(GTK_STOCK_DELETE);
- gtk_widget_set_sensitive(w, FALSE);
- g_signal_connect(w, "clicked", G_CALLBACK(trg_prefs_del_exec_cb), priv->etv);
- gtk_box_pack_start(GTK_BOX(hbox), w, FALSE, FALSE, 4);
-
- hig_workarea_add_wide_control(t, &row, hbox);
-
- //gtk_container_add(GTK_CONTAINER(frame), t);
- //return frame;
-
return t;
}
@@ -887,6 +751,10 @@ static GObject *trg_preferences_dialog_constructor(GType type,
trg_prefs_openExecPage(TRG_PREFERENCES_DIALOG(object)),
gtk_label_new(_("Remote Execute")));
+ /*gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
+ trg_prefs_dirsPage(TRG_PREFERENCES_DIALOG(object)),
+ gtk_label_new(_("Directories")));*/
+
gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
trg_prefs_desktopPage(TRG_PREFERENCES_DIALOG(object)),
gtk_label_new(_("Desktop")));
diff --git a/src/trg-preferences-dialog.h b/src/trg-preferences-dialog.h
index 8b90284..92190a6 100644
--- a/src/trg-preferences-dialog.h
+++ b/src/trg-preferences-dialog.h
@@ -58,5 +58,8 @@ GType trg_preferences_dialog_get_type(void);
GtkWidget *trg_preferences_dialog_get_instance(TrgMainWindow * win,
TrgClient * client);
+trg_pref_widget_desc* trg_pref_widget_desc_new(GtkWidget *w, gchar *key,
+ int flags);
+
G_END_DECLS
#endif /* TRG_PREFERENCES_WINDOW_H_ */
diff --git a/src/trg-prefs.h b/src/trg-prefs.h
index d340d8a..61ac369 100644
--- a/src/trg-prefs.h
+++ b/src/trg-prefs.h
@@ -67,9 +67,12 @@
#define TRG_PREFS_KEY_TV_WIDTHS "widths"
#define TRG_PREFS_KEY_NOTEBOOK_PANED_POS "notebook-paned-pos"
#define TRG_PREFS_KEY_STATES_PANED_POS "states-paned-pos"
+#define TRG_PREFS_SUBKEY_LABEL "label"
#define TRG_PREFS_KEY_EXEC_COMMANDS "exec-commands"
#define TRG_PREFS_KEY_EXEC_COMMANDS_SUBKEY_CMD "cmd"
-#define TRG_PREFS_KEY_EXEC_COMMANDS_SUBKEY_LABEL "label"
+#define TRG_PREFS_KEY_DESTINATIONS "destinations"
+#define TRG_PREFS_KEY_DESTINATIONS_SUBKEY_DIR "dir"
+
#define TRG_PREFS_NOFLAGS (1 << 0) /* 0x00 */
#define TRG_PREFS_GLOBAL (1 << 1) /* 0x01 */
diff --git a/src/trg-torrent-add-dialog.c b/src/trg-torrent-add-dialog.c
index 2e8ccf9..9589751 100644
--- a/src/trg-torrent-add-dialog.c
+++ b/src/trg-torrent-add-dialog.c
@@ -231,7 +231,7 @@ trg_torrent_add_response_cb(GtkDialog * dlg, gint res_id, gpointer data)
gtk_combo_box_get_active(GTK_COMBO_BOX(priv->priority_combo)) -
1;
gchar *dir =
- gtk_combo_box_get_active_text(GTK_COMBO_BOX(priv->dest_combo));
+ trg_destination_combo_get_dir(TRG_DESTINATION_COMBO(priv->dest_combo));
if (g_slist_length(priv->filenames) == 1) {
JsonNode *req =
@@ -258,6 +258,8 @@ trg_torrent_add_response_cb(GtkDialog * dlg, gint res_id, gpointer data)
launch_add_thread(args);
}
+
+ g_free(dir);
} else {
g_str_slist_free(priv->filenames);
}
diff --git a/src/trg-torrent-move-dialog.c b/src/trg-torrent-move-dialog.c
index c742e98..8ea6802 100644
--- a/src/trg-torrent-move-dialog.c
+++ b/src/trg-torrent-move-dialog.c
@@ -60,14 +60,14 @@ trg_torrent_move_response_cb(GtkDialog * dlg, gint res_id, gpointer data)
if (res_id == GTK_RESPONSE_ACCEPT) {
gchar *location =
- gtk_combo_box_get_active_text(GTK_COMBO_BOX
+ trg_destination_combo_get_dir(TRG_DESTINATION_COMBO
(priv->location_combo));
JsonNode *request = torrent_set_location(priv->ids, location,
gtk_toggle_button_get_active
(GTK_TOGGLE_BUTTON
(priv->move_check)));
- request_set_tag_from_ids(request, priv->ids);
g_free(location);
+ request_set_tag_from_ids(request, priv->ids);
dispatch_async(priv->client, request,
on_generic_interactive_action, data);
} else {