[gtk+] inspector: Improve actions tab



commit fa80bb23249c2fb6da2a1a16c84a1c884cab1494
Author: Matthias Clasen <mclasen redhat com>
Date:   Thu May 15 22:36:48 2014 -0400

    inspector: Improve actions tab
    
    React to action group changes, and allow changing action states.

 gtk/inspector/actions.c  |  198 +++++++++++++++++++++++++++++++++++++++-------
 gtk/inspector/actions.ui |    4 +-
 2 files changed, 172 insertions(+), 30 deletions(-)
---
diff --git a/gtk/inspector/actions.c b/gtk/inspector/actions.c
index 2adca38..ab83594 100644
--- a/gtk/inspector/actions.c
+++ b/gtk/inspector/actions.c
@@ -26,13 +26,16 @@ enum
   COLUMN_NAME,
   COLUMN_ENABLED,
   COLUMN_PARAMETER,
-  COLUMN_STATE
+  COLUMN_STATE,
+  COLUMN_GROUP
 };
 
 struct _GtkInspectorActionsPrivate
 {
   GtkListStore *model;
   GtkWidget *prefix_label;
+  GHashTable *groups;
+  GHashTable *iters;
 };
 
 G_DEFINE_TYPE_WITH_PRIVATE (GtkInspectorActions, gtk_inspector_actions, GTK_TYPE_BOX)
@@ -41,58 +44,167 @@ static void
 gtk_inspector_actions_init (GtkInspectorActions *sl)
 {
   sl->priv = gtk_inspector_actions_get_instance_private (sl);
+  sl->priv->iters = g_hash_table_new_full (g_str_hash,
+                                           g_str_equal,
+                                           g_free,
+                                           (GDestroyNotify) gtk_tree_iter_free);
+  sl->priv->groups = g_hash_table_new_full (g_direct_hash,
+                                            g_direct_equal,
+                                            NULL,
+                                            g_free);
   gtk_widget_init_template (GTK_WIDGET (sl));
 }
 
 static void
-add_actions (GtkInspectorActions *sl,
-             const gchar         *prefix,
-             GActionGroup        *group)
+add_action (GtkInspectorActions *sl,
+            GActionGroup        *group,
+            const gchar         *prefix,
+            const gchar         *name)
 {
   GtkTreeIter iter;
-  gint i;
-  gchar **names;
   gboolean enabled;
   const gchar *parameter;
   GVariant *state;
   gchar *state_string;
 
+  enabled = g_action_group_get_action_enabled (group, name);
+  parameter = (const gchar *)g_action_group_get_action_parameter_type (group, name);
+  state = g_action_group_get_action_state (group, name);
+  if (state)
+    state_string = g_variant_print (state, FALSE);
+  else
+    state_string = g_strdup ("");
+  gtk_list_store_append (sl->priv->model, &iter);
+  gtk_list_store_set (sl->priv->model, &iter,
+                      COLUMN_PREFIX, prefix,
+                      COLUMN_NAME, name,
+                      COLUMN_ENABLED, enabled,
+                      COLUMN_PARAMETER, parameter,
+                      COLUMN_STATE, state_string,
+                      COLUMN_GROUP, group,
+                      -1);
+  g_hash_table_insert (sl->priv->iters,
+                       g_strconcat (prefix, ".", name, NULL),
+                       gtk_tree_iter_copy (&iter));
+  g_free (state_string);
+}
+
+static void
+action_added_cb (GActionGroup        *group,
+                 const gchar         *action_name,
+                 GtkInspectorActions *sl)
+{
+  const gchar *prefix;
+  prefix = g_hash_table_lookup (sl->priv->groups, group);
+  add_action (sl, group, prefix, action_name);
+}
+
+static void
+action_removed_cb (GActionGroup        *group,
+                   const gchar         *action_name,
+                   GtkInspectorActions *sl)
+{
+  const gchar *prefix;
+  gchar *key;
+  GtkTreeIter *iter;
+  prefix = g_hash_table_lookup (sl->priv->groups, group);
+  key = g_strconcat (prefix, ".", action_name, NULL);
+  iter = g_hash_table_lookup (sl->priv->iters, key);
+  gtk_list_store_remove (sl->priv->model, iter);
+  g_hash_table_remove (sl->priv->iters, key);
+  g_free (key);
+}
+
+static void
+action_enabled_changed_cb (GActionGroup        *group,
+                           const gchar         *action_name,
+                           gboolean             enabled,
+                           GtkInspectorActions *sl)
+{
+  const gchar *prefix;
+  gchar *key;
+  GtkTreeIter *iter;
+  prefix = g_hash_table_lookup (sl->priv->groups, group);
+  key = g_strconcat (prefix, ".", action_name, NULL);
+  iter = g_hash_table_lookup (sl->priv->iters, key);
+  gtk_list_store_set (sl->priv->model, iter,
+                      COLUMN_ENABLED, enabled,
+                      -1);
+  g_free (key);
+}
+
+static void
+action_state_changed_cb (GActionGroup        *group,
+                         const gchar         *action_name,
+                         GVariant            *state,
+                         GtkInspectorActions *sl)
+{
+  const gchar *prefix;
+  gchar *key;
+  GtkTreeIter *iter;
+  gchar *state_string;
+  prefix = g_hash_table_lookup (sl->priv->groups, group);
+  key = g_strconcat (prefix, ".", action_name, NULL);
+  iter = g_hash_table_lookup (sl->priv->iters, key);
+  if (state)
+    state_string = g_variant_print (state, FALSE);
+  else
+    state_string = g_strdup ("");
+  gtk_list_store_set (sl->priv->model, iter,
+                      COLUMN_STATE, state_string,
+                      -1);
+  g_free (state_string);
+  g_free (key);
+}
+
+static void
+add_group (GtkInspectorActions *sl,
+           GActionGroup        *group,
+           const gchar         *prefix)
+{
+  gint i;
+  gchar **names;
+
   gtk_widget_show (GTK_WIDGET (sl));
 
+  g_signal_connect (group, "action-added", G_CALLBACK (action_added_cb), sl);
+  g_signal_connect (group, "action-removed", G_CALLBACK (action_removed_cb), sl);
+  g_signal_connect (group, "action-enabled-changed", G_CALLBACK (action_enabled_changed_cb), sl);
+  g_signal_connect (group, "action-state-changed", G_CALLBACK (action_state_changed_cb), sl);
+  g_hash_table_insert (sl->priv->groups, group, g_strdup (prefix));
+
   names = g_action_group_list_actions (group);
   for (i = 0; names[i]; i++)
-    {
-      enabled = g_action_group_get_action_enabled (group, names[i]);
-      parameter = (const gchar *)g_action_group_get_action_parameter_type (group, names[i]);
-      state = g_action_group_get_action_state (group, names[i]);
-      if (state)
-        state_string = g_variant_print (state, FALSE);
-      else
-        state_string = g_strdup ("");
-      gtk_list_store_append (sl->priv->model, &iter);
-      gtk_list_store_set (sl->priv->model, &iter,
-                          COLUMN_PREFIX, prefix,
-                          COLUMN_NAME, names[i],
-                          COLUMN_ENABLED, enabled,
-                          COLUMN_PARAMETER, parameter,
-                          COLUMN_STATE, state_string,
-                          -1);
-      g_free (state_string);
-    }
+    add_action (sl, group, prefix, names[i]);
   g_strfreev (names);
 }
 
+static void
+disconnect_group (gpointer key, gpointer value, gpointer data)
+{
+  GActionGroup *group = key;
+  GtkInspectorActions *sl = data;
+
+  g_signal_handlers_disconnect_by_func (group, action_added_cb, sl);
+  g_signal_handlers_disconnect_by_func (group, action_removed_cb, sl);
+  g_signal_handlers_disconnect_by_func (group, action_enabled_changed_cb, sl);
+  g_signal_handlers_disconnect_by_func (group, action_state_changed_cb, sl);
+}
+
 void
 gtk_inspector_actions_set_object (GtkInspectorActions *sl,
                                   GObject             *object)
 {
-  gtk_list_store_clear (sl->priv->model);
   gtk_widget_hide (GTK_WIDGET (sl));
-
+  g_hash_table_foreach (sl->priv->groups, disconnect_group, sl);
+  g_hash_table_remove_all (sl->priv->groups);
+  g_hash_table_remove_all (sl->priv->iters);
+  gtk_list_store_clear (sl->priv->model);
+  
   if (GTK_IS_APPLICATION (object))
-    add_actions (sl, "app", G_ACTION_GROUP (object));
+    add_group (sl, G_ACTION_GROUP (object), "app");
   else if (GTK_IS_APPLICATION_WINDOW (object))
-    add_actions (sl, "win", G_ACTION_GROUP (object));
+    add_group (sl, G_ACTION_GROUP (object), "win");
   else if (GTK_IS_WIDGET (object))
     {
       gchar **prefixes;
@@ -105,7 +217,7 @@ gtk_inspector_actions_set_object (GtkInspectorActions *sl,
           for (i = 0; prefixes[i]; i++)
             {
               group = _gtk_widget_get_action_group (GTK_WIDGET (object), prefixes[i]);
-              add_actions (sl, prefixes[i], group);
+              add_group (sl, group, prefixes[i]);
             }
           g_free (prefixes);
         }
@@ -113,6 +225,33 @@ gtk_inspector_actions_set_object (GtkInspectorActions *sl,
 }
 
 static void
+state_edited (GtkCellRenderer     *cell,
+              const gchar         *path_string,
+              const gchar         *new_text,
+              GtkInspectorActions *sl)
+{
+  GtkTreePath *path;
+  GtkTreeIter iter;
+  GActionGroup *group;
+  gchar *name;
+  GError *error = NULL;
+  GVariant *state;
+
+  path = gtk_tree_path_new_from_string (path_string);
+  gtk_tree_model_get_iter (GTK_TREE_MODEL (sl->priv->model), &iter, path);
+  gtk_tree_path_free (path);
+
+  gtk_tree_model_get (GTK_TREE_MODEL (sl->priv->model), &iter,
+                      COLUMN_GROUP, &group,
+                      COLUMN_NAME, &name,
+                      -1);
+  state = g_variant_parse (NULL, new_text, NULL, NULL, &error);
+  if (state)
+    g_action_group_change_action_state (group, name, state);
+  g_free (name);
+}
+
+static void
 gtk_inspector_actions_class_init (GtkInspectorActionsClass *klass)
 {
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
@@ -120,6 +259,7 @@ gtk_inspector_actions_class_init (GtkInspectorActionsClass *klass)
   gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/inspector/actions.ui");
   gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorActions, model);
   gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorActions, prefix_label);
+  gtk_widget_class_bind_template_callback (widget_class, state_edited);
 }
 
 // vim: set et sw=2 ts=2:
diff --git a/gtk/inspector/actions.ui b/gtk/inspector/actions.ui
index cdc92b9..37776f0 100644
--- a/gtk/inspector/actions.ui
+++ b/gtk/inspector/actions.ui
@@ -7,7 +7,7 @@
       <column type="gboolean"/>
       <column type="gchararray"/>
       <column type="gchararray"/>
-      <column type="gchararray"/>
+      <column type="gpointer"/>
     </columns>
   </object>
   <template class="GtkInspectorActions" parent="GtkBox">
@@ -88,6 +88,8 @@
                 <child>
                   <object class="GtkCellRendererText">
                     <property name="scale">0.8</property>
+                    <property name="editable">True</property>
+                    <signal name="edited" handler="state_edited"/>
                   </object>
                   <attributes>
                     <attribute name="text">4</attribute>


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