[gtk+/parasite] parasite: Display child properties too



commit 34566964844d0a6bf1b910c28530e30cb0b20900
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat May 3 03:08:23 2014 -0400

    parasite: Display child properties too

 modules/other/parasite/parasite.h               |    1 +
 modules/other/parasite/prop-list.c              |  115 +++++++++++++++++++++--
 modules/other/parasite/prop-list.h              |    4 +-
 modules/other/parasite/property-cell-renderer.c |   99 ++++++++++++++++---
 modules/other/parasite/window.c                 |   26 ++++-
 5 files changed, 215 insertions(+), 30 deletions(-)
---
diff --git a/modules/other/parasite/parasite.h b/modules/other/parasite/parasite.h
index 3a24b9c..34ad6a7 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 *action_list;
   GtkWidget *python_shell;
 
diff --git a/modules/other/parasite/prop-list.c b/modules/other/parasite/prop-list.c
index 9fa4c10..5196ba3 100644
--- a/modules/other/parasite/prop-list.c
+++ b/modules/other/parasite/prop-list.c
@@ -33,6 +33,11 @@ enum
   NUM_COLUMNS
 };
 
+enum
+{
+  PROP_ZERO,
+  PROP_CHILD_PROPS
+};
 
 struct _ParasitePropListPrivate
 {
@@ -40,6 +45,9 @@ struct _ParasitePropListPrivate
   GtkListStore *model;
   GHashTable *prop_iters;
   GList *signal_cnxs;
+  gboolean child_props;
+  GtkTreeViewColumn *name_col;
+  GtkTreeViewColumn *value_col;
 };
 
 #define PARASITE_PROPLIST_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), PARASITE_TYPE_PROPLIST, 
ParasitePropListPrivate))
@@ -73,6 +81,7 @@ parasite_proplist_init (ParasitePropList      *proplist,
   gtk_tree_view_column_set_resizable (column, TRUE);
   gtk_tree_view_column_set_sort_order (column, GTK_SORT_ASCENDING);
   gtk_tree_view_column_set_sort_column_id (column, COLUMN_NAME);
+  proplist->priv->name_col = column;
 
   renderer = parasite_property_cell_renderer_new ();
   g_object_set (G_OBJECT (renderer), "scale", TREE_TEXT_SCALE, NULL);
@@ -84,12 +93,71 @@ parasite_proplist_init (ParasitePropList      *proplist,
                                                      NULL);
   gtk_tree_view_append_column (GTK_TREE_VIEW (proplist), column);
   gtk_tree_view_column_set_resizable (column, TRUE);
+  proplist->priv->value_col = column;
 
   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (proplist->priv->model),
                                         COLUMN_NAME,
                                         GTK_SORT_ASCENDING);
 }
 
+static void
+parasite_proplist_set_child_props (ParasitePropList *proplist,
+                                   gboolean          child_props)
+{
+  GList *cells;
+
+  proplist->priv->child_props = child_props;
+
+  if (child_props)
+    gtk_tree_view_column_set_title (proplist->priv->name_col, "Child Property");
+  else
+    gtk_tree_view_column_set_title (proplist->priv->name_col, "Property");
+
+  cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (proplist->priv->value_col));
+  g_object_set (cells->data, "is-child-property", child_props, NULL);
+  g_list_free (cells);
+}
+
+static void
+parasite_proplist_get_property (GObject    *object,
+                                guint       param_id,
+                                GValue     *value,
+                                GParamSpec *pspec)
+{
+  ParasitePropList *proplist = PARASITE_PROPLIST (object);
+
+  switch (param_id)
+    {
+    case PROP_CHILD_PROPS:
+      g_value_set_boolean (value, proplist->priv->child_props);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+      break;
+    }
+}
+
+static void
+parasite_proplist_set_property (GObject      *object,
+                                guint         param_id,
+                                const GValue *value,
+                                GParamSpec   *pspec)
+{
+  ParasitePropList *proplist = PARASITE_PROPLIST (object);
+
+  switch (param_id)
+    {
+    case PROP_CHILD_PROPS:
+      parasite_proplist_set_child_props (proplist, g_value_get_boolean (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+      break;
+    }
+}
+
 
 static void
 parasite_proplist_class_init (ParasitePropListClass *klass)
@@ -97,6 +165,12 @@ parasite_proplist_class_init (ParasitePropListClass *klass)
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
   parent_class = g_type_class_peek_parent (klass);
+  object_class->get_property = parasite_proplist_get_property;
+  object_class->set_property = parasite_proplist_set_property;
+
+  g_object_class_install_property (object_class, PROP_CHILD_PROPS,
+     g_param_spec_boolean ("child-properties", "Child properties", "Child properties",
+                           FALSE, G_PARAM_READWRITE));
 
   g_type_class_add_private (object_class, sizeof (ParasitePropListPrivate));
 }
@@ -110,8 +184,18 @@ parasite_prop_list_update_prop (ParasitePropList *proplist,
   gchar *value;
 
   g_value_init (&gvalue, prop->value_type);
-  g_object_get_property (G_OBJECT (proplist->priv->widget),
-                         prop->name, &gvalue);
+  if (proplist->priv->child_props)
+    {
+      GtkWidget *parent;
+
+      parent = gtk_widget_get_parent (proplist->priv->widget);
+      gtk_container_child_get_property (GTK_CONTAINER (parent),
+                                        proplist->priv->widget,
+                                        prop->name, &gvalue);
+    }
+  else
+    g_object_get_property (G_OBJECT (proplist->priv->widget),
+                           prop->name, &gvalue);
 
   if (G_VALUE_HOLDS_ENUM (&gvalue))
     {
@@ -176,9 +260,11 @@ parasite_proplist_get_type (void)
 
 
 GtkWidget *
-parasite_proplist_new (void)
+parasite_proplist_new (gboolean child_props)
 {
-  return GTK_WIDGET (g_object_new (PARASITE_TYPE_PROPLIST, NULL));
+  return GTK_WIDGET (g_object_new (PARASITE_TYPE_PROPLIST,
+                                   "child-properties", child_props,
+                                   NULL));
 }
 
 void
@@ -207,8 +293,20 @@ parasite_proplist_set_widget (ParasitePropList *proplist,
   g_hash_table_remove_all (proplist->priv->prop_iters);
   gtk_list_store_clear (proplist->priv->model);
 
-  props = g_object_class_list_properties (G_OBJECT_GET_CLASS (widget),
-                                          &num_properties);
+  if (proplist->priv->child_props)
+    {
+      GtkWidget *parent;
+
+      parent = gtk_widget_get_parent (widget);
+      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 (widget),
+                                            &num_properties);
 
   for (i = 0; i < num_properties; i++)
     {
@@ -226,7 +324,10 @@ parasite_proplist_set_widget (ParasitePropList *proplist,
                            gtk_tree_iter_copy (&iter));
 
       /* Listen for updates */
-      signal_name = g_strdup_printf ("notify::%s", prop->name);
+      if (proplist->priv->child_props)
+        signal_name = g_strdup_printf ("child-notify::%s", prop->name);
+      else
+        signal_name = g_strdup_printf ("notify::%s", prop->name);
 
       handler = g_signal_connect (G_OBJECT (widget), signal_name,
                                   G_CALLBACK (parasite_proplist_prop_changed_cb),
diff --git a/modules/other/parasite/prop-list.h b/modules/other/parasite/prop-list.h
index c88e583..bfa1f4a 100644
--- a/modules/other/parasite/prop-list.h
+++ b/modules/other/parasite/prop-list.h
@@ -55,9 +55,9 @@ typedef struct _ParasitePropListClass
 G_BEGIN_DECLS
 
 GType      parasite_proplist_get_type   (void);
-GtkWidget *parasite_proplist_new        (void);
+GtkWidget *parasite_proplist_new        (gboolean child_props);
 void       parasite_proplist_set_widget (ParasitePropList *proplist,
-                                                        GtkWidget        *widget);
+                                         GtkWidget        *widget);
 
 
 G_END_DECLS
diff --git a/modules/other/parasite/property-cell-renderer.c b/modules/other/parasite/property-cell-renderer.c
index 1f6052d..6cb8505 100644
--- a/modules/other/parasite/property-cell-renderer.c
+++ b/modules/other/parasite/property-cell-renderer.c
@@ -33,6 +33,7 @@ typedef struct
 {
   GObject *object;
   char *name;
+  gboolean is_child_property;
 
 } ParasitePropertyCellRendererPrivate;
 
@@ -61,7 +62,8 @@ enum
 {
   PROP_0,
   PROP_OBJECT,
-  PROP_NAME
+  PROP_NAME,
+  PROP_IS_CHILD_PROPERTY
 };
 
 
@@ -92,6 +94,10 @@ parasite_property_cell_renderer_class_init (ParasitePropertyCellRendererClass *k
       g_param_spec_string ("name", "Name", "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));
+
   g_type_class_add_private (object_class, sizeof (ParasitePropertyCellRendererPrivate));
 }
 
@@ -114,6 +120,10 @@ parasite_property_cell_renderer_get_property (GObject    *object,
       g_value_set_string (value, priv->name);
       break;
 
+    case PROP_IS_CHILD_PROPERTY:
+      g_value_set_boolean (value, priv->is_child_property);
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
       break;
@@ -142,12 +152,79 @@ parasite_property_cell_renderer_set_property (GObject      *object,
       g_object_notify (object, "name");
       break;
 
+    case PROP_IS_CHILD_PROPERTY:
+      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_prop (GtkCellRenderer *renderer)
+{
+  ParasitePropertyCellRendererPrivate *priv =
+    PARASITE_PROPERTY_CELL_RENDERER_GET_PRIVATE (renderer);
+
+  if (priv->is_child_property)
+    {
+      GtkWidget *widget;
+      GtkWidget *parent;
+
+      widget = GTK_WIDGET (priv->object);
+      parent = gtk_widget_get_parent (widget);
+
+      return gtk_container_class_find_child_property (G_OBJECT_GET_CLASS (parent), priv->name);
+    }
+
+  return g_object_class_find_property (G_OBJECT_GET_CLASS (priv->object), priv->name);
+}
+
+static void
+get_value (GtkCellRenderer *renderer,
+           GValue          *gvalue)
+{
+  ParasitePropertyCellRendererPrivate *priv =
+    PARASITE_PROPERTY_CELL_RENDERER_GET_PRIVATE (renderer);
+
+  if (priv->is_child_property)
+    {
+      GtkWidget *widget;
+      GtkWidget *parent;
+
+      widget = GTK_WIDGET (priv->object);
+      parent = gtk_widget_get_parent (widget);
+
+      gtk_container_child_get_property (GTK_CONTAINER (parent), widget, priv->name, gvalue);
+    }
+  else
+    g_object_get_property (priv->object, priv->name, gvalue);
+}
+
+static void
+set_value (GtkCellRenderer *renderer,
+           GValue          *gvalue)
+{
+  ParasitePropertyCellRendererPrivate *priv =
+    PARASITE_PROPERTY_CELL_RENDERER_GET_PRIVATE (renderer);
+
+  if (priv->is_child_property)
+    {
+      GtkWidget *widget;
+      GtkWidget *parent;
+
+      widget = GTK_WIDGET (priv->object);
+      parent = gtk_widget_get_parent (widget);
+
+      gtk_container_child_set_property (GTK_CONTAINER (parent), widget, priv->name, gvalue);
+    }
+  else
+    g_object_set_property (priv->object, priv->name, gvalue);
+}
+
 static GtkCellEditable *
 parasite_property_cell_renderer_start_editing (GtkCellRenderer      *renderer,
                                                GdkEvent             *event,
@@ -159,20 +236,17 @@ parasite_property_cell_renderer_start_editing (GtkCellRenderer      *renderer,
 {
   PangoFontDescription *font_desc;
   GtkCellEditable *editable = NULL;
-  GObject *object;
-  const char *name;
   GValue gvalue = { 0 };
   GParamSpec *prop;
 
-  g_object_get (renderer, "object", &object, "name", &name, NULL);
-
-  prop = g_object_class_find_property (G_OBJECT_GET_CLASS (object), name);
+  prop = find_prop (renderer);
 
   if (!(prop->flags & G_PARAM_WRITABLE))
     return NULL;
 
   g_value_init (&gvalue, prop->value_type);
-  g_object_get_property (object, name, &gvalue);
+
+  get_value (renderer, &gvalue);
 
   if (G_VALUE_HOLDS_ENUM (&gvalue) || G_VALUE_HOLDS_BOOLEAN (&gvalue))
     {
@@ -308,9 +382,6 @@ parasite_property_cell_renderer_start_editing (GtkCellRenderer      *renderer,
                     G_CALLBACK (parasite_property_cell_renderer_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;
 }
 
@@ -318,15 +389,11 @@ static void
 parasite_property_cell_renderer_stop_editing (GtkCellEditable *editable,
                                               GtkCellRenderer *renderer)
 {
-  GObject *object;
-  const gchar *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 = find_prop (renderer);
 
-  prop = g_object_class_find_property (G_OBJECT_GET_CLASS (object), name);
   g_value_init (&gvalue, prop->value_type);
 
   if (GTK_IS_ENTRY (editable))
@@ -388,7 +455,7 @@ parasite_property_cell_renderer_stop_editing (GtkCellEditable *editable,
         }
     }
 
-  g_object_set_property (object, name, &gvalue);
+  set_value (renderer, &gvalue);
   g_value_unset (&gvalue);
 }
 
diff --git a/modules/other/parasite/window.c b/modules/other/parasite/window.c
index 6d09426..f8769f4 100644
--- a/modules/other/parasite/window.c
+++ b/modules/other/parasite/window.c
@@ -33,8 +33,8 @@ on_widget_tree_selection_changed (ParasiteWidgetTree *widget_tree,
     parasite_widget_tree_get_selected_widget (widget_tree);
   if (selected != NULL)
     {
-      parasite_proplist_set_widget (PARASITE_PROPLIST (parasite->prop_list),
-                                    selected);
+      parasite_proplist_set_widget (PARASITE_PROPLIST (parasite->prop_list), selected);
+      parasite_proplist_set_widget (PARASITE_PROPLIST (parasite->child_prop_list), selected);
 
       /* Flash the widget. */
       gtkparasite_flash_widget (parasite, selected);
@@ -66,20 +66,36 @@ create_widget_list_pane (ParasiteWindow *parasite)
 static GtkWidget *
 create_prop_list_pane (ParasiteWindow *parasite)
 {
+  GtkWidget *paned;
   GtkWidget *swin;
 
+  paned = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
+
   swin = gtk_scrolled_window_new (NULL, NULL);
   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swin),
                                   GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
   gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (swin),
                                        GTK_SHADOW_IN);
   gtk_widget_set_size_request (swin, 250, -1);
-
-  parasite->prop_list = parasite_proplist_new ();
+  parasite->prop_list = parasite_proplist_new (FALSE);
   gtk_widget_show (parasite->prop_list);
   gtk_container_add (GTK_CONTAINER (swin), parasite->prop_list);
+  gtk_widget_show (swin);
+  gtk_container_add (GTK_CONTAINER (paned), swin);
 
-  return swin;
+  swin = gtk_scrolled_window_new (NULL, NULL);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swin),
+                                  GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (swin),
+                                       GTK_SHADOW_IN);
+  gtk_widget_set_size_request (swin, 250, -1);
+  parasite->child_prop_list = parasite_proplist_new (TRUE);
+  gtk_widget_show (parasite->child_prop_list);
+  gtk_container_add (GTK_CONTAINER (swin), parasite->child_prop_list);
+  gtk_widget_show (swin);
+  gtk_container_add (GTK_CONTAINER (paned), swin);
+
+  return paned;
 }
 
 static void


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