summaryrefslogtreecommitdiff
path: root/src/trg-persistent-tree-view.c
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 /src/trg-persistent-tree-view.c
parent3b8fd9e7274477cfad98d66e41a43417ce8d21bf (diff)
make the execute command tree view in preferences a generic widget, the "persistent tree view"
Diffstat (limited to 'src/trg-persistent-tree-view.c')
-rw-r--r--src/trg-persistent-tree-view.c368
1 files changed, 368 insertions, 0 deletions
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);
+}