[gtk+/parasite2: 3/38] parasite: Display child properties too



commit cd1dc22901105c9f9293a48ee2c95bb3ff322e37
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat May 3 15:25:43 2014 -0400

    parasite: Display child properties too

 modules/other/parasite/parasite.h               |    1 +
 modules/other/parasite/prop-list.c              |   73 ++++++++++++++---
 modules/other/parasite/prop-list.h              |    3 +-
 modules/other/parasite/property-cell-renderer.c |   99 ++++++++++++++++++-----
 modules/other/parasite/window.c                 |   28 +++++--
 5 files changed, 161 insertions(+), 43 deletions(-)
---
diff --git a/modules/other/parasite/parasite.h b/modules/other/parasite/parasite.h
index 8ff6d09..107dca1 100644
--- a/modules/other/parasite/parasite.h
+++ b/modules/other/parasite/parasite.h
@@ -36,6 +36,7 @@ typedef struct
     GtkWidget *window;
     GtkWidget *widget_tree;
     GtkWidget *prop_list;
+    GtkWidget *child_prop_list;
     GtkWidget *python_shell;
     GtkWidget *button_path;
     GtkWidget *classes_list;
diff --git a/modules/other/parasite/prop-list.c b/modules/other/parasite/prop-list.c
index 90d395e..8cedde3 100644
--- a/modules/other/parasite/prop-list.c
+++ b/modules/other/parasite/prop-list.c
@@ -39,7 +39,8 @@ enum
 enum
 {
   PROP_0,
-  PROP_WIDGET_TREE
+  PROP_WIDGET_TREE,
+  PROP_CHILD_PROPERTIES
 };
 
 struct _ParasitePropListPrivate
@@ -50,6 +51,8 @@ struct _ParasitePropListPrivate
   GList *signal_cnxs;
   GtkWidget *widget_tree;
   GtkTreeViewColumn *property_column;
+  GtkTreeViewColumn *value_column;
+  gboolean child_properties;
 };
 
 G_DEFINE_TYPE_WITH_PRIVATE (ParasitePropList, parasite_proplist, GTK_TYPE_TREE_VIEW)
@@ -163,19 +166,20 @@ constructed (GObject *object)
   g_object_set (renderer,
                 "scale", TREE_TEXT_SCALE,
                 "editable", TRUE,
+                "is-child-property", pl->priv->child_properties,
                 NULL);
-  column = gtk_tree_view_column_new_with_attributes ("Value", renderer,
-                                                     "text", COLUMN_VALUE,
-                                                     "object", COLUMN_OBJECT,
-                                                     "name", COLUMN_NAME,
-                                                      NULL);
-  gtk_tree_view_append_column (GTK_TREE_VIEW (pl), column);
-  gtk_tree_view_column_set_resizable (column, TRUE);
+  pl->priv->value_column = gtk_tree_view_column_new_with_attributes ("Value", renderer,
+                                                                     "text", COLUMN_VALUE,
+                                                                     "object", COLUMN_OBJECT,
+                                                                     "name", COLUMN_NAME,
+                                                                     NULL);
+  gtk_tree_view_append_column (GTK_TREE_VIEW (pl), pl->priv->value_column);
+  gtk_tree_view_column_set_resizable (pl->priv->value_column, TRUE);
 
   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (pl->priv->model),
                                         COLUMN_NAME,
                                         GTK_SORT_ASCENDING);
- gtk_tree_view_column_set_cell_data_func (column,
+ gtk_tree_view_column_set_cell_data_func (pl->priv->value_column,
                                           renderer,
                                           (GtkTreeCellDataFunc) draw_columns,
                                           pl,
@@ -212,6 +216,10 @@ get_property (GObject    *object,
         g_value_take_object (value, pl->priv->widget_tree);
         break;
 
+      case PROP_CHILD_PROPERTIES:
+        g_value_set_boolean (value, pl->priv->child_properties);
+        break;
+
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
         break;
@@ -232,6 +240,10 @@ set_property (GObject      *object,
         pl->priv->widget_tree = g_value_get_object (value);
         break;
 
+      case PROP_CHILD_PROPERTIES:
+        pl->priv->child_properties = g_value_get_boolean (value);
+        break;
+
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
         break;
@@ -254,6 +266,9 @@ parasite_proplist_class_init (ParasitePropListClass *klass)
                                                          "Widget tree",
                                                          GTK_TYPE_WIDGET,
                                                          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+  g_object_class_install_property (object_class, PROP_CHILD_PROPERTIES,
+      g_param_spec_boolean ("child-properties", "Child properties", "Child properties",
+                            FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 }
 
 static void
@@ -265,7 +280,17 @@ parasite_prop_list_update_prop (ParasitePropList *pl,
   char *value;
 
   g_value_init(&gvalue, prop->value_type);
-  g_object_get_property (pl->priv->object, prop->name, &gvalue);
+  if (pl->priv->child_properties)
+    {
+      GtkWidget *parent;
+
+      parent = gtk_widget_get_parent (GTK_WIDGET (pl->priv->object));
+      gtk_container_child_get_property (GTK_CONTAINER (parent),
+                                        GTK_WIDGET (pl->priv->object),
+                                        prop->name, &gvalue);
+    }
+  else
+    g_object_get_property (pl->priv->object, prop->name, &gvalue);
 
   if (G_VALUE_HOLDS_ENUM (&gvalue))
     {
@@ -281,7 +306,7 @@ parasite_prop_list_update_prop (ParasitePropList *pl,
 
   gtk_list_store_set (pl->priv->model, iter,
                       COLUMN_NAME, prop->name,
-                      COLUMN_VALUE, value,
+                      COLUMN_VALUE, value ? value : g_strdup (""),
                       COLUMN_DEFINED_AT, g_type_name (prop->owner_type),
                       COLUMN_OBJECT, pl->priv->object,
                       COLUMN_TOOLTIP, g_param_spec_get_blurb (prop),
@@ -304,10 +329,12 @@ parasite_proplist_prop_changed_cb (GObject *pspec,
 }
 
 GtkWidget *
-parasite_proplist_new (GtkWidget *widget_tree)
+parasite_proplist_new (GtkWidget *widget_tree,
+                       gboolean   child_properties)
 {
     return g_object_new (PARASITE_TYPE_PROPLIST,
                          "widget-tree", widget_tree,
+                         "child-properties", child_properties,
                          NULL);
 }
 
@@ -336,7 +363,22 @@ parasite_proplist_set_object (ParasitePropList* pl, GObject *object)
   g_hash_table_remove_all (pl->priv->prop_iters);
   gtk_list_store_clear (pl->priv->model);
 
-  props = g_object_class_list_properties (G_OBJECT_GET_CLASS (object), &num_properties);
+  if (pl->priv->child_properties)
+    {
+      GtkWidget *parent;
+
+      if (!GTK_IS_WIDGET (object))
+        return;
+
+      parent = gtk_widget_get_parent (GTK_WIDGET (object));
+      if (!parent)
+        return;
+
+      props = gtk_container_class_list_child_properties (G_OBJECT_GET_CLASS (parent), &num_properties);
+    }
+  else
+    props = g_object_class_list_properties (G_OBJECT_GET_CLASS (object), &num_properties);
+
   for (i = 0; i < num_properties; i++)
     {
       GParamSpec *prop = props[i];
@@ -351,7 +393,10 @@ parasite_proplist_set_object (ParasitePropList* pl, GObject *object)
       g_hash_table_insert (pl->priv->prop_iters, (gpointer) prop->name, gtk_tree_iter_copy (&iter));
 
       /* Listen for updates */
-      signal_name = g_strdup_printf ("notify::%s", prop->name);
+      if (pl->priv->child_properties)
+        signal_name = g_strdup_printf ("child-notify::%s", prop->name);
+      else
+        signal_name = g_strdup_printf ("notify::%s", prop->name);
 
       pl->priv->signal_cnxs =
             g_list_prepend (pl->priv->signal_cnxs, GINT_TO_POINTER(
diff --git a/modules/other/parasite/prop-list.h b/modules/other/parasite/prop-list.h
index d5eed22..efc75b5 100644
--- a/modules/other/parasite/prop-list.h
+++ b/modules/other/parasite/prop-list.h
@@ -49,7 +49,8 @@ typedef struct _ParasitePropListClass {
 G_BEGIN_DECLS
 
 GType      parasite_proplist_get_type   (void);
-GtkWidget *parasite_proplist_new        (GtkWidget *widget_tree);
+GtkWidget *parasite_proplist_new        (GtkWidget *widget_tree,
+                                         gboolean   child_properties);
 void       parasite_proplist_set_object (ParasitePropList *proplist,
                                          GObject          *object);
 
diff --git a/modules/other/parasite/property-cell-renderer.c b/modules/other/parasite/property-cell-renderer.c
index 16a7d0f..1e0f4e9 100644
--- a/modules/other/parasite/property-cell-renderer.c
+++ b/modules/other/parasite/property-cell-renderer.c
@@ -28,13 +28,15 @@ struct _ParasitePropertyCellRendererPrivate
 {
   GObject *object;
   char *name;
+  gboolean is_child_property;
 };
 
 enum
 {
   PROP_0,
   PROP_OBJECT,
-  PROP_NAME
+  PROP_NAME,
+  PROP_IS_CHILD_PROPERTY
 };
 
 G_DEFINE_TYPE_WITH_PRIVATE (ParasitePropertyCellRenderer, parasite_property_cell_renderer, 
GTK_TYPE_CELL_RENDERER_TEXT);
@@ -63,6 +65,10 @@ get_property (GObject *object,
         g_value_set_string(value, r->priv->name);
         break;
 
+      case PROP_IS_CHILD_PROPERTY:
+        g_value_set_boolean (value, r->priv->is_child_property);
+        break;
+
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
         break;
@@ -88,24 +94,81 @@ set_property (GObject *object,
         r->priv->name = g_value_dup_string (value);
         break;
 
+      case PROP_IS_CHILD_PROPERTY:
+        r->priv->is_child_property = g_value_get_boolean (value);
+        g_object_notify (object, "is-child-property");
+        break;
+
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
         break;
     }
 }
 
+static GParamSpec *
+find_property (GtkCellRenderer *renderer)
+{
+  ParasitePropertyCellRenderer *r = PARASITE_PROPERTY_CELL_RENDERER (renderer);
+
+  if (r->priv->is_child_property)
+    {
+      GtkWidget *parent;
+
+      parent = gtk_widget_get_parent (GTK_WIDGET (r->priv->object));
+
+      return gtk_container_class_find_child_property (G_OBJECT_GET_CLASS (parent), r->priv->name);
+    }
+
+  return g_object_class_find_property (G_OBJECT_GET_CLASS (r->priv->object), r->priv->name);
+}
+
+static void
+get_value (GtkCellRenderer *renderer,
+           GValue          *gvalue)
+{
+  ParasitePropertyCellRenderer *r = PARASITE_PROPERTY_CELL_RENDERER (renderer);
+
+  if (r->priv->is_child_property)
+    {
+      GtkWidget *widget;
+      GtkWidget *parent;
+
+      widget = GTK_WIDGET (r->priv->object);
+      parent = gtk_widget_get_parent (widget);
+
+      gtk_container_child_get_property (GTK_CONTAINER (parent), widget, r->priv->name, gvalue);
+    }
+  else
+    g_object_get_property (r->priv->object, r->priv->name, gvalue);
+}
+
+static void
+set_value (GtkCellRenderer *renderer,
+           GValue          *gvalue)
+{
+  ParasitePropertyCellRenderer *r = PARASITE_PROPERTY_CELL_RENDERER (renderer);
+
+  if (r->priv->is_child_property)
+    {
+      GtkWidget *widget;
+      GtkWidget *parent;
+
+      widget = GTK_WIDGET (r->priv->object);
+      parent = gtk_widget_get_parent (widget);
+
+      gtk_container_child_set_property (GTK_CONTAINER (parent), widget, r->priv->name, gvalue);
+    }
+  else
+    g_object_set_property (r->priv->object, r->priv->name, gvalue);
+}
+
 static void
 stop_editing(GtkCellEditable *editable, GtkCellRenderer *renderer)
 {
-    GObject *object;
-    const char *name;
     GValue gvalue = {0};
     GParamSpec *prop;
 
-    object = g_object_get_data(G_OBJECT(editable), "_prop_object");
-    name   = g_object_get_data(G_OBJECT(editable), "_prop_name");
-
-    prop = g_object_class_find_property(G_OBJECT_GET_CLASS(object), name);
+    prop = find_property (renderer);
     g_value_init(&gvalue, prop->value_type);
 
     if (GTK_IS_ENTRY(editable))
@@ -172,7 +235,7 @@ stop_editing(GtkCellEditable *editable, GtkCellRenderer *renderer)
         }
     }
 
-    g_object_set_property(object, name, &gvalue);
+    set_value (renderer, &gvalue);
     g_value_unset(&gvalue);
 }
 
@@ -187,19 +250,15 @@ start_editing (GtkCellRenderer *renderer,
 {
     PangoFontDescription *font_desc;
     GtkCellEditable *editable = NULL;
-    GObject *object;
-    const char *name;
     GValue gvalue = {0};
     GParamSpec *prop;
+    ParasitePropertyCellRenderer *r = PARASITE_PROPERTY_CELL_RENDERER (renderer);
 
-    g_object_get(renderer,
-                 "object", &object,
-                 "name", &name,
-                 NULL);
+    prop = find_property (renderer);
 
-    prop = g_object_class_find_property(G_OBJECT_GET_CLASS(object), name);
     g_value_init(&gvalue, prop->value_type);
-    g_object_get_property(object, name, &gvalue);
+
+    get_value (renderer, &gvalue);
 
     if (G_VALUE_HOLDS_OBJECT (&gvalue))
       {
@@ -214,7 +273,7 @@ start_editing (GtkCellRenderer *renderer,
               {
                 parasite_widget_tree_select_object (widget_tree, prop_object);
               }
-            else if (parasite_widget_tree_find_object (widget_tree, object, &iter))
+            else if (parasite_widget_tree_find_object (widget_tree, r->priv->object, &iter))
               {
                 parasite_widget_tree_append_object (widget_tree, prop_object, &iter);
                 parasite_widget_tree_select_object (widget_tree, prop_object);
@@ -366,8 +425,6 @@ start_editing (GtkCellRenderer *renderer,
     pango_font_description_free(font_desc);
 
     g_signal_connect(editable, "editing_done", G_CALLBACK (stop_editing), renderer);
-    g_object_set_data_full (G_OBJECT (editable), "_prop_name", g_strdup (name), g_free);
-    g_object_set_data (G_OBJECT (editable), "_prop_object", object);
 
     return editable;
 }
@@ -398,6 +455,10 @@ parasite_property_cell_renderer_class_init (ParasitePropertyCellRendererClass *k
                              "The property name",
                              NULL,
                              G_PARAM_READWRITE));
+
+  g_object_class_install_property (object_class, PROP_IS_CHILD_PROPERTY,
+      g_param_spec_boolean ("is-child-property", "Child property", "Child property",
+                            FALSE, G_PARAM_READWRITE));
 }
 
 GtkCellRenderer *
diff --git a/modules/other/parasite/window.c b/modules/other/parasite/window.c
index 4b12b18..fd7dc87 100644
--- a/modules/other/parasite/window.c
+++ b/modules/other/parasite/window.c
@@ -42,10 +42,9 @@ on_widget_tree_selection_changed (ParasiteWidgetTree *widget_tree,
 
   if (selected != NULL)
     {
-      parasite_proplist_set_object (PARASITE_PROPLIST (parasite->prop_list),
-                                    selected);
-      parasite_objecthierarchy_set_object (PARASITE_OBJECTHIERARCHY (parasite->oh),
-                                           selected);
+      parasite_proplist_set_object (PARASITE_PROPLIST (parasite->prop_list), selected);
+      parasite_proplist_set_object (PARASITE_PROPLIST (parasite->child_prop_list), selected);
+      parasite_objecthierarchy_set_object (PARASITE_OBJECTHIERARCHY (parasite->oh), selected);
 
       if (GTK_IS_WIDGET (selected))
         {
@@ -135,9 +134,11 @@ create_widget_list_pane(ParasiteWindow *parasite)
 }
 
 static GtkWidget *
-create_prop_list_pane(ParasiteWindow *parasite)
+create_prop_list_pane (ParasiteWindow *parasite,
+                       gboolean        child_properties)
 {
     GtkWidget *swin;
+    GtkWidget *pl;
 
     swin = g_object_new (GTK_TYPE_SCROLLED_WINDOW,
                         "hscrollbar-policy", GTK_POLICY_AUTOMATIC,
@@ -146,8 +147,13 @@ create_prop_list_pane(ParasiteWindow *parasite)
                         "width-request", 250,
                         NULL);
 
-    parasite->prop_list = parasite_proplist_new (parasite->widget_tree);
-    gtk_container_add(GTK_CONTAINER(swin), parasite->prop_list);
+    pl = parasite_proplist_new (parasite->widget_tree, child_properties);
+    gtk_container_add (GTK_CONTAINER (swin), pl);
+
+    if (child_properties)
+      parasite->child_prop_list = pl;
+    else
+      parasite->prop_list = pl;
 
     return swin;
 }
@@ -273,8 +279,12 @@ gtkparasite_window_create()
                        "show-border", FALSE,
                        NULL);
     gtk_notebook_append_page (GTK_NOTEBOOK (nb),
-                              create_prop_list_pane (window),
-                              gtk_label_new ("GObject Properties"));
+                              create_prop_list_pane (window, FALSE),
+                              gtk_label_new ("Properties"));
+
+    gtk_notebook_append_page (GTK_NOTEBOOK (nb),
+                              create_prop_list_pane (window, TRUE),
+                              gtk_label_new ("Child Properties"));
 
     window->oh = parasite_objecthierarchy_new ();
     gtk_notebook_append_page (GTK_NOTEBOOK (nb),


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