[glade3] * gladeui/glade-widget.[ch], gladeui/glade-project.c, plugins/gtk+/glade-gtk.c: Cleanup object r



commit 6b3a5ec94873110f731f1b4ef959b72dbeb96206
Author: Tristan Van Berkom <tristan van berkom gmail com>
Date:   Wed Dec 15 21:45:58 2010 +0900

    	* gladeui/glade-widget.[ch], gladeui/glade-project.c, plugins/gtk+/glade-gtk.c: Cleanup
    	  object ref count cycles, now GladeProject just releases all widgets from the project
    	  and keeps a reference to the GladeWidget instead of the GObject, GladeWidget is now
    	  GInitiallyUnowned and GladeProject assumes ownership when objects are added to the
    	  project (glade-gtk.c in this patch avoids needlessly adding a widget to the project
    	  that will be implicitly added, now glade-gtk.c does not directly manually add any
    	  widgets to the project).

 ChangeLog                |    8 +++
 gladeui/glade-project.c  |   67 ++++++---------------------
 gladeui/glade-widget.c   |  115 ++++++++++++++++++++++++++++++----------------
 gladeui/glade-widget.h   |    4 +-
 plugins/gtk+/glade-gtk.c |    8 +---
 5 files changed, 101 insertions(+), 101 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 8ae401d..ae11647 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -7,6 +7,14 @@
 	* plugins/gtk+/glade-gtk.c: Fixed errors when undoing the addition of notebook pages.
 	  The problem at length was an issue of orphaned project widgets left in the project model.
 
+	* gladeui/glade-widget.[ch], gladeui/glade-project.c, plugins/gtk+/glade-gtk.c: Cleanup
+	  object ref count cycles, now GladeProject just releases all widgets from the project
+	  and keeps a reference to the GladeWidget instead of the GObject, GladeWidget is now
+	  GInitiallyUnowned and GladeProject assumes ownership when objects are added to the
+	  project (glade-gtk.c in this patch avoids needlessly adding a widget to the project
+	  that will be implicitly added, now glade-gtk.c does not directly manually add any
+	  widgets to the project).
+
 2010-12-14  Tristan Van Berkom <tristanvb openismus com>
 
 	* Reverted 3.0 commit, now targetting this branch to the final GTK+ 2.x chapter
diff --git a/gladeui/glade-project.c b/gladeui/glade-project.c
index 5efa157..43df9bc 100644
--- a/gladeui/glade-project.c
+++ b/gladeui/glade-project.c
@@ -263,9 +263,7 @@ static void
 glade_project_dispose (GObject *object)
 {
 	GladeProject  *project = GLADE_PROJECT (object);
-	GList   *list;
-	GladeWidget   *gwidget;
-	GladeProperty *property;
+	GList         *list, *tree;
 	
 	/* Emit close signal */
 	g_signal_emit (object, glade_project_signals [CLOSE], 0);
@@ -275,41 +273,11 @@ glade_project_dispose (GObject *object)
 	glade_project_list_unref (project->priv->undo_stack);
 	project->priv->undo_stack = NULL;
 
-	/* Unparent all widgets in the heirarchy first 
-	 * (Since we are bookkeeping exact reference counts, we 
-	 * dont want the hierarchy to just get destroyed)
-	 */
-	for (list = project->priv->objects; list; list = list->next)
-	{
-		gwidget = glade_widget_get_from_gobject (list->data);
-
-		if (gwidget->parent &&
-		    gwidget->internal == NULL &&
-		    glade_widget_adaptor_has_child (gwidget->parent->adaptor,
-						    gwidget->parent->object,
-						    gwidget->object))
-			glade_widget_remove_child (gwidget->parent, gwidget);
-
-		/* Release references by way of object properties... */
-		while (gwidget->prop_refs)
-		{
-			property = GLADE_PROPERTY (gwidget->prop_refs->data);
-			glade_property_set (property, NULL);
-		}
-	}
-
 	/* Remove objects from the project */
-	for (list = project->priv->objects; list; list = list->next)
-	{
-		gwidget = glade_widget_get_from_gobject (list->data);
-		g_object_unref (G_OBJECT (list->data)); /* Remove the GladeProject reference */
-		g_object_unref (G_OBJECT (gwidget));  /* Remove the overall "Glade" reference */
-	}
-	g_list_free (list);
-	g_list_free (project->priv->objects);
-	g_list_free (project->priv->tree);
-	project->priv->tree = NULL;
-	project->priv->objects = NULL;
+	tree = g_list_copy (project->priv->tree);
+	for (list = tree; list; list = list->next)
+		glade_project_remove_object (project, list->data);
+	g_list_free (tree);
 
 	G_OBJECT_CLASS (glade_project_parent_class)->dispose (object);
 }
@@ -1472,9 +1440,7 @@ glade_project_load_from_file (GladeProject *project, const gchar *path)
 			continue;
 
 		if ((widget = glade_widget_read (project, NULL, node, NULL)) != NULL)
-		{
 			glade_project_add_object (project, NULL, widget->object);
-		}
 	}
 
 	if (!has_gtk_dep)
@@ -2895,7 +2861,7 @@ glade_project_add_object (GladeProject *project,
 	GladeWidget      *gwidget;
 	GList            *list, *children;
 	gchar            *name;
-	GtkTreeIter      iter;
+	GtkTreeIter       iter;
 	GtkTreePath	 *path;
 
 	g_return_if_fail (GLADE_IS_PROJECT (project));
@@ -2911,10 +2877,12 @@ glade_project_add_object (GladeProject *project,
 	 */
 	if ((gwidget = glade_widget_get_from_gobject (object)) == NULL)
 		return;
-		
-	/* set the project */
-	if (gwidget->project != project)
-		glade_widget_set_project (gwidget, project);
+
+	if (glade_project_has_object (project, object))
+	{
+		g_warning ("Trying to add an object to the project that is already in the project\n");
+		return;
+	}
 
 	/* Create a name context for newly added toplevels... */
 	if (!gwidget->parent)
@@ -2938,7 +2906,7 @@ glade_project_add_object (GladeProject *project,
 	glade_project_reserve_widget_name (project, gwidget, gwidget->name);
 
 	glade_widget_set_project (gwidget, (gpointer)project);
-	g_object_ref (object);
+	g_object_ref_sink (gwidget);
 
 	if (glade_widget_get_parent (gwidget) == NULL)
 	{
@@ -2947,8 +2915,7 @@ glade_project_add_object (GladeProject *project,
 	}
 
 	/* Be sure to update the list before emitting signals */
-	project->priv->objects = g_list_prepend (project->priv->objects,
-	                                         object);
+	project->priv->objects = g_list_prepend (project->priv->objects, object);
 
 	if (!project->priv->loading)
 	{
@@ -2996,8 +2963,6 @@ glade_project_has_object (GladeProject *project, GObject *object)
 	return (g_list_find (project->priv->objects, object)) != NULL;
 }
 
-
-GladeWidget *project_debug_widget;
 /**
  * glade_project_remove_object:
  * @project: a #GladeProject
@@ -3026,8 +2991,6 @@ glade_project_remove_object (GladeProject *project, GObject *object)
 	if ((gwidget = glade_widget_get_from_gobject (object)) == NULL)
 		return;
 
-	project_debug_widget = gwidget;
-
 	/* Recurse and remove deepest children first */
 	if ((children = 
 	     glade_widget_get_children (gwidget)) != NULL)
@@ -3062,7 +3025,7 @@ glade_project_remove_object (GladeProject *project, GObject *object)
 	}
 
 	project->priv->objects = g_list_remove (project->priv->objects, object);
-	g_object_unref (object);
+	g_object_unref (gwidget);
 
 	project->priv->stamp++;
 
diff --git a/gladeui/glade-widget.c b/gladeui/glade-widget.c
index 15efdbd..e0116c8 100644
--- a/gladeui/glade-widget.c
+++ b/gladeui/glade-widget.c
@@ -102,7 +102,7 @@ static guint         glade_widget_signals[LAST_SIGNAL] = {0};
 static GQuark        glade_widget_name_quark = 0;
 
 
-G_DEFINE_TYPE (GladeWidget, glade_widget, G_TYPE_OBJECT)
+G_DEFINE_TYPE (GladeWidget, glade_widget, G_TYPE_INITIALLY_UNOWNED)
 
 /*******************************************************************************
                            GladeWidget class methods
@@ -802,6 +802,8 @@ glade_widget_finalize (GObject *object)
 
 	g_return_if_fail (GLADE_IS_WIDGET (object));
 
+	g_print ("Finalizing a widget with name %s\n", widget->name);
+
 	g_free (widget->name);
 	g_free (widget->internal);
 	g_free (widget->support_warning);
@@ -812,35 +814,64 @@ glade_widget_finalize (GObject *object)
 	if (widget->pack_props_hash)
 		g_hash_table_destroy (widget->pack_props_hash);
 
-	G_OBJECT_CLASS(glade_widget_parent_class)->finalize(object);
+	G_OBJECT_CLASS (glade_widget_parent_class)->finalize(object);
+}
+
+static void
+reset_object_property (GladeProperty *property,
+		       GladeProject  *project)
+{
+	if (glade_property_class_is_object (property->klass, 
+					    glade_project_get_format (project)))
+		glade_property_reset (property);
 }
 
 static void
 glade_widget_dispose (GObject *object)
 {
 	GladeWidget *widget = GLADE_WIDGET (object);
+	GladeWidget *child;
+	GList *children, *list;
 
 	g_return_if_fail (GLADE_IS_WIDGET (object));
 
-	/* 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);
-
-	/* We do not keep a reference to internal widgets */
-	if (widget->internal == NULL)
+	/* Release references by way of object properties... */
+	while (widget->prop_refs)
 	{
-		if (GTK_IS_OBJECT (widget->object))
-			gtk_object_destroy (GTK_OBJECT (widget->object));
-		else 
-			g_object_unref (widget->object);
+		GladeProperty *property = GLADE_PROPERTY (widget->prop_refs->data);
+		glade_property_set (property, NULL);
 	}
 
+	/* We have to make sure properties release thier references on other widgets first 
+	 * hence the reset (for object properties) */
 	if (widget->properties)
 	{
+		g_list_foreach (widget->properties, (GFunc)reset_object_property, widget->project);
 		g_list_foreach (widget->properties, (GFunc)g_object_unref, NULL);
 		g_list_free (widget->properties);
 	}
+
+	/* Unparent all children */
+	if ((children = 
+	     glade_widget_get_children (widget)) != NULL)
+	{
+		for (list = children; list; list = list->next)
+		{
+			child = glade_widget_get_from_gobject (list->data);
+
+			if (child->internal == NULL)
+				glade_widget_remove_child (widget, child);
+		}
+		g_list_free (children);
+	}
+
+	/* 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);
 	
 	if (widget->packing_properties)
 	{
@@ -859,7 +890,7 @@ glade_widget_dispose (GObject *object)
 		g_list_foreach (widget->packing_actions, (GFunc)g_object_unref, NULL);
 		g_list_free (widget->packing_actions);
 	}
-	
+
 	G_OBJECT_CLASS (glade_widget_parent_class)->dispose (object);
 }
 
@@ -3336,42 +3367,46 @@ glade_widget_set_object (GladeWidget *gwidget, GObject *new_object)
 	GObject            *old_object;
 	
 	g_return_if_fail (GLADE_IS_WIDGET (gwidget));
-	g_return_if_fail (G_IS_OBJECT     (new_object));
-	g_return_if_fail (g_type_is_a (G_OBJECT_TYPE (new_object),
+	g_return_if_fail (new_object == NULL || 
+			  g_type_is_a (G_OBJECT_TYPE (new_object),
 				       gwidget->adaptor->type));
 
 	adaptor    = gwidget->adaptor;
 	old_object = gwidget->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;
-	
-	g_object_set_qdata (G_OBJECT (new_object), glade_widget_name_quark, gwidget);
 
-	if (g_type_is_a (gwidget->adaptor->type, GTK_TYPE_WIDGET))
+	if (new_object)
 	{
-		/* Disable any built-in DnD
-		 */
-		gtk_drag_dest_unset (GTK_WIDGET (new_object));
-		gtk_drag_source_unset (GTK_WIDGET (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;
+	
+		g_object_set_qdata (G_OBJECT (new_object), glade_widget_name_quark, gwidget);
 
-		/* Take care of drawing selection directly on widgets
-		 * for the time being
-		 */
-		glade_widget_connect_signal_handlers
-			(GTK_WIDGET(new_object),
-			 G_CALLBACK (glade_widget_event_private),
-			 gwidget);
+		if (g_type_is_a (gwidget->adaptor->type, GTK_TYPE_WIDGET))
+		{
+			/* Disable any built-in DnD
+			 */
+			gtk_drag_dest_unset (GTK_WIDGET (new_object));
+			gtk_drag_source_unset (GTK_WIDGET (new_object));
+			
+			/* Take care of drawing selection directly on widgets
+			 * for the time being
+			 */
+			glade_widget_connect_signal_handlers
+				(GTK_WIDGET(new_object),
+				 G_CALLBACK (glade_widget_event_private),
+				 gwidget);
+		}
 	}
 
 	/* Remove internal reference to old widget */
-	if (gwidget->internal == NULL && old_object) {
+	if (gwidget->internal == NULL && old_object) 
+	{
 		g_object_set_qdata (G_OBJECT (old_object), glade_widget_name_quark, NULL);
 		g_object_unref (G_OBJECT (old_object));
 	}
diff --git a/gladeui/glade-widget.h b/gladeui/glade-widget.h
index 3094d6d..bbc3f1d 100644
--- a/gladeui/glade-widget.h
+++ b/gladeui/glade-widget.h
@@ -23,7 +23,7 @@ typedef struct _GladeWidgetClass  GladeWidgetClass;
 
 struct _GladeWidget
 {
-	GObject parent_instance;
+	GInitiallyUnowned parent_instance;
 
 	GladeWidgetAdaptor *adaptor; /* An adaptor class for the object type */
 
@@ -117,7 +117,7 @@ struct _GladeWidget
 
 struct _GladeWidgetClass
 {
-	GObjectClass parent_class;
+	GInitiallyUnownedClass parent_class;
 
 	void         (*add_child)               (GladeWidget *, GladeWidget *, gboolean);
 	void         (*remove_child)            (GladeWidget *, GladeWidget *);
diff --git a/plugins/gtk+/glade-gtk.c b/plugins/gtk+/glade-gtk.c
index f2b145f..d8ac55a 100644
--- a/plugins/gtk+/glade-gtk.c
+++ b/plugins/gtk+/glade-gtk.c
@@ -3944,12 +3944,6 @@ glade_gtk_notebook_set_n_pages (GObject *object, const GValue *value)
 			if (old_size == 0 && new_size > 1)
 			{
 				gtab = glade_gtk_notebook_generate_tab (widget, position + 1);
-
-				/* Must tell the project that were adding a widget (so that
-				 * saving works properly & it appears in the inspector properly)
-				 */
-				glade_project_add_object (glade_widget_get_project (widget), 
-							  NULL, gtab->object);
 				
 				/* Must pass through GladeWidget api so that packing props
 				 * are correctly assigned.
@@ -3960,7 +3954,7 @@ glade_gtk_notebook_set_n_pages (GObject *object, const GValue *value)
 			{
 				GtkWidget *tab_placeholder = glade_placeholder_new ();
 
-				g_object_set_data (tab_placeholder, "special-child-type", "tab");
+				g_object_set_data (G_OBJECT (tab_placeholder), "special-child-type", "tab");
 
 				gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook), placeholder, 
 							    tab_placeholder);



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