summaryrefslogtreecommitdiffstats
path: root/src/legacy/treeview.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/legacy/treeview.c')
-rw-r--r--src/legacy/treeview.c289
1 files changed, 289 insertions, 0 deletions
diff --git a/src/legacy/treeview.c b/src/legacy/treeview.c
new file mode 100644
index 0000000..b50393d
--- /dev/null
+++ b/src/legacy/treeview.c
@@ -0,0 +1,289 @@
+/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+#include <config.h>
+
+#include "treeview.h"
+
+typedef struct
+{
+ GSettings *settings;
+ gboolean store_column_order;
+ GHashTable *excluded_columns;
+} GsmTreeViewPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (GsmTreeView, gsm_tree_view, GTK_TYPE_TREE_VIEW)
+
+static void
+gsm_tree_view_finalize (GObject *object)
+{
+ GsmTreeViewPrivate *priv = gsm_tree_view_get_instance_private (GSM_TREE_VIEW (object));
+
+ g_hash_table_destroy (priv->excluded_columns);
+ priv->excluded_columns = NULL;
+
+ G_OBJECT_CLASS (gsm_tree_view_parent_class)->finalize (object);
+}
+
+static void
+gsm_tree_view_class_init (GsmTreeViewClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = gsm_tree_view_finalize;
+}
+
+static void
+gsm_tree_view_init (GsmTreeView *self)
+{
+ GsmTreeViewPrivate *priv = gsm_tree_view_get_instance_private (self);
+
+ priv->excluded_columns = g_hash_table_new (g_direct_hash, g_direct_equal);
+}
+
+void
+gsm_tree_view_save_state (GsmTreeView *tree_view)
+{
+ GsmTreeViewPrivate *priv;
+
+ g_return_if_fail (GSM_IS_TREE_VIEW (tree_view));
+
+ priv = gsm_tree_view_get_instance_private (tree_view);
+ GtkTreeModel *model;
+ gint sort_col;
+ GtkSortType sort_type;
+
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
+ g_settings_delay (priv->settings);
+ if (gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (model),
+ &sort_col,
+ &sort_type)) {
+ g_settings_set_int (priv->settings, "sort-col", sort_col);
+ g_settings_set_int (priv->settings, "sort-order", sort_type);
+ }
+
+ if (priv->store_column_order) {
+ GList *columns = gtk_tree_view_get_columns (GTK_TREE_VIEW (tree_view));
+ GList *iter;
+ GVariantBuilder builder;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
+
+ for (iter = columns; iter != NULL; iter = iter->next) {
+ gint id = gtk_tree_view_column_get_sort_column_id (GTK_TREE_VIEW_COLUMN (iter->data));
+ g_variant_builder_add (&builder, "i", id);
+ }
+
+ g_settings_set_value (priv->settings, "columns-order",
+ g_variant_builder_end (&builder));
+
+ g_list_free (columns);
+ }
+
+ g_settings_apply (priv->settings);
+}
+
+GtkTreeViewColumn *
+gsm_tree_view_get_column_from_id (GsmTreeView *tree_view, gint sort_id)
+{
+ GList *columns;
+ GList *iter;
+ GtkTreeViewColumn *col = NULL;
+
+ g_return_val_if_fail (GSM_IS_TREE_VIEW (tree_view), NULL);
+
+ columns = gtk_tree_view_get_columns (GTK_TREE_VIEW (tree_view));
+
+ for (iter = columns; iter != NULL; iter = iter->next) {
+ col = GTK_TREE_VIEW_COLUMN (iter->data);
+ if (gtk_tree_view_column_get_sort_column_id (col) == sort_id)
+ break;
+ }
+
+ g_list_free (columns);
+
+ return col;
+}
+
+static gboolean
+cb_column_header_clicked (GtkTreeViewColumn *column, GdkEventButton *event, gpointer data)
+{
+ GtkMenu *menu = GTK_MENU (data);
+
+ if (event->button == GDK_BUTTON_SECONDARY) {
+ gtk_menu_popup_at_pointer (menu, (GdkEvent*)event);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void
+gsm_tree_view_load_state (GsmTreeView *tree_view)
+{
+ GsmTreeViewPrivate *priv;
+ GtkTreeModel *model;
+ gint sort_col;
+ GtkSortType sort_type;
+
+ g_return_if_fail (GSM_IS_TREE_VIEW (tree_view));
+
+ priv = gsm_tree_view_get_instance_private (tree_view);
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
+
+ sort_col = g_settings_get_int (priv->settings, "sort-col");
+ sort_type = g_settings_get_int (priv->settings, "sort-order");
+
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
+ sort_col,
+ sort_type);
+
+ if (priv->store_column_order) {
+ GtkMenu *header_menu = GTK_MENU (gtk_menu_new ());
+ GList *columns = gtk_tree_view_get_columns (GTK_TREE_VIEW (tree_view));
+ GList *iter;
+ GVariantIter *var_iter;
+ GtkTreeViewColumn *col, *last;
+ gint sort_id;
+
+ for (iter = columns; iter != NULL; iter = iter->next) {
+ const char *title;
+ char *key;
+ GtkButton *button;
+ GtkCheckMenuItem *column_item;
+
+ col = GTK_TREE_VIEW_COLUMN (iter->data);
+ sort_id = gtk_tree_view_column_get_sort_column_id (col);
+
+ if (priv->excluded_columns &&
+ g_hash_table_contains (priv->excluded_columns, GINT_TO_POINTER (sort_id))) {
+ gtk_tree_view_column_set_visible (col, FALSE);
+ continue;
+ }
+
+ title = gtk_tree_view_column_get_title (col);
+
+ button = GTK_BUTTON (gtk_tree_view_column_get_button (col));
+ g_signal_connect (button, "button-press-event",
+ G_CALLBACK (cb_column_header_clicked),
+ header_menu);
+
+ column_item = GTK_CHECK_MENU_ITEM (gtk_check_menu_item_new_with_label (title));
+ g_object_bind_property (col, "visible",
+ column_item, "active",
+ G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+
+ gtk_menu_shell_append (GTK_MENU_SHELL (header_menu), GTK_WIDGET (column_item));
+
+ key = g_strdup_printf ("col-%d-width", sort_id);
+ gtk_tree_view_column_set_fixed_width (col, g_settings_get_int (priv->settings, key));
+ gtk_tree_view_column_set_min_width (col, 30);
+ g_free (key);
+
+ key = g_strdup_printf ("col-%d-visible", sort_id);
+ gtk_tree_view_column_set_visible (col, g_settings_get_boolean (priv->settings, key));
+ g_free (key);
+ }
+
+ g_list_free (columns);
+
+ gtk_widget_show_all (GTK_WIDGET (header_menu));
+
+ g_settings_get (priv->settings, "columns-order", "ai", &var_iter);
+ last = NULL;
+ while (g_variant_iter_loop (var_iter, "i", &sort_id)) {
+ col = gsm_tree_view_get_column_from_id (tree_view, sort_id);
+
+ if (col != NULL && col != last) {
+ gtk_tree_view_move_column_after (GTK_TREE_VIEW (tree_view),
+ col, last);
+ last = col;
+ }
+ }
+ g_variant_iter_free (var_iter);
+ }
+}
+
+void
+gsm_tree_view_add_excluded_column (GsmTreeView *tree_view, gint column_id)
+{
+ GsmTreeViewPrivate *priv;
+
+ g_return_if_fail (GSM_IS_TREE_VIEW (tree_view));
+
+ priv = gsm_tree_view_get_instance_private (tree_view);
+ g_hash_table_add (priv->excluded_columns, GINT_TO_POINTER (column_id));
+}
+
+static guint timeout_id = 0;
+static GtkTreeViewColumn *current_column;
+
+static gboolean
+save_column_state (gpointer data)
+{
+ GSettings *settings = G_SETTINGS (data);
+ gint column_id = gtk_tree_view_column_get_sort_column_id (current_column);
+ gint width = gtk_tree_view_column_get_width (current_column);
+ gboolean visible = gtk_tree_view_column_get_visible (current_column);
+
+ gchar *key;
+ g_settings_delay (settings);
+
+ key = g_strdup_printf ("col-%d-width", column_id);
+ g_settings_set_int (settings, key, width);
+ g_free (key);
+
+ key = g_strdup_printf ("col-%d-visible", column_id);
+ g_settings_set_boolean (settings, key, visible);
+ g_free (key);
+ timeout_id = 0;
+ g_settings_apply (settings);
+
+ return FALSE;
+}
+
+static void
+cb_update_column_state (GObject *object, GParamSpec *pspec, gpointer data)
+{
+ GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN (object);
+
+ current_column = column;
+
+ if (timeout_id > 0)
+ g_source_remove (timeout_id);
+
+ timeout_id = g_timeout_add_seconds (1, save_column_state, data);
+}
+
+void
+gsm_tree_view_append_and_bind_column (GsmTreeView *tree_view, GtkTreeViewColumn *column)
+{
+ GsmTreeViewPrivate *priv;
+
+ g_return_if_fail (GSM_IS_TREE_VIEW (tree_view));
+ g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (column));
+
+ priv = gsm_tree_view_get_instance_private (tree_view);
+
+ gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view),
+ column);
+
+ g_signal_connect (column, "notify::fixed-width",
+ G_CALLBACK (cb_update_column_state),
+ priv->settings);
+
+ g_signal_connect (column, "notify::visible",
+ G_CALLBACK (cb_update_column_state),
+ priv->settings);
+}
+
+
+GsmTreeView *
+gsm_tree_view_new (GSettings *settings, gboolean store_column_order)
+{
+ GsmTreeView *self = g_object_new (GSM_TYPE_TREE_VIEW, NULL);
+ GsmTreeViewPrivate *priv = gsm_tree_view_get_instance_private (self);
+
+ priv->settings = settings;
+ priv->store_column_order = store_column_order;
+
+ return self;
+}