[gnome-system-monitor/wip/gsmtreeview] Make a GsmTreeView widget out of a few scattered functions



commit c9ff53e51f10bf7e5a6d6876b3379ecd3fc0cee1
Author: Stefano Facchini <stefano facchini gmail com>
Date:   Sun Aug 11 11:20:11 2013 +0200

    Make a GsmTreeView widget out of a few scattered functions

 src/Makefile.am     |    3 +-
 src/application.cpp |  167 -----------------------------------
 src/application.h   |    6 --
 src/disks.cpp       |   29 ++----
 src/memmaps.cpp     |   20 ++--
 src/openfiles.cpp   |   24 ++----
 src/proctable.cpp   |  109 ++++++-----------------
 src/proctable.h     |    3 -
 src/settings-keys.h |    2 +-
 src/treeview.c      |  241 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/treeview.h      |   43 +++++++++
 src/util.cpp        |   13 ---
 src/util.h          |    3 -
 13 files changed, 341 insertions(+), 322 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 6fda309..98ce336 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -37,7 +37,8 @@ gnome_system_monitor_cpp_files = \
 
 gnome_system_monitor_c_files = \
        e_date.c \
-       gsm_color_button.c
+       gsm_color_button.c \
+       treeview.c
 
 gnome_system_monitor_h_files = \
        $(gnome_system_monitor_cpp_files:.cpp=.h) \
diff --git a/src/application.cpp b/src/application.cpp
index 8a04961..4961f28 100644
--- a/src/application.cpp
+++ b/src/application.cpp
@@ -15,7 +15,6 @@
 #include "settings-keys.h"
 #include "argv.h"
 #include "util.h"
-#include "cgroups.h"
 #include "lsof.h"
 #include "disks.h"
 
@@ -249,172 +248,6 @@ void GsmApplication::on_activate()
     gtk_window_present (GTK_WINDOW (main_window));
 }
 
-static void
-cb_header_menu_position_function (GtkMenu* menu, gint *x, gint *y, gboolean *push_in, gpointer data)
-{
-    GdkEventButton* event = (GdkEventButton *) data;
-    gint wx, wy, ww, wh;
-    gdk_window_get_geometry(event->window, &wx, &wy, &ww, &wh);
-    gdk_window_get_origin(event->window, &wx, &wy);
-
-    *x = wx + event->x;
-    *y = wy + wh;
-    *push_in = TRUE;
-}
-
-static gboolean
-cb_column_header_clicked (GtkTreeViewColumn* column, GdkEvent* event, gpointer data)
-{
-    GtkMenu *menu = (GtkMenu *) data;
-
-    if (event->button.button == GDK_BUTTON_SECONDARY) {
-        gtk_menu_popup(GTK_MENU(menu), NULL, NULL, cb_header_menu_position_function, &(event->button), 
event->button.button, event->button.time);
-        return TRUE;
-    }
-
-    return FALSE;
-}
-
-gboolean
-procman_get_tree_state (GSettings *settings, GtkWidget *tree, const gchar *child_schema)
-{
-    GtkTreeModel *model;
-    GList *columns, *it;
-    gint sort_col;
-    GtkSortType order;
-    GtkWidget *header_menu;
-   
-    g_assert(tree);
-    g_assert(child_schema);
-
-    GSettings *pt_settings = g_settings_get_child (settings, child_schema);
-    model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree));
-    
-    sort_col = g_settings_get_int (pt_settings, "sort-col");
-
-    order = static_cast<GtkSortType>(g_settings_get_int (pt_settings, "sort-order"));
-
-    if (sort_col != -1)
-        gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
-                                              sort_col,
-                                              order);
-
-    columns = gtk_tree_view_get_columns (GTK_TREE_VIEW (tree));
-
-    if(!g_strcmp0(child_schema, "proctree") ||
-       !g_strcmp0(child_schema, "disktreenew"))
-    {
-        header_menu = gtk_menu_new();
-        
-        for(it = columns; it; it = it->next)
-        {
-            GtkTreeViewColumn *column;
-            int id;
-            const gchar *title;
-            GtkWidget* column_item;
-            GtkWidget* button;
-
-            column = static_cast<GtkTreeViewColumn*>(it->data);
-            id = gtk_tree_view_column_get_sort_column_id (column);
-
-            if ((id == COL_CGROUP) && (!cgroups_enabled()))
-                continue;
-
-            if ((id == COL_UNIT ||
-                id == COL_SESSION ||
-                id == COL_SEAT ||
-                id == COL_OWNER)
-#ifdef HAVE_SYSTEMD
-                && !LOGIND_RUNNING()
-#endif
-                )
-                continue;
-            // set the states for the columns visibility menu available by header right click
-            title = gtk_tree_view_column_get_title (column);
-
-            if (!title)
-                title = _("Icon");
-            button = gtk_tree_view_column_get_button(column);
-            g_signal_connect(G_OBJECT(button), "button_press_event", G_CALLBACK(cb_column_header_clicked), 
header_menu);
-
-            column_item = gtk_check_menu_item_new_with_label(title);
-            g_object_bind_property (column, "visible", column_item, "active",
-                                    (GBindingFlags) (G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE));
-            gtk_menu_shell_append(GTK_MENU_SHELL(header_menu), column_item);
-        }
-        gtk_widget_show_all(header_menu);
-        GVariant     *value;
-        GVariantIter iter;
-        int          sortIndex;
-
-        GSList *order = NULL;
-
-        value = g_settings_get_value(pt_settings, "columns-order");
-        g_variant_iter_init(&iter, value);
-
-        while (g_variant_iter_loop (&iter, "i", &sortIndex))
-            order = g_slist_append(order, GINT_TO_POINTER(sortIndex));
-
-        proctable_set_columns_order(GTK_TREE_VIEW(tree), order);
-
-        g_variant_unref(value);
-        g_slist_free(order);
-    }
-
-    g_object_unref(pt_settings);
-    pt_settings = NULL;
-
-    g_list_free(columns);
-
-    return TRUE;
-}
-
-void
-procman_save_tree_state (GSettings *settings, GtkWidget *tree, const gchar *child_schema)
-{
-    GtkTreeModel *model;
-    GList *columns;
-    gint sort_col;
-    GtkSortType order;
-
-    g_assert(tree);
-    g_assert(child_schema);
-
-    GSettings *pt_settings = g_settings_get_child (settings, child_schema);
-    model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree));
-   
-    if (gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (model), &sort_col,
-                                              &order)) {
-        g_settings_set_int (pt_settings, "sort-col", sort_col);
-        g_settings_set_int (pt_settings, "sort-order", order);
-    }
-
-    columns = gtk_tree_view_get_columns (GTK_TREE_VIEW (tree));
-
-    if(!g_strcmp0(child_schema, "proctree") || !g_strcmp0(child_schema, "disktreenew"))
-    {
-        GSList *order;
-        GSList *order_node;
-        GVariantBuilder *builder;
-        GVariant *order_variant;
-
-        order = proctable_get_columns_order(GTK_TREE_VIEW(tree));
-
-        builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
-
-        for(order_node = order; order_node; order_node = order_node->next)
-            g_variant_builder_add(builder, "i", GPOINTER_TO_INT(order_node->data));
-
-        order_variant = g_variant_new("ai", builder);
-        g_settings_set_value(pt_settings, "columns-order", order_variant);
-
-        g_variant_builder_unref(builder);
-        g_slist_free(order);
-    }
-
-    g_list_free(columns);
-}
-
 void
 GsmApplication::save_config ()
 {
diff --git a/src/application.h b/src/application.h
index 0780edd..8a32d14 100644
--- a/src/application.h
+++ b/src/application.h
@@ -211,10 +211,4 @@ struct KillArgs
     int signal;
 };
 
-
-void            procman_save_tree_state (GSettings *settings, GtkWidget *tree, const gchar *prefix);
-gboolean        procman_get_tree_state (GSettings *settings, GtkWidget *tree, const gchar *prefix);
-
-
-
 #endif /* _GSM_APPLICATION_H_ */
diff --git a/src/disks.cpp b/src/disks.cpp
index fe30ecb..59a475a 100644
--- a/src/disks.cpp
+++ b/src/disks.cpp
@@ -13,6 +13,7 @@
 #include "util.h"
 #include "iconthemewrapper.h"
 #include "settings-keys.h"
+#include "treeview.h"
 
 enum DiskColumns
 {
@@ -38,9 +39,7 @@ cb_sort_changed (GtkTreeSortable *model, gpointer data)
 {
     GsmApplication *app = (GsmApplication *) data;
 
-    procman_save_tree_state (app->settings,
-                             GTK_WIDGET (app->disk_list),
-                             GSM_SETTINGS_CHILD_DISKS);
+    gsm_tree_view_save_state (GSM_TREE_VIEW (app->disk_list));
 }
 
 static void
@@ -298,11 +297,7 @@ disks_reset_timeout (GsmApplication *app)
 static void
 cb_disk_columns_changed(GtkTreeView *treeview, gpointer data)
 {
-    GsmApplication *app = static_cast<GsmApplication *>(data);
-
-    procman_save_tree_state (app->settings,
-                             GTK_WIDGET (treeview),
-                             GSM_SETTINGS_CHILD_DISKS);
+    gsm_tree_view_save_state (GSM_TREE_VIEW (treeview));
 }
 
 
@@ -395,8 +390,9 @@ create_disk_view(GsmApplication *app, GtkBuilder *builder)
                                GDK_TYPE_PIXBUF,     /* DISK_ICON */
                                G_TYPE_INT           /* DISK_USED_PERCENTAGE */
         );
-    
-    disk_tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model));
+    disk_tree = gsm_tree_view_new (settings, TRUE);
+    gtk_tree_view_set_model (GTK_TREE_VIEW (disk_tree), GTK_TREE_MODEL (model));
+
     g_signal_connect(G_OBJECT(disk_tree), "row-activated", G_CALLBACK(open_dir), NULL);
     app->disk_list = disk_tree;
     gtk_container_add(GTK_CONTAINER(scrolled), disk_tree);
@@ -418,11 +414,10 @@ create_disk_view(GsmApplication *app, GtkBuilder *builder)
                                         NULL);
     gtk_tree_view_column_set_title(col, _(titles[DISK_DEVICE]));
     gtk_tree_view_column_set_sort_column_id(col, DISK_DEVICE);
-    bind_column_to_gsetting (settings, col);  
     gtk_tree_view_column_set_reorderable(col, TRUE);
     gtk_tree_view_column_set_resizable(col, TRUE);
     gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_FIXED);
-    gtk_tree_view_append_column(GTK_TREE_VIEW(disk_tree), col);
+    gsm_tree_view_append_and_bind_column (GSM_TREE_VIEW (disk_tree), col);
 
 
     /* sizes - used */
@@ -434,10 +429,9 @@ create_disk_view(GsmApplication *app, GtkBuilder *builder)
         gtk_tree_view_column_set_title(col, _(titles[i]));
         gtk_tree_view_column_set_resizable(col, TRUE);
         gtk_tree_view_column_set_sort_column_id(col, i);
-        bind_column_to_gsetting (settings, col);
         gtk_tree_view_column_set_reorderable(col, TRUE);
         gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_FIXED);
-        gtk_tree_view_append_column(GTK_TREE_VIEW(disk_tree), col);
+        gsm_tree_view_append_and_bind_column (GSM_TREE_VIEW (disk_tree), col);
         switch (i) {
             case DISK_TOTAL:
             case DISK_FREE:
@@ -474,17 +468,14 @@ create_disk_view(GsmApplication *app, GtkBuilder *builder)
     gtk_tree_view_column_pack_start(col, cell, TRUE);
     gtk_tree_view_column_set_attributes(col, cell, "value",
                                         DISK_USED_PERCENTAGE, NULL);
-    gtk_tree_view_append_column(GTK_TREE_VIEW(disk_tree), col);
     gtk_tree_view_column_set_resizable(col, TRUE);
     gtk_tree_view_column_set_sort_column_id(col, DISK_USED);
-    bind_column_to_gsetting (settings, col);
     gtk_tree_view_column_set_reorderable(col, TRUE);
+    gsm_tree_view_append_and_bind_column (GSM_TREE_VIEW (disk_tree), col);
 
     /* numeric sort */
 
-    procman_get_tree_state (app->settings, disk_tree,
-                            GSM_SETTINGS_CHILD_DISKS);
-
+    gsm_tree_view_load_state (GSM_TREE_VIEW (disk_tree));
     g_signal_connect (G_OBJECT(disk_tree), "destroy",
                       G_CALLBACK(cb_disk_list_destroying),
                       app);
diff --git a/src/memmaps.cpp b/src/memmaps.cpp
index 649e2fe..6eeb35f 100644
--- a/src/memmaps.cpp
+++ b/src/memmaps.cpp
@@ -19,6 +19,7 @@ using std::string;
 #include "memmaps.h"
 #include "proctable.h"
 #include "settings-keys.h"
+#include "treeview.h"
 #include "util.h"
 
 
@@ -158,23 +159,19 @@ namespace
     public:
         guint timer;
         GtkWidget *tree;
-        GSettings *settings;
         ProcInfo *info;
         OffsetFormater format;
         mutable InodeDevices devices;
-        const char * const schema;
 
-        MemMapsData(GtkWidget *a_tree, GSettings *a_settings)
-            : tree(a_tree),
-              settings(a_settings),
-              schema(GSM_SETTINGS_CHILD_MEMMAP)
+        MemMapsData(GtkWidget *a_tree)
+            : tree(a_tree)
         {
-            procman_get_tree_state(this->settings, this->tree, this->schema);
+            gsm_tree_view_load_state (GSM_TREE_VIEW (this->tree));
         }
 
         ~MemMapsData()
         {
-            procman_save_tree_state(this->settings, this->tree, this->schema);
+            gsm_tree_view_save_state (GSM_TREE_VIEW (this->tree));
         }
     };
 }
@@ -379,7 +376,10 @@ create_memmapsdata (GsmApplication *app)
                                 G_TYPE_UINT64 /* MMAP_COL_INODE      */
         );
 
-    tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
+    GSettings *settings = g_settings_get_child (app->settings, GSM_SETTINGS_CHILD_MEMMAP);
+
+    tree = gsm_tree_view_new (settings, FALSE);
+    gtk_tree_view_set_model (GTK_TREE_VIEW (tree), GTK_TREE_MODEL (model));
     gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (tree), TRUE);
     g_object_unref (G_OBJECT (model));
 
@@ -427,7 +427,7 @@ create_memmapsdata (GsmApplication *app)
         }
     }
 
-    return new MemMapsData(tree, app->settings);
+    return new MemMapsData(tree);
 }
 
 
diff --git a/src/openfiles.cpp b/src/openfiles.cpp
index 2b5277f..abadc07 100644
--- a/src/openfiles.cpp
+++ b/src/openfiles.cpp
@@ -15,6 +15,7 @@
 #include "proctable.h"
 #include "util.h"
 #include "settings-keys.h"
+#include "treeview.h"
 
 #ifndef NI_IDN
 #define NI_IDN 0
@@ -221,11 +222,9 @@ static void
 close_openfiles_dialog (GtkDialog *dialog, gint id, gpointer data)
 {
     GtkWidget *tree = static_cast<GtkWidget*>(data);
-    GSettings *settings;
     guint timer;
 
-    settings = static_cast<GSettings*>(g_object_get_data (G_OBJECT (tree), "settings"));
-    procman_save_tree_state (settings, tree, GSM_SETTINGS_CHILD_OPEN_FILES);
+    gsm_tree_view_save_state (GSM_TREE_VIEW (tree));
 
     timer = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (tree), "timer"));
     g_source_remove (timer);
@@ -261,7 +260,10 @@ create_openfiles_tree (GsmApplication *app)
                                 G_TYPE_POINTER      /* open_files_entry */
         );
 
-    tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
+    GSettings *settings = g_settings_get_child (app->settings, GSM_SETTINGS_CHILD_OPEN_FILES);
+
+    tree = gsm_tree_view_new (settings, FALSE);
+    gtk_tree_view_set_model (GTK_TREE_VIEW (tree), GTK_TREE_MODEL (model));
     gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (tree), TRUE);
     g_object_unref (G_OBJECT (model));
 
@@ -283,18 +285,7 @@ create_openfiles_tree (GsmApplication *app)
         gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
     }
 
-#if 0
-    gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (model),
-                                     COL_VMSZ,
-                                     sort_ints,
-                                     GINT_TO_POINTER (COL_FD),
-                                     NULL);
-/*gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
-  0,
-  GTK_SORT_ASCENDING);*/
-#endif
-
-    procman_get_tree_state (app->settings, tree, GSM_SETTINGS_CHILD_OPEN_FILES);
+    gsm_tree_view_load_state (GSM_TREE_VIEW (tree));
 
     return tree;
 
@@ -354,7 +345,6 @@ create_single_openfiles_dialog (GtkTreeModel *model, GtkTreePath *path,
     tree = create_openfiles_tree (app);
     gtk_container_add (GTK_CONTAINER (scrolled), tree);
     g_object_set_data (G_OBJECT (tree), "selected_info", GUINT_TO_POINTER (info->pid));
-    g_object_set_data (G_OBJECT (tree), "settings", app->settings);
 
     g_signal_connect (G_OBJECT (openfilesdialog), "response",
                       G_CALLBACK (close_openfiles_dialog), tree);
diff --git a/src/proctable.cpp b/src/proctable.cpp
index bc38d9e..14ac66c 100644
--- a/src/proctable.cpp
+++ b/src/proctable.cpp
@@ -62,6 +62,7 @@
 #include "selinux.h"
 #include "settings-keys.h"
 #include "cgroups.h"
+#include "treeview.h"
 
 ProcInfo::UserMap ProcInfo::users;
 ProcInfo::List ProcInfo::all;
@@ -79,79 +80,7 @@ cb_save_tree_state(gpointer, gpointer data)
 {
     GsmApplication * const app = static_cast<GsmApplication *>(data);
 
-    procman_save_tree_state (app->settings,
-                             GTK_WIDGET (app->tree),
-                             GSM_SETTINGS_CHILD_PROCESSES);
-}
-
-static GtkTreeViewColumn*
-my_gtk_tree_view_get_column_with_sort_column_id(GtkTreeView *treeview, int id)
-{
-    GList *columns, *it;
-    GtkTreeViewColumn *col = NULL;
-
-    columns = gtk_tree_view_get_columns(treeview);
-
-    for(it = columns; it; it = it->next)
-    {
-        if(gtk_tree_view_column_get_sort_column_id(static_cast<GtkTreeViewColumn*>(it->data)) == id)
-        {
-            col = static_cast<GtkTreeViewColumn*>(it->data);
-            break;
-        }
-    }
-
-    g_list_free(columns);
-
-    return col;
-}
-
-void
-proctable_set_columns_order(GtkTreeView *treeview, GSList *order)
-{
-    GtkTreeViewColumn* last = NULL;
-    GSList *it;
-
-    for(it = order; it; it = it->next)
-    {
-        int id;
-        GtkTreeViewColumn *cur;
-
-        id = GPOINTER_TO_INT(it->data);
-
-        g_assert(id >= 0 && id < NUM_COLUMNS);
-
-        cur = my_gtk_tree_view_get_column_with_sort_column_id(treeview, id);
-
-        if(cur && cur != last)
-        {
-            gtk_tree_view_move_column_after(treeview, cur, last);
-            last = cur;
-        }
-    }
-}
-
-GSList*
-proctable_get_columns_order(GtkTreeView *treeview)
-{
-    GList *columns, *col;
-    GSList *order = NULL;
-
-    columns = gtk_tree_view_get_columns(treeview);
-
-    for(col = columns; col; col = col->next)
-    {
-        int id;
-
-        id = gtk_tree_view_column_get_sort_column_id(static_cast<GtkTreeViewColumn*>(col->data));
-        order = g_slist_prepend(order, GINT_TO_POINTER(id));
-    }
-
-    g_list_free(columns);
-
-    order = g_slist_reverse(order);
-
-    return order;
+    gsm_tree_view_save_state (GSM_TREE_VIEW (app->tree));
 }
 
 static void
@@ -446,7 +375,9 @@ proctable_new (GsmApplication * const app)
     
     model_sort = GTK_TREE_MODEL_SORT (gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (model_filter)));
     
-    proctree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model_sort));
+    proctree = gsm_tree_view_new (settings, TRUE);
+    gtk_tree_view_set_model (GTK_TREE_VIEW (proctree), GTK_TREE_MODEL (model_sort));
+
     gtk_tree_view_set_tooltip_column (GTK_TREE_VIEW (proctree), COL_TOOLTIP);
     gtk_tree_view_set_show_expanders (GTK_TREE_VIEW (proctree),
                                       g_settings_get_boolean (app->settings, GSM_SETTING_SHOW_DEPENDENCIES));
@@ -470,12 +401,12 @@ proctable_new (GsmApplication * const app)
     gtk_tree_view_column_set_title (column, _(titles[0]));
 
     gtk_tree_view_column_set_sort_column_id (column, COL_NAME);
-    bind_column_to_gsetting (settings, column);
     gtk_tree_view_column_set_resizable (column, TRUE);
     gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
     gtk_tree_view_column_set_min_width (column, 1);
     gtk_tree_view_column_set_reorderable(column, TRUE);
-    gtk_tree_view_append_column (GTK_TREE_VIEW (proctree), column);
+
+    gsm_tree_view_append_and_bind_column (GSM_TREE_VIEW (proctree), column);
     gtk_tree_view_set_expander_column (GTK_TREE_VIEW (proctree), column);
 
     for (i = COL_USER; i <= COL_PRIORITY; i++) {
@@ -496,9 +427,8 @@ proctable_new (GsmApplication * const app)
         gtk_tree_view_column_set_title(col, _(titles[i]));
         gtk_tree_view_column_set_resizable(col, TRUE);
         gtk_tree_view_column_set_sort_column_id(col, i);
-        bind_column_to_gsetting (settings, col);
         gtk_tree_view_column_set_reorderable(col, TRUE);
-        gtk_tree_view_append_column(GTK_TREE_VIEW(proctree), col);
+        gsm_tree_view_append_and_bind_column (GSM_TREE_VIEW (proctree), col);
 
         // type
         switch (i) {
@@ -611,18 +541,33 @@ proctable_new (GsmApplication * const app)
     app->last_vscroll_max = 0;
     app->last_vscroll_value = 0;
 
-    procman_get_tree_state (app->settings, proctree, "proctree");
+    if (!cgroups_enabled ())
+        gsm_tree_view_add_excluded_column (GSM_TREE_VIEW (proctree), COL_CGROUP);
+
+#ifdef HAVE_SYSTEMD
+    if (!LOGIND_RUNNING ()) {
+#else
+    {
+#endif
+        gsm_tree_view_add_excluded_column (GSM_TREE_VIEW (proctree), COL_UNIT);
+        gsm_tree_view_add_excluded_column (GSM_TREE_VIEW (proctree), COL_SESSION);
+        gsm_tree_view_add_excluded_column (GSM_TREE_VIEW (proctree), COL_SEAT);
+        gsm_tree_view_add_excluded_column (GSM_TREE_VIEW (proctree), COL_OWNER);
+    }
+
+    gsm_tree_view_load_state (GSM_TREE_VIEW (proctree));
+
     /* Override column settings by hiding this column if it's meaningless: */
     if (!can_show_security_context_column ()) {
         GtkTreeViewColumn *column;
-        column = my_gtk_tree_view_get_column_with_sort_column_id (GTK_TREE_VIEW (proctree), 
COL_SECURITYCONTEXT);
+        column = gsm_tree_view_get_column_from_id (GSM_TREE_VIEW (proctree), COL_SECURITYCONTEXT);
         gtk_tree_view_column_set_visible (column, FALSE);
     }
 
     if (!cgroups_enabled()) {
         GtkTreeViewColumn *column;
 
-        column = my_gtk_tree_view_get_column_with_sort_column_id(GTK_TREE_VIEW(proctree), COL_CGROUP);
+        column = gsm_tree_view_get_column_from_id (GSM_TREE_VIEW(proctree), COL_CGROUP);
         gtk_tree_view_column_set_visible(column, FALSE);
     }
 
@@ -636,7 +581,7 @@ proctable_new (GsmApplication * const app)
         GtkTreeViewColumn *column;
 
         for (i = COL_UNIT; i <= COL_OWNER; i++) {
-            column = my_gtk_tree_view_get_column_with_sort_column_id(GTK_TREE_VIEW(proctree), i);
+            column = gsm_tree_view_get_column_from_id (GSM_TREE_VIEW(proctree), i);
             gtk_tree_view_column_set_visible(column, FALSE);
         }
     }
diff --git a/src/proctable.h b/src/proctable.h
index 9b0cc6c..8d80b1a 100644
--- a/src/proctable.h
+++ b/src/proctable.h
@@ -64,9 +64,6 @@ void            proctable_freeze (GsmApplication *app);
 void            proctable_thaw (GsmApplication *app);
 void            proctable_reset_timeout (GsmApplication *app);
 
-GSList*         proctable_get_columns_order(GtkTreeView *treeview);
-void            proctable_set_columns_order(GtkTreeView *treeview, GSList *order);
-
 char*           make_loadavg_string(void);
 
 void            get_process_memory_writable (ProcInfo *info);
diff --git a/src/settings-keys.h b/src/settings-keys.h
index 0b84144..2ef20cc 100644
--- a/src/settings-keys.h
+++ b/src/settings-keys.h
@@ -7,7 +7,7 @@
 #define GSM_SETTINGS_CHILD_OPEN_FILES       "openfilestree"
 #define GSM_SETTINGS_CHILD_DISKS            "disktreenew"
 #define GSM_SETTINGS_CHILD_PROCESSES        "proctree"
-#define GSM_SETTINGS_CHILD_MEMMAP           "memmaptree"
+#define GSM_SETTINGS_CHILD_MEMMAP           "memmapstree"
 
 #define GSM_SETTING_WINDOW_STATE            "window-state"
 #define GSM_SETTING_MAXIMIZED               "maximized"
diff --git a/src/treeview.c b/src/treeview.c
new file mode 100644
index 0000000..4d1fecc
--- /dev/null
+++ b/src/treeview.c
@@ -0,0 +1,241 @@
+/* -*- 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));
+
+    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_new ("ai", builder));
+
+        g_list_free (columns);
+    }
+}
+
+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, GdkEvent* event, gpointer data)
+{
+    GtkMenu *menu = GTK_MENU (data);
+
+    if (event->button.button == GDK_BUTTON_SECONDARY) {
+        gtk_menu_popup (menu, NULL, NULL,
+                        NULL,
+                        &(event->button),
+                        event->button.button,
+                        event->button.time);
+        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) {
+        GtkWidget *header_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;
+            GtkWidget *button;
+            GtkWidget *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)))
+                continue;
+
+            title = gtk_tree_view_column_get_title (col);
+
+            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_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), column_item);
+        }
+
+        gtk_widget_show_all (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));
+}
+
+void
+gsm_tree_view_append_and_bind_column (GsmTreeView *tree_view, GtkTreeViewColumn *column)
+{
+    GsmTreeViewPrivate *priv;
+    gchar *key;
+    gint column_id;
+
+    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);
+
+    column_id = gtk_tree_view_column_get_sort_column_id (column);
+
+    key = g_strdup_printf ("col-%d-width", column_id);
+    g_settings_bind (priv->settings, key, column, "fixed-width", G_SETTINGS_BIND_DEFAULT);
+    g_free (key);
+
+    key = g_strdup_printf ("col-%d-visible", column_id);
+    g_settings_bind (priv->settings, key, column, "visible", G_SETTINGS_BIND_DEFAULT);
+    g_free (key);
+}
+
+
+GtkWidget *
+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 GTK_WIDGET (self);
+}
diff --git a/src/treeview.h b/src/treeview.h
new file mode 100644
index 0000000..4ca9e5c
--- /dev/null
+++ b/src/treeview.h
@@ -0,0 +1,43 @@
+/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+#ifndef _GSM_TREE_VIEW_H_
+#define _GSM_TREE_VIEW_H_
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GSM_TYPE_TREE_VIEW (gsm_tree_view_get_type ())
+#define GSM_TREE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSM_TYPE_TREE_VIEW, GsmTreeView))
+#define GSM_TREE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSM_TYPE_TREE_VIEW, GsmTreeViewClass))
+#define GSM_IS_TREE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSM_TYPE_TREE_VIEW))
+#define GSM_IS_TREE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSM_TYPE_TREE_VIEW))
+#define GSM_TREE_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSM_TYPE_TREE_VIEW, 
GsmTreeViewClass))
+
+typedef struct _GsmTreeView      GsmTreeView;
+typedef struct _GsmTreeViewClass GsmTreeViewClass;
+
+struct _GsmTreeView
+{
+    GtkTreeView parent_instance;
+};
+
+struct _GsmTreeViewClass
+{
+    GtkTreeViewClass parent_class;
+};
+
+GType               gsm_tree_view_get_type               (void) G_GNUC_CONST;
+GtkWidget         * gsm_tree_view_new                    (GSettings *settings,
+                                                          gboolean   store_column_order);
+void                gsm_tree_view_save_state             (GsmTreeView *tree_view);
+void                gsm_tree_view_load_state             (GsmTreeView *tree_view);
+GtkTreeViewColumn * gsm_tree_view_get_column_from_id     (GsmTreeView *tree_view,
+                                                          gint         sort_id);
+void                gsm_tree_view_add_excluded_column    (GsmTreeView *tree_view,
+                                                          gint         column_id);
+void                gsm_tree_view_append_and_bind_column (GsmTreeView       *tree_view,
+                                                          GtkTreeViewColumn *column);
+
+G_END_DECLS
+
+#endif /* _GSM_TREE_VIEW_H_ */
diff --git a/src/util.cpp b/src/util.cpp
index b03dcf6..d052a96 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -647,16 +647,3 @@ namespace procman
     }
 
 }
-
-void
-bind_column_to_gsetting (GSettings *settings, GtkTreeViewColumn *column)
-{
-    char *key;
-    gint column_id = gtk_tree_view_column_get_sort_column_id(column);
-    key = g_strdup_printf ("col-%d-width", column_id);
-    g_settings_bind (settings, key, column, "fixed-width", G_SETTINGS_BIND_DEFAULT);
-    g_free (key);
-    key = g_strdup_printf ("col-%d-visible", column_id);
-    g_settings_bind (settings, key, column, "visible", G_SETTINGS_BIND_DEFAULT);
-    g_free (key);
-}
diff --git a/src/util.h b/src/util.h
index d97aaca..6dda021 100644
--- a/src/util.h
+++ b/src/util.h
@@ -127,7 +127,4 @@ namespace procman
     std::string format_network_rate(guint64 rate, guint64 max_rate = 0);
 }
 
-void bind_column_to_gsetting (GSettings *settings, GtkTreeViewColumn *column);
-
-
 #endif /* _GSM_UTIL_H_ */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]