[glade3] * gladeui/glade-widget.[ch]: Hide glade_widget_set_object(), improved reference count balancing



commit e551f1d12785aa5bb5b83531e4c3f7074bb6768c
Author: Tristan Van Berkom <tristan van berkom gmail com>
Date:   Sun Dec 19 20:07:12 2010 +0900

    	* gladeui/glade-widget.[ch]: Hide glade_widget_set_object(), improved reference count
    	  balancing and fixed segfaults upon closing projects that contain filechooser dialogs
    	  referenced by filechooserbuttons.

 ChangeLog              |    4 ++
 gladeui/glade-widget.c |  118 ++++++++++++++++++++++++++---------------------
 gladeui/glade-widget.h |    3 -
 3 files changed, 69 insertions(+), 56 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index a16224e..a8e44eb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -6,6 +6,10 @@
 	* plugins/gtk+/glade-gtk.c: Removed alpha_sort_box_children(), project needs to be
 	  sorted with box children by position, loading process depends on this.
 
+	* gladeui/glade-widget.[ch]: Hide glade_widget_set_object(), improved reference count
+	  balancing and fixed segfaults upon closing projects that contain filechooser dialogs
+	  referenced by filechooserbuttons.
+
 2010-12-18  Tristan Van Berkom <tristanvb openismus com>
 
 	* src/Makefile.am, gladeui/Makefile.am, plugins/gtk+/Makefile.am, plugins/gnome/Makefile.am:
diff --git a/gladeui/glade-widget.c b/gladeui/glade-widget.c
index d5acc5d..ac67f1b 100644
--- a/gladeui/glade-widget.c
+++ b/gladeui/glade-widget.c
@@ -63,8 +63,11 @@ static void         glade_widget_set_adaptor           (GladeWidget           *w
 							GladeWidgetAdaptor    *adaptor);
 static void         glade_widget_set_properties        (GladeWidget           *widget,
 							GList                 *properties);
-static gboolean     glade_window_is_embedded           (GtkWindow *window);
-static gboolean     glade_widget_embed                 (GladeWidget *widget);
+static gboolean     glade_window_is_embedded           (GtkWindow             *window);
+static gboolean     glade_widget_embed                 (GladeWidget           *widget);
+static void         glade_widget_set_object            (GladeWidget           *gwidget, 
+							GObject               *new_object, 
+							gboolean               destroy);
 
 enum
 {
@@ -166,6 +169,8 @@ glade_widget_remove_child_impl (GladeWidget  *widget,
 		(widget->adaptor, widget->object, child->object);
 
 	g_object_unref (child);
+
+	child->parent = NULL;
 }
 
 static void
@@ -532,7 +537,7 @@ glade_widget_build_object (GladeWidget *widget,
 	if (reason == GLADE_CREATE_LOAD)
 	{
 		object = glade_widget_adaptor_construct_object (widget->adaptor, 0, NULL);
-		glade_widget_set_object (widget, object);
+		glade_widget_set_object (widget, object, TRUE);
 		return object;
 	}
 
@@ -547,7 +552,8 @@ glade_widget_build_object (GladeWidget *widget,
 
 	free_params (params, n_params);
 
-	glade_widget_set_object (widget, object);
+	/* Dont destroy toplevels when rebuilding, handle that separately */
+	glade_widget_set_object (widget, object, reason != GLADE_CREATE_REBUILD);
 
 	if (template)
 		params = glade_widget_template_params (widget, FALSE, &n_params);
@@ -747,9 +753,9 @@ glade_widget_constructor (GType                  type,
 
 	if (gwidget->object == NULL)
 	{
-		object = glade_widget_build_object(gwidget, 
-						   gwidget->construct_template, 
-						   gwidget->construct_reason);
+		object = glade_widget_build_object (gwidget, 
+						    gwidget->construct_template, 
+						    gwidget->construct_reason);
 	}
 
 	/* Copy sync parentless widget props here after a dup
@@ -849,16 +855,6 @@ glade_widget_dispose (GObject *object)
 
 	glade_widget_push_superuser ();
 
-	/* Release references by way of object properties... */
-	while (widget->prop_refs)
-	{
-		GladeProperty *property = GLADE_PROPERTY (widget->prop_refs->data);
-		glade_property_set (property, NULL);
-	}
-
-	if (widget->properties)
-		g_list_foreach (widget->properties, (GFunc)reset_object_property, widget->project);
-
 	/* Unparent all children */
 	if ((children = 
 	     glade_widget_get_children (widget)) != NULL)
@@ -873,6 +869,16 @@ glade_widget_dispose (GObject *object)
 		g_list_free (children);
 	}
 
+	/* Release references by way of object properties... */
+	while (widget->prop_refs)
+	{
+		GladeProperty *property = GLADE_PROPERTY (widget->prop_refs->data);
+		glade_property_set (property, NULL);
+	}
+
+	if (widget->properties)
+		g_list_foreach (widget->properties, (GFunc)reset_object_property, widget->project);
+
 	/* We have to make sure properties release thier references on other widgets first 
 	 * hence the reset (for object properties) */
 	if (widget->properties)
@@ -882,13 +888,7 @@ glade_widget_dispose (GObject *object)
 		widget->properties = NULL;
 	}
 
-	/* We do not keep a reference to internal widgets */
-	glade_widget_set_object (widget, NULL);
-
-	/* At this point, any callbacks on "object" generated by destroy 
-	 * wont come with a GladeWidget 
-	 */
-	g_object_set_qdata (G_OBJECT (object), glade_widget_name_quark, NULL);
+	glade_widget_set_object (widget, NULL, TRUE);
 	
 	if (widget->packing_properties)
 	{
@@ -939,7 +939,7 @@ glade_widget_set_real_property (GObject         *object,
 		break;
 	case PROP_OBJECT:
 		if (g_value_get_object (value))
-			glade_widget_set_object (widget, g_value_get_object (value));
+			glade_widget_set_object (widget, g_value_get_object (value), TRUE);
 		break;
 	case PROP_PROJECT:
 		glade_widget_set_project (widget, GLADE_PROJECT (g_value_get_object (value)));
@@ -2418,8 +2418,8 @@ glade_widget_rebuild (GladeWidget *gwidget)
 	/* Hold a reference to the old widget while we transport properties
 	 * and children from it
 	 */
-	old_object = g_object_ref(glade_widget_get_object (gwidget));
-	new_object = glade_widget_build_object(gwidget, gwidget, GLADE_CREATE_REBUILD);
+	old_object = g_object_ref (glade_widget_get_object (gwidget));
+	new_object = glade_widget_build_object (gwidget, gwidget, GLADE_CREATE_REBUILD);
 
 	/* Only call this once the object has a proper GladeWidget */
 	glade_widget_adaptor_post_create (adaptor, new_object, GLADE_CREATE_REBUILD);
@@ -2431,10 +2431,10 @@ glade_widget_rebuild (GladeWidget *gwidget)
 				      old_object, new_object);
 
 	/* Must call dispose for cases like dialogs and toplevels */
-	if (g_type_is_a (adaptor->type, GTK_TYPE_OBJECT))
-		gtk_object_destroy  (GTK_OBJECT (old_object));
+	if (GTK_IS_WINDOW (old_object))
+		gtk_widget_destroy (GTK_WIDGET (old_object));
 	else
-		g_object_run_dispose (G_OBJECT (old_object));
+		g_object_unref (old_object);
 
 	/* Reparent any children of the old object to the new object
 	 * (this function will consume and free the child list).
@@ -2470,7 +2470,8 @@ glade_widget_rebuild (GladeWidget *gwidget)
 
 	/* Sync packing.
 	 */
-	glade_widget_sync_packing_props (gwidget);
+	if (gwidget->parent)
+		glade_widget_sync_packing_props (gwidget);
 
 	/* If the widget was in a project (and maybe the selection), then
 	 * restore that stuff.
@@ -3327,17 +3328,8 @@ glade_widget_event_private (GtkWidget   *widget,
 		return FALSE;
 }
 
-/**
- * glade_widget_set_object:
- * @gwidget: A #GladeWidget
- * @new_object: the new #GObject for @gwidget
- *
- * Set the runtime object for this GladeWidget wrapper
- * (this is used deep in the core and is probably unsafe
- * to use elsewhere).
- */
-void
-glade_widget_set_object (GladeWidget *gwidget, GObject *new_object)
+static void
+glade_widget_set_object (GladeWidget *gwidget, GObject *new_object, gboolean destroy)
 {
 	GladeWidgetAdaptor *adaptor;
 	GObject            *old_object;
@@ -3347,19 +3339,22 @@ glade_widget_set_object (GladeWidget *gwidget, GObject *new_object)
 			  g_type_is_a (G_OBJECT_TYPE (new_object),
 				       gwidget->adaptor->type));
 
-	adaptor    = gwidget->adaptor;
-	old_object = gwidget->object;
+	if (gwidget->object == new_object)
+		return;
+
+	adaptor         = gwidget->adaptor;
+	old_object      = gwidget->object;
+	gwidget->object = new_object;
 
 	if (new_object)
 	{
 		/* Add internal reference to new widget if its not internal */
-		if (gwidget->internal)
-			gwidget->object = G_OBJECT(new_object);
-		else if (GTK_IS_OBJECT (new_object))
-			gwidget->object = g_object_ref (G_OBJECT(new_object));
-		else
-			/* If this is a base GObject; assume ownership of the initial ref count */
-			gwidget->object = new_object;
+		if (gwidget->internal == NULL)
+		{
+			/* Assume ownership of floating objects */
+			if (g_object_is_floating (new_object))
+				g_object_ref_sink (new_object);
+		}
 	
 		g_object_set_qdata (G_OBJECT (new_object), glade_widget_name_quark, gwidget);
 
@@ -3381,10 +3376,27 @@ glade_widget_set_object (GladeWidget *gwidget, GObject *new_object)
 	}
 
 	/* Remove internal reference to old widget */
-	if (gwidget->internal == NULL && old_object) 
+	if (old_object)
 	{
+		/* From this point on, the GladeWidget is no longer retrievable with
+		 * glade_widget_get_from_gobject() */
 		g_object_set_qdata (G_OBJECT (old_object), glade_widget_name_quark, NULL);
-		g_object_unref (G_OBJECT (old_object));
+
+		if (gwidget->internal == NULL)
+		{
+
+#if _YOU_WANT_TO_LOOK_AT_PROJECT_REFCOUNT_BALANCING_
+			g_print ("Killing '%s::%s' widget's object with reference count %d\n",
+				 gwidget->adaptor->name, gwidget->name ? gwidget->name : "(unknown)",
+				 old_object->ref_count);
+#endif
+
+			if (GTK_IS_WINDOW (old_object) && destroy)
+				gtk_widget_destroy (GTK_WIDGET (old_object));
+			else
+				g_object_unref (old_object);
+			
+		}
 	}
 	g_object_notify (G_OBJECT (gwidget), "object");
 }
diff --git a/gladeui/glade-widget.h b/gladeui/glade-widget.h
index 3d909f7..541e2f1 100644
--- a/gladeui/glade-widget.h
+++ b/gladeui/glade-widget.h
@@ -398,9 +398,6 @@ void                    glade_widget_set_internal	    (GladeWidget      *widget,
 							     const gchar      *internal);
  
 G_CONST_RETURN gchar   *glade_widget_get_internal           (GladeWidget      *widget);
-
-void                    glade_widget_set_object		    (GladeWidget      *gwidget,
-							     GObject          *new_object);
  
 GObject                *glade_widget_get_object             (GladeWidget      *widget);
 



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