parasite: Display child properties too

This commit is contained in:
Matthias Clasen 2014-05-03 15:25:43 -04:00
parent 2166a9b163
commit 413faa55a0
5 changed files with 161 additions and 43 deletions

View File

@ -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;

View File

@ -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(

View File

@ -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);

View File

@ -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 *

View File

@ -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),