[gtk/inspector-menus: 2/2] inspector: Stop using a treeview for menus




commit ab7a04d89f0e65981c32269ea67dca592e638339
Author: Matthias Clasen <mclasen redhat com>
Date:   Tue Oct 4 22:46:53 2022 -0400

    inspector: Stop using a treeview for menus
    
    Replace this with a GtkColumnView.

 gtk/inspector/menu.c  | 274 +++++++++++++++++++++++++++++++++++++++++---------
 gtk/inspector/menu.ui |  44 ++------
 2 files changed, 235 insertions(+), 83 deletions(-)
---
diff --git a/gtk/inspector/menu.c b/gtk/inspector/menu.c
index ec7e6901e3..dc14fc5b66 100644
--- a/gtk/inspector/menu.c
+++ b/gtk/inspector/menu.c
@@ -20,48 +20,227 @@
 
 #include "menu.h"
 
-#include "gtktreestore.h"
 #include "gtkwidgetprivate.h"
 #include "gtklabel.h"
 #include "gtkstack.h"
+#include "gtkcolumnview.h"
+#include "gtkcolumnviewcolumn.h"
+#include "gtktreelistmodel.h"
+#include "gtknoselection.h"
+#include "gtksignallistitemfactory.h"
+#include "gtktreeexpander.h"
+#include "gtklistitem.h"
 
 
-enum
+typedef struct _MenuItem MenuItem;
+
+G_DECLARE_FINAL_TYPE (MenuItem, menu_item, MENU, ITEM, GObject);
+
+struct _MenuItem
 {
-  COLUMN_TYPE,
-  COLUMN_LABEL,
-  COLUMN_ACTION,
-  COLUMN_TARGET,
-  COLUMN_ICON
+  GObject parent;
+
+  char *label;
+  char *action;
+  char *target;
+  char *icon;
+  GMenuModel *model;
 };
 
+G_DEFINE_TYPE (MenuItem, menu_item, G_TYPE_OBJECT);
+
+static void
+menu_item_init (MenuItem *self)
+{
+}
+
+static void
+menu_item_finalize (GObject *object)
+{
+  MenuItem *self = MENU_ITEM (object);
+
+  g_free (self->label);
+  g_free (self->action);
+  g_free (self->target);
+  g_free (self->icon);
+  g_clear_object (&self->model);
+
+  G_OBJECT_CLASS (menu_item_parent_class)->finalize (object);
+}
+
+static void
+menu_item_class_init (MenuItemClass *class)
+{
+  G_OBJECT_CLASS (class)->finalize = menu_item_finalize;
+}
+
+static MenuItem *
+menu_item_new (const char *label,
+               const char *action,
+               const char *target,
+               const char *icon,
+               GMenuModel *model)
+{
+  MenuItem *self;
+
+  self = g_object_new (menu_item_get_type (), NULL);
+  self->label = g_strdup (label);
+  self->action = g_strdup (action);
+  self->target = g_strdup (target);
+  self->icon = g_strdup (icon);
+  g_set_object (&self->model, model);
+
+  return self;
+}
+
 struct _GtkInspectorMenuPrivate
 {
-  GtkTreeStore *model;
+  GtkColumnView *view;
+  GtkTreeListModel *tree_model;
 };
 
 G_DEFINE_TYPE_WITH_PRIVATE (GtkInspectorMenu, gtk_inspector_menu, GTK_TYPE_BOX)
 
+static GListModel * create_model (gpointer item, gpointer user_data);
+
+static void
+setup_label (GtkListItemFactory *factory,
+             GtkListItem        *item)
+{
+  GtkWidget *expander;
+  GtkWidget *label;
+
+  expander = gtk_tree_expander_new ();
+  label = gtk_label_new (NULL);
+  gtk_label_set_xalign (GTK_LABEL (label), 0.);
+  gtk_tree_expander_set_child (GTK_TREE_EXPANDER (expander), label);
+
+  gtk_list_item_set_child (item, expander);
+}
+
+static void
+bind_label (GtkListItemFactory *factory,
+            GtkListItem        *item)
+{
+  GtkWidget *expander;
+  GtkWidget *label;
+  GtkTreeListRow *row;
+  MenuItem *menu_item;
+
+  row = gtk_list_item_get_item (item);
+  menu_item = gtk_tree_list_row_get_item (row);
+
+  expander = gtk_list_item_get_child (item);
+  gtk_tree_expander_set_list_row (GTK_TREE_EXPANDER (expander), row);
+
+  label = gtk_tree_expander_get_child (GTK_TREE_EXPANDER (expander));
+  gtk_label_set_label (GTK_LABEL (label), menu_item->label);
+}
+
+static void
+setup_action (GtkListItemFactory *factory,
+              GtkListItem        *item)
+{
+  GtkWidget *label;
+
+  label = gtk_label_new (NULL);
+  gtk_label_set_xalign (GTK_LABEL (label), 0.);
+
+  gtk_list_item_set_child (item, label);
+}
+
+static void
+bind_action (GtkListItemFactory *factory,
+             GtkListItem        *item)
+{
+  GtkWidget *label;
+  GtkTreeListRow *row;
+  MenuItem *menu_item;
+
+  row = gtk_list_item_get_item (item);
+  menu_item = gtk_tree_list_row_get_item (row);
+
+  label = gtk_list_item_get_child (item);
+  gtk_label_set_label (GTK_LABEL (label), menu_item->action);
+}
+
+static void
+setup_target (GtkListItemFactory *factory,
+              GtkListItem        *item)
+{
+  GtkWidget *label;
+
+  label = gtk_label_new (NULL);
+  gtk_label_set_xalign (GTK_LABEL (label), 0.);
+
+  gtk_list_item_set_child (item, label);
+}
+
+static void
+bind_target (GtkListItemFactory *factory,
+             GtkListItem        *item)
+{
+  GtkWidget *label;
+  GtkTreeListRow *row;
+  MenuItem *menu_item;
+
+  row = gtk_list_item_get_item (item);
+  menu_item = gtk_tree_list_row_get_item (row);
+
+  label = gtk_list_item_get_child (item);
+  gtk_label_set_label (GTK_LABEL (label), menu_item->target);
+}
+
 static void
 gtk_inspector_menu_init (GtkInspectorMenu *sl)
 {
+  GtkTreeListModel *store;
+  GtkColumnViewColumn *column;
+  GtkListItemFactory *factory;
+
   sl->priv = gtk_inspector_menu_get_instance_private (sl);
   gtk_widget_init_template (GTK_WIDGET (sl));
-}
 
-static void add_menu (GtkInspectorMenu *sl,
-                      GtkStackPage     *page,
-                      GMenuModel       *menu,
-                      GtkTreeIter      *parent);
+  store = gtk_tree_list_model_new (G_LIST_MODEL (g_list_store_new (menu_item_get_type ())),
+                                   FALSE, FALSE,
+                                   create_model,
+                                   sl, NULL);
+
+  gtk_column_view_set_model (sl->priv->view, GTK_SELECTION_MODEL (gtk_no_selection_new (G_LIST_MODEL 
(store))));
+
+  column = g_list_model_get_item (gtk_column_view_get_columns (sl->priv->view), 0);
+  factory = gtk_signal_list_item_factory_new ();
+  g_signal_connect (factory, "setup", G_CALLBACK (setup_label), NULL);
+  g_signal_connect (factory, "bind", G_CALLBACK (bind_label), NULL);
+  gtk_column_view_column_set_factory (column, factory);
+  g_object_unref (factory);
+  g_object_unref (column);
+
+  column = g_list_model_get_item (gtk_column_view_get_columns (sl->priv->view), 1);
+  factory = gtk_signal_list_item_factory_new ();
+  g_signal_connect (factory, "setup", G_CALLBACK (setup_action), NULL);
+  g_signal_connect (factory, "bind", G_CALLBACK (bind_action), NULL);
+  gtk_column_view_column_set_factory (column, factory);
+  g_object_unref (factory);
+  g_object_unref (column);
+
+  column = g_list_model_get_item (gtk_column_view_get_columns (sl->priv->view), 2);
+  factory = gtk_signal_list_item_factory_new ();
+  g_signal_connect (factory, "setup", G_CALLBACK (setup_target), NULL);
+  g_signal_connect (factory, "bind", G_CALLBACK (bind_target), NULL);
+  gtk_column_view_column_set_factory (column, factory);
+  g_object_unref (factory);
+  g_object_unref (column);
+
+  sl->priv->tree_model = store;
+}
 
 static void
 add_item (GtkInspectorMenu *sl,
-          GtkStackPage     *page,
           GMenuModel       *menu,
           int               idx,
-          GtkTreeIter      *parent)
+          GListStore       *store)
 {
-  GtkTreeIter iter;
   GVariant *value;
   char *label = NULL;
   char *action = NULL;
@@ -78,33 +257,18 @@ add_item (GtkInspectorMenu *sl,
       g_variant_unref (value);
     }
 
-  gtk_tree_store_append (sl->priv->model, &iter, parent);
-  gtk_tree_store_set (sl->priv->model, &iter,
-                      COLUMN_TYPE, "item",
-                      COLUMN_LABEL, label,
-                      COLUMN_ACTION, action,
-                      COLUMN_TARGET, target,
-                      COLUMN_ICON, icon,
-                      -1);
-
   model = g_menu_model_get_item_link (menu, idx, G_MENU_LINK_SECTION);
   if (model)
     {
       if (label == NULL)
-        gtk_tree_store_set (sl->priv->model, &iter,
-                            COLUMN_LABEL, _("Unnamed section"),
-                            -1);
-      add_menu (sl, page, model, &iter);
-      g_object_unref (model);
+        label = g_strdup (_("Unnamed section"));
     }
+  else
+    model = g_menu_model_get_item_link (menu, idx, G_MENU_LINK_SUBMENU);
 
-  model = g_menu_model_get_item_link (menu, idx, G_MENU_LINK_SUBMENU);
-  if (model)
-    {
-      add_menu (sl, page, model, &iter);
-      g_object_unref (model);
-    }
+  g_list_store_append (store, menu_item_new (label, action, target, icon, model));
 
+  g_clear_object (&model);
   g_free (label);
   g_free (action);
   g_free (target);
@@ -113,18 +277,32 @@ add_item (GtkInspectorMenu *sl,
 
 static void
 add_menu (GtkInspectorMenu *sl,
-          GtkStackPage     *page,
           GMenuModel       *menu,
-          GtkTreeIter      *parent)
+          GListStore       *store)
 {
   int n_items;
   int i;
 
-  g_object_set (page, "visible", TRUE, NULL);
-
   n_items = g_menu_model_get_n_items (menu);
   for (i = 0; i < n_items; i++)
-    add_item (sl, page, menu, i, parent);
+    add_item (sl, menu, i, store);
+}
+
+static GListModel *
+create_model (gpointer item,
+              gpointer user_data)
+{
+  MenuItem *self = item;
+  GtkInspectorMenu *sl = user_data;
+  GListStore *store;
+
+  if (self->model == NULL)
+    return NULL;
+
+  store = g_list_store_new (menu_item_get_type ());
+  add_menu (sl, self->model, store);
+
+  return G_LIST_MODEL (store);
 }
 
 void
@@ -133,15 +311,21 @@ gtk_inspector_menu_set_object (GtkInspectorMenu *sl,
 {
   GtkWidget *stack;
   GtkStackPage *page;
+  GListStore *store;
 
   stack = gtk_widget_get_parent (GTK_WIDGET (sl));
   page = gtk_stack_get_page (GTK_STACK (stack), GTK_WIDGET (sl));
 
   g_object_set (page, "visible", FALSE, NULL);
-  gtk_tree_store_clear (sl->priv->model);
-  
+
+  store = G_LIST_STORE (gtk_tree_list_model_get_model (sl->priv->tree_model));
+  g_list_store_remove_all (store);
+
   if (G_IS_MENU_MODEL (object))
-    add_menu (sl, page, G_MENU_MODEL (object), NULL);
+    {
+      g_object_set (page, "visible", TRUE, NULL);
+      add_menu (sl, G_MENU_MODEL (object), store);
+    }
 }
 
 static void
@@ -150,7 +334,7 @@ gtk_inspector_menu_class_init (GtkInspectorMenuClass *klass)
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
 
   gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/libgtk/inspector/menu.ui");
-  gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMenu, model);
+  gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMenu, view);
 }
 
 // vim: set et sw=2 ts=2:
diff --git a/gtk/inspector/menu.ui b/gtk/inspector/menu.ui
index 2546256e84..4820f4f718 100644
--- a/gtk/inspector/menu.ui
+++ b/gtk/inspector/menu.ui
@@ -16,58 +16,26 @@
         <property name="vexpand">1</property>
         <property name="vscrollbar-policy">always</property>
         <child>
-          <object class="GtkTreeView">
-            <property name="model">model</property>
+          <object class="GtkColumnView" id="view">
             <child>
-              <object class="GtkTreeViewColumn">
+              <object class="GtkColumnViewColumn">
                 <property name="title" translatable="yes">Label</property>
-                <child>
-                  <object class="GtkCellRendererText">
-                    <property name="scale">0.8</property>
-                  </object>
-                  <attributes>
-                    <attribute name="text">1</attribute>
-                  </attributes>
-                </child>
               </object>
             </child>
             <child>
-              <object class="GtkTreeViewColumn">
+              <object class="GtkColumnViewColumn">
                 <property name="title" translatable="yes">Action</property>
-                <child>
-                  <object class="GtkCellRendererText">
-                    <property name="scale">0.8</property>
-                  </object>
-                  <attributes>
-                    <attribute name="text">2</attribute>
-                  </attributes>
-                </child>
               </object>
             </child>
             <child>
-              <object class="GtkTreeViewColumn">
+              <object class="GtkColumnViewColumn">
                 <property name="title" translatable="yes">Target</property>
-                <child>
-                  <object class="GtkCellRendererText">
-                    <property name="scale">0.8</property>
-                  </object>
-                  <attributes>
-                    <attribute name="text">3</attribute>
-                  </attributes>
-                </child>
               </object>
             </child>
             <child>
-              <object class="GtkTreeViewColumn">
+              <object class="GtkColumnViewColumn">
                 <property name="title" translatable="yes">Icon</property>
-                <child>
-                  <object class="GtkCellRendererText">
-                    <property name="scale">0.8</property>
-                  </object>
-                  <attributes>
-                    <attribute name="text">4</attribute>
-                  </attributes>
-                </child>
+                <property name="expand">1</property>
               </object>
             </child>
           </object>


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