mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2025-01-12 21:40:19 +00:00
inspector: Deal with dying objects
The widget-tree was not safe against object just going away. Fix this by using row references instead of iters where necessary, and by using weak refs to clean up when objects die.
This commit is contained in:
parent
0dbfef5696
commit
700657ad19
@ -39,17 +39,27 @@ typedef struct
|
|||||||
|
|
||||||
struct _GtkInspectorClassesListPrivate
|
struct _GtkInspectorClassesListPrivate
|
||||||
{
|
{
|
||||||
GtkWidget *toolbar;
|
|
||||||
GtkWidget *view;
|
|
||||||
GtkTreeViewColumn *column;
|
|
||||||
GtkCellRenderer *name_renderer;
|
|
||||||
GtkListStore *model;
|
GtkListStore *model;
|
||||||
GHashTable *contexts;
|
GtkStyleContext *context;
|
||||||
GtkStyleContext *current_context;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE_WITH_PRIVATE (GtkInspectorClassesList, gtk_inspector_classes_list, GTK_TYPE_BOX)
|
G_DEFINE_TYPE_WITH_PRIVATE (GtkInspectorClassesList, gtk_inspector_classes_list, GTK_TYPE_BOX)
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_hash_context (GtkInspectorClassesList *cl, GHashTable *hash_context)
|
||||||
|
{
|
||||||
|
g_object_set_data_full (G_OBJECT (cl->priv->context),
|
||||||
|
"gtk-inspector-hash-context",
|
||||||
|
hash_context, (GDestroyNotify)g_hash_table_unref);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GHashTable *
|
||||||
|
get_hash_context (GtkInspectorClassesList *cl)
|
||||||
|
{
|
||||||
|
return (GHashTable *)g_object_get_data (G_OBJECT (cl->priv->context),
|
||||||
|
"gtk-inspector-hash-context");
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
enabled_toggled (GtkCellRendererToggle *renderer,
|
enabled_toggled (GtkCellRendererToggle *renderer,
|
||||||
const gchar *path,
|
const gchar *path,
|
||||||
@ -76,7 +86,7 @@ enabled_toggled (GtkCellRendererToggle *renderer,
|
|||||||
COLUMN_ENABLED, enabled,
|
COLUMN_ENABLED, enabled,
|
||||||
-1);
|
-1);
|
||||||
|
|
||||||
context = g_hash_table_lookup (cl->priv->contexts, cl->priv->current_context);
|
context = get_hash_context (cl);
|
||||||
if (context)
|
if (context)
|
||||||
{
|
{
|
||||||
c = g_hash_table_lookup (context, name);
|
c = g_hash_table_lookup (context, name);
|
||||||
@ -84,9 +94,9 @@ enabled_toggled (GtkCellRendererToggle *renderer,
|
|||||||
{
|
{
|
||||||
c->enabled = enabled;
|
c->enabled = enabled;
|
||||||
if (enabled)
|
if (enabled)
|
||||||
gtk_style_context_add_class (cl->priv->current_context, name);
|
gtk_style_context_add_class (cl->priv->context, name);
|
||||||
else
|
else
|
||||||
gtk_style_context_remove_class (cl->priv->current_context, name);
|
gtk_style_context_remove_class (cl->priv->context, name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
g_warning ("GtkInspector: Couldn't find the css class %s in the class hash table.", name);
|
g_warning ("GtkInspector: Couldn't find the css class %s in the class hash table.", name);
|
||||||
@ -120,14 +130,16 @@ add_clicked (GtkButton *button,
|
|||||||
|
|
||||||
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
|
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
|
||||||
{
|
{
|
||||||
const gchar *name = gtk_entry_get_text (GTK_ENTRY (entry));
|
const gchar *name;
|
||||||
GHashTable *context = g_hash_table_lookup (cl->priv->contexts, cl->priv->current_context);
|
GHashTable *context;
|
||||||
|
|
||||||
|
context = get_hash_context (cl);
|
||||||
|
name = gtk_entry_get_text (GTK_ENTRY (entry));
|
||||||
if (*name && !g_hash_table_contains (context, name))
|
if (*name && !g_hash_table_contains (context, name))
|
||||||
{
|
{
|
||||||
GtkTreeIter tree_iter;
|
GtkTreeIter tree_iter;
|
||||||
|
|
||||||
gtk_style_context_add_class (cl->priv->current_context, name);
|
gtk_style_context_add_class (cl->priv->context, name);
|
||||||
|
|
||||||
GtkInspectorClassesListByContext *c = g_new0 (GtkInspectorClassesListByContext, 1);
|
GtkInspectorClassesListByContext *c = g_new0 (GtkInspectorClassesListByContext, 1);
|
||||||
c->enabled = TRUE;
|
c->enabled = TRUE;
|
||||||
@ -155,7 +167,7 @@ read_classes_from_style_context (GtkInspectorClassesList *cl)
|
|||||||
GHashTable *hash_context;
|
GHashTable *hash_context;
|
||||||
|
|
||||||
hash_context = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
hash_context = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||||||
classes = gtk_style_context_list_classes (cl->priv->current_context);
|
classes = gtk_style_context_list_classes (cl->priv->context);
|
||||||
|
|
||||||
for (l = classes; l; l = l->next)
|
for (l = classes; l; l = l->next)
|
||||||
{
|
{
|
||||||
@ -171,7 +183,7 @@ read_classes_from_style_context (GtkInspectorClassesList *cl)
|
|||||||
-1);
|
-1);
|
||||||
}
|
}
|
||||||
g_list_free (classes);
|
g_list_free (classes);
|
||||||
g_hash_table_replace (cl->priv->contexts, cl->priv->current_context, hash_context);
|
set_hash_context (cl, hash_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -181,15 +193,16 @@ restore_defaults_clicked (GtkButton *button,
|
|||||||
GHashTableIter hash_iter;
|
GHashTableIter hash_iter;
|
||||||
gchar *name;
|
gchar *name;
|
||||||
GtkInspectorClassesListByContext *c;
|
GtkInspectorClassesListByContext *c;
|
||||||
GHashTable *hash_context = g_hash_table_lookup (cl->priv->contexts, cl->priv->current_context);
|
GHashTable *hash_context;
|
||||||
|
|
||||||
|
hash_context = get_hash_context (cl);
|
||||||
g_hash_table_iter_init (&hash_iter, hash_context);
|
g_hash_table_iter_init (&hash_iter, hash_context);
|
||||||
while (g_hash_table_iter_next (&hash_iter, (gpointer *)&name, (gpointer *)&c))
|
while (g_hash_table_iter_next (&hash_iter, (gpointer *)&name, (gpointer *)&c))
|
||||||
{
|
{
|
||||||
if (c->style == PANGO_STYLE_ITALIC)
|
if (c->style == PANGO_STYLE_ITALIC)
|
||||||
gtk_style_context_remove_class (cl->priv->current_context, name);
|
gtk_style_context_remove_class (cl->priv->context, name);
|
||||||
else if (!c->enabled)
|
else if (!c->enabled)
|
||||||
gtk_style_context_add_class (cl->priv->current_context, name);
|
gtk_style_context_add_class (cl->priv->context, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
gtk_list_store_clear (cl->priv->model);
|
gtk_list_store_clear (cl->priv->model);
|
||||||
@ -201,27 +214,47 @@ gtk_inspector_classes_list_init (GtkInspectorClassesList *cl)
|
|||||||
{
|
{
|
||||||
cl->priv = gtk_inspector_classes_list_get_instance_private (cl);
|
cl->priv = gtk_inspector_classes_list_get_instance_private (cl);
|
||||||
gtk_widget_init_template (GTK_WIDGET (cl));
|
gtk_widget_init_template (GTK_WIDGET (cl));
|
||||||
cl->priv->contexts = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)g_hash_table_destroy);
|
}
|
||||||
|
|
||||||
|
static void remove_dead_object (gpointer data, GObject *dead_object);
|
||||||
|
|
||||||
|
static void
|
||||||
|
cleanup_context (GtkInspectorClassesList *cl)
|
||||||
|
{
|
||||||
|
if (cl->priv->context)
|
||||||
|
g_object_weak_unref (G_OBJECT (cl->priv->context), remove_dead_object, cl);
|
||||||
|
|
||||||
|
gtk_list_store_clear (cl->priv->model);
|
||||||
|
cl->priv->context = NULL;
|
||||||
|
gtk_widget_set_sensitive (GTK_WIDGET (cl), FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
remove_dead_object (gpointer data, GObject *dead_object)
|
||||||
|
{
|
||||||
|
GtkInspectorClassesList *cl = data;
|
||||||
|
|
||||||
|
cl->priv->context = NULL;
|
||||||
|
cleanup_context (cl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gtk_inspector_classes_list_set_widget (GtkInspectorClassesList *cl,
|
gtk_inspector_classes_list_set_widget (GtkInspectorClassesList *cl,
|
||||||
GtkWidget *widget)
|
GtkWidget *widget)
|
||||||
{
|
{
|
||||||
GtkStyleContext *widget_context;
|
|
||||||
GHashTable *hash_context;
|
GHashTable *hash_context;
|
||||||
GtkTreeIter tree_iter;
|
GtkTreeIter tree_iter;
|
||||||
GtkInspectorClassesListByContext *c;
|
GtkInspectorClassesListByContext *c;
|
||||||
|
|
||||||
gtk_list_store_clear (cl->priv->model);
|
cleanup_context (cl);
|
||||||
|
|
||||||
gtk_widget_set_sensitive (GTK_WIDGET (cl), TRUE);
|
gtk_widget_set_sensitive (GTK_WIDGET (cl), TRUE);
|
||||||
widget_context = gtk_widget_get_style_context (widget);
|
|
||||||
|
|
||||||
cl->priv->current_context = widget_context;
|
cl->priv->context = gtk_widget_get_style_context (widget);
|
||||||
gtk_widget_set_sensitive (cl->priv->toolbar, TRUE);
|
|
||||||
|
|
||||||
hash_context = g_hash_table_lookup (cl->priv->contexts, widget_context);
|
g_object_weak_ref (G_OBJECT (cl->priv->context), remove_dead_object, cl);
|
||||||
|
|
||||||
|
hash_context = get_hash_context (cl);
|
||||||
if (hash_context)
|
if (hash_context)
|
||||||
{
|
{
|
||||||
GHashTableIter hash_iter;
|
GHashTableIter hash_iter;
|
||||||
@ -239,9 +272,7 @@ gtk_inspector_classes_list_set_widget (GtkInspectorClassesList *cl,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
read_classes_from_style_context (cl);
|
||||||
read_classes_from_style_context (cl);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -250,11 +281,7 @@ gtk_inspector_classes_list_class_init (GtkInspectorClassesListClass *klass)
|
|||||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||||
|
|
||||||
gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/inspector/classes-list.ui");
|
gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/inspector/classes-list.ui");
|
||||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorClassesList, toolbar);
|
|
||||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorClassesList, view);
|
|
||||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorClassesList, model);
|
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorClassesList, model);
|
||||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorClassesList, column);
|
|
||||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorClassesList, name_renderer);
|
|
||||||
gtk_widget_class_bind_template_callback (widget_class, add_clicked);
|
gtk_widget_class_bind_template_callback (widget_class, add_clicked);
|
||||||
gtk_widget_class_bind_template_callback (widget_class, restore_defaults_clicked);
|
gtk_widget_class_bind_template_callback (widget_class, restore_defaults_clicked);
|
||||||
gtk_widget_class_bind_template_callback (widget_class, enabled_toggled);
|
gtk_widget_class_bind_template_callback (widget_class, enabled_toggled);
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
<template class="GtkInspectorClassesList" parent="GtkBox">
|
<template class="GtkInspectorClassesList" parent="GtkBox">
|
||||||
<property name="orientation">vertical</property>
|
<property name="orientation">vertical</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkToolbar" id="toolbar">
|
<object class="GtkToolbar">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="icon-size">small-toolbar</property>
|
<property name="icon-size">small-toolbar</property>
|
||||||
<property name="sensitive">False</property>
|
<property name="sensitive">False</property>
|
||||||
@ -37,11 +37,11 @@
|
|||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="expand">True</property>
|
<property name="expand">True</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkTreeView" id="view">
|
<object class="GtkTreeView">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="model">model</property>
|
<property name="model">model</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkTreeViewColumn" id="column">
|
<object class="GtkTreeViewColumn">
|
||||||
<property name="title" translatable="yes">Name</property>
|
<property name="title" translatable="yes">Name</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkCellRendererToggle">
|
<object class="GtkCellRendererToggle">
|
||||||
@ -53,7 +53,7 @@
|
|||||||
</attributes>
|
</attributes>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkCellRendererText" id="name_renderer">
|
<object class="GtkCellRendererText">
|
||||||
<property name="scale">0.8</property>
|
<property name="scale">0.8</property>
|
||||||
</object>
|
</object>
|
||||||
<attributes>
|
<attributes>
|
||||||
|
@ -205,8 +205,9 @@ create_provider (GtkInspectorCssEditor *ce)
|
|||||||
gtk_style_context_add_provider (ce->priv->context,
|
gtk_style_context_add_provider (ce->priv->context,
|
||||||
GTK_STYLE_PROVIDER (provider),
|
GTK_STYLE_PROVIDER (provider),
|
||||||
G_MAXUINT);
|
G_MAXUINT);
|
||||||
g_object_set_data (G_OBJECT (ce->priv->context),
|
g_object_set_data_full (G_OBJECT (ce->priv->context),
|
||||||
GTK_INSPECTOR_CSS_EDITOR_PROVIDER, provider);
|
GTK_INSPECTOR_CSS_EDITOR_PROVIDER, provider,
|
||||||
|
g_object_unref);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_signal_connect (provider, "parsing-error",
|
g_signal_connect (provider, "parsing-error",
|
||||||
@ -302,6 +303,15 @@ gtk_inspector_css_editor_new (gboolean global)
|
|||||||
NULL));
|
NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
remove_dead_object (gpointer data, GObject *dead_object)
|
||||||
|
{
|
||||||
|
GtkInspectorCssEditor *ce = data;
|
||||||
|
|
||||||
|
ce->priv->context = NULL;
|
||||||
|
gtk_widget_set_sensitive (GTK_WIDGET (ce), ce->priv->global);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gtk_inspector_css_editor_set_widget (GtkInspectorCssEditor *ce,
|
gtk_inspector_css_editor_set_widget (GtkInspectorCssEditor *ce,
|
||||||
GtkWidget *widget)
|
GtkWidget *widget)
|
||||||
@ -316,6 +326,7 @@ gtk_inspector_css_editor_set_widget (GtkInspectorCssEditor *ce,
|
|||||||
|
|
||||||
if (ce->priv->context)
|
if (ce->priv->context)
|
||||||
{
|
{
|
||||||
|
g_object_weak_unref (G_OBJECT (ce->priv->context), remove_dead_object, ce);
|
||||||
text = get_current_text (GTK_TEXT_BUFFER (ce->priv->text));
|
text = get_current_text (GTK_TEXT_BUFFER (ce->priv->text));
|
||||||
g_object_set_data_full (G_OBJECT (ce->priv->context),
|
g_object_set_data_full (G_OBJECT (ce->priv->context),
|
||||||
GTK_INSPECTOR_CSS_EDITOR_TEXT,
|
GTK_INSPECTOR_CSS_EDITOR_TEXT,
|
||||||
@ -331,6 +342,8 @@ gtk_inspector_css_editor_set_widget (GtkInspectorCssEditor *ce,
|
|||||||
|
|
||||||
set_initial_text (ce);
|
set_initial_text (ce);
|
||||||
disable_toggled (ce->priv->disable_button, ce);
|
disable_toggled (ce->priv->disable_button, ce);
|
||||||
|
|
||||||
|
g_object_weak_ref (G_OBJECT (ce->priv->context), remove_dead_object, ce);
|
||||||
}
|
}
|
||||||
|
|
||||||
// vim: set et sw=2 ts=2:
|
// vim: set et sw=2 ts=2:
|
||||||
|
@ -50,7 +50,7 @@ G_BEGIN_DECLS
|
|||||||
|
|
||||||
GType gtk_inspector_css_editor_get_type (void);
|
GType gtk_inspector_css_editor_get_type (void);
|
||||||
GtkWidget *gtk_inspector_css_editor_new (gboolean global);
|
GtkWidget *gtk_inspector_css_editor_new (gboolean global);
|
||||||
void gtk_inspector_css_editor_set_widget (GtkInspectorCssEditor *editor,
|
void gtk_inspector_css_editor_set_widget (GtkInspectorCssEditor *ce,
|
||||||
GtkWidget *widget);
|
GtkWidget *widget);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
@ -232,6 +232,38 @@ gtk_inspector_prop_list_new (GtkWidget *widget_tree,
|
|||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void remove_dead_object (gpointer data, GObject *dead_object);
|
||||||
|
|
||||||
|
static void
|
||||||
|
cleanup_object (GtkInspectorPropList *pl)
|
||||||
|
{
|
||||||
|
gtk_widget_set_sensitive (GTK_WIDGET (pl), FALSE);
|
||||||
|
|
||||||
|
if (pl->priv->object)
|
||||||
|
g_object_weak_unref (pl->priv->object, remove_dead_object, pl);
|
||||||
|
|
||||||
|
if (pl->priv->object && pl->priv->notify_handler_id != 0)
|
||||||
|
{
|
||||||
|
g_signal_handler_disconnect (pl->priv->object, pl->priv->notify_handler_id);
|
||||||
|
pl->priv->notify_handler_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pl->priv->object = NULL;
|
||||||
|
|
||||||
|
g_hash_table_remove_all (pl->priv->prop_iters);
|
||||||
|
gtk_list_store_clear (pl->priv->model);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
remove_dead_object (gpointer data, GObject *dead_object)
|
||||||
|
{
|
||||||
|
GtkInspectorPropList *pl = data;
|
||||||
|
|
||||||
|
pl->priv->notify_handler_id = 0;
|
||||||
|
pl->priv->object = NULL;
|
||||||
|
cleanup_object (pl);
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
gtk_inspector_prop_list_set_object (GtkInspectorPropList *pl,
|
gtk_inspector_prop_list_set_object (GtkInspectorPropList *pl,
|
||||||
GObject *object)
|
GObject *object)
|
||||||
@ -244,18 +276,16 @@ gtk_inspector_prop_list_set_object (GtkInspectorPropList *pl,
|
|||||||
if (pl->priv->object == object)
|
if (pl->priv->object == object)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (pl->priv->notify_handler_id != 0)
|
cleanup_object (pl);
|
||||||
{
|
|
||||||
g_signal_handler_disconnect (pl->priv->object, pl->priv->notify_handler_id);
|
|
||||||
pl->priv->notify_handler_id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_hash_table_remove_all (pl->priv->prop_iters);
|
|
||||||
gtk_list_store_clear (pl->priv->model);
|
|
||||||
gtk_widget_set_sensitive (GTK_WIDGET (pl), FALSE);
|
|
||||||
|
|
||||||
pl->priv->object = object;
|
pl->priv->object = object;
|
||||||
|
|
||||||
|
g_object_weak_ref (object, remove_dead_object, pl);
|
||||||
|
|
||||||
|
g_object_set (pl->priv->attribute_column,
|
||||||
|
"visible", !pl->priv->child_properties && GTK_IS_CELL_RENDERER (object),
|
||||||
|
NULL);
|
||||||
|
|
||||||
if (pl->priv->child_properties)
|
if (pl->priv->child_properties)
|
||||||
{
|
{
|
||||||
GtkWidget *parent;
|
GtkWidget *parent;
|
||||||
@ -294,9 +324,6 @@ gtk_inspector_prop_list_set_object (GtkInspectorPropList *pl,
|
|||||||
G_CALLBACK (gtk_inspector_prop_list_prop_changed_cb),
|
G_CALLBACK (gtk_inspector_prop_list_prop_changed_cb),
|
||||||
pl);
|
pl);
|
||||||
|
|
||||||
g_object_set (pl->priv->attribute_column,
|
|
||||||
"visible", !pl->priv->child_properties && GTK_IS_CELL_RENDERER (object),
|
|
||||||
NULL);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,20 +63,42 @@ on_widget_selected (GtkTreeSelection *selection,
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
GtkInspectorWidgetTree *wt;
|
||||||
GObject *object;
|
GObject *object;
|
||||||
GtkTreeIter *iter;
|
GtkTreeRowReference *row;
|
||||||
gulong map_handler;
|
gulong map_handler;
|
||||||
gulong unmap_handler;
|
gulong unmap_handler;
|
||||||
} ObjectData;
|
} ObjectData;
|
||||||
|
|
||||||
|
static void
|
||||||
|
remove_dead_object (gpointer data, GObject *dead_object)
|
||||||
|
{
|
||||||
|
ObjectData *od = data;
|
||||||
|
|
||||||
|
if (gtk_tree_row_reference_valid (od->row))
|
||||||
|
{
|
||||||
|
GtkTreePath *path;
|
||||||
|
GtkTreeIter iter;
|
||||||
|
path = gtk_tree_row_reference_get_path (od->row);
|
||||||
|
gtk_tree_model_get_iter (GTK_TREE_MODEL (od->wt->priv->model), &iter, path);
|
||||||
|
gtk_tree_store_remove (od->wt->priv->model, &iter);
|
||||||
|
gtk_tree_path_free (path);
|
||||||
|
}
|
||||||
|
od->object = NULL;
|
||||||
|
g_hash_table_remove (od->wt->priv->iters, dead_object);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
object_data_free (gpointer data)
|
object_data_free (gpointer data)
|
||||||
{
|
{
|
||||||
ObjectData *od = data;
|
ObjectData *od = data;
|
||||||
|
|
||||||
gtk_tree_iter_free (od->iter);
|
gtk_tree_row_reference_free (od->row);
|
||||||
|
|
||||||
if (g_signal_handler_is_connected (od->object, od->map_handler))
|
if (od->object)
|
||||||
|
g_object_weak_unref (od->object, remove_dead_object, od);
|
||||||
|
|
||||||
|
if (od->object && od->map_handler)
|
||||||
{
|
{
|
||||||
g_signal_handler_disconnect (od->object, od->map_handler);
|
g_signal_handler_disconnect (od->object, od->map_handler);
|
||||||
g_signal_handler_disconnect (od->object, od->unmap_handler);
|
g_signal_handler_disconnect (od->object, od->unmap_handler);
|
||||||
@ -181,6 +203,7 @@ gtk_inspector_widget_tree_append_object (GtkInspectorWidgetTree *wt,
|
|||||||
const gchar *name)
|
const gchar *name)
|
||||||
{
|
{
|
||||||
GtkTreeIter iter;
|
GtkTreeIter iter;
|
||||||
|
GtkTreePath *path;
|
||||||
const gchar *class_name = G_OBJECT_CLASS_NAME (G_OBJECT_GET_CLASS (object));
|
const gchar *class_name = G_OBJECT_CLASS_NAME (G_OBJECT_GET_CLASS (object));
|
||||||
gchar *address;
|
gchar *address;
|
||||||
gboolean mapped;
|
gboolean mapped;
|
||||||
@ -231,8 +254,11 @@ gtk_inspector_widget_tree_append_object (GtkInspectorWidgetTree *wt,
|
|||||||
-1);
|
-1);
|
||||||
|
|
||||||
od = g_new0 (ObjectData, 1);
|
od = g_new0 (ObjectData, 1);
|
||||||
|
od->wt = wt;
|
||||||
od->object = object;
|
od->object = object;
|
||||||
od->iter = gtk_tree_iter_copy (&iter);
|
path = gtk_tree_model_get_path (GTK_TREE_MODEL (wt->priv->model), &iter);
|
||||||
|
od->row = gtk_tree_row_reference_new (GTK_TREE_MODEL (wt->priv->model), path);
|
||||||
|
gtk_tree_path_free (path);
|
||||||
if (GTK_IS_WIDGET (object))
|
if (GTK_IS_WIDGET (object))
|
||||||
{
|
{
|
||||||
od->map_handler = g_signal_connect (object, "map", G_CALLBACK (map_or_unmap), wt);
|
od->map_handler = g_signal_connect (object, "map", G_CALLBACK (map_or_unmap), wt);
|
||||||
@ -240,6 +266,7 @@ gtk_inspector_widget_tree_append_object (GtkInspectorWidgetTree *wt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
g_hash_table_insert (wt->priv->iters, object, od);
|
g_hash_table_insert (wt->priv->iters, object, od);
|
||||||
|
g_object_weak_ref (object, remove_dead_object, od);
|
||||||
|
|
||||||
g_free (address);
|
g_free (address);
|
||||||
|
|
||||||
@ -306,9 +333,14 @@ gtk_inspector_widget_tree_find_object (GtkInspectorWidgetTree *wt,
|
|||||||
ObjectData *od;
|
ObjectData *od;
|
||||||
|
|
||||||
od = g_hash_table_lookup (wt->priv->iters, object);
|
od = g_hash_table_lookup (wt->priv->iters, object);
|
||||||
if (od)
|
if (od && gtk_tree_row_reference_valid (od->row))
|
||||||
{
|
{
|
||||||
*iter = *od->iter;
|
GtkTreePath *path;
|
||||||
|
|
||||||
|
path = gtk_tree_row_reference_get_path (od->row);
|
||||||
|
gtk_tree_model_get_iter (GTK_TREE_MODEL (wt->priv->model), iter, path);
|
||||||
|
gtk_tree_path_free (path);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user