[glade] GladeProject: cleanup dispose



commit 7aa34400724a7b4692af22b4a669a6a41395f62b
Author: Juan Pablo Ugarte <juanpablougarte gmail com>
Date:   Wed Aug 5 19:32:32 2020 -0300

    GladeProject: cleanup dispose
    
    GladeAdaptorChooserWidget: use g_object_add_weak_pointer() instead of
    g_object_weak_ref() and unset project on dispose.
    
    GladeDesignLayout, GladeDesignView: use g_object_add_weak_pointer()
    
    GladeEditable: fix project signal disconnect issue

 gladeui/glade-adaptor-chooser-widget.c |  28 +++++----
 gladeui/glade-design-layout.c          |  36 +++++++-----
 gladeui/glade-design-view.c            |   6 +-
 gladeui/glade-editable.c               |   6 +-
 gladeui/glade-project.c                | 101 ++++++++++++++++++---------------
 5 files changed, 96 insertions(+), 81 deletions(-)
---
diff --git a/gladeui/glade-adaptor-chooser-widget.c b/gladeui/glade-adaptor-chooser-widget.c
index cdfa59422..545e86856 100644
--- a/gladeui/glade-adaptor-chooser-widget.c
+++ b/gladeui/glade-adaptor-chooser-widget.c
@@ -89,13 +89,20 @@ _glade_adaptor_chooser_widget_init (_GladeAdaptorChooserWidget *chooser)
   gtk_widget_init_template (GTK_WIDGET (chooser));
 }
 
+static void
+_glade_adaptor_chooser_widget_dispose (GObject *object)
+{
+  _glade_adaptor_chooser_widget_set_project (GLADE_ADAPTOR_CHOOSER_WIDGET (object), NULL);
+
+  G_OBJECT_CLASS (_glade_adaptor_chooser_widget_parent_class)->dispose (object);
+}
+
 static void
 _glade_adaptor_chooser_widget_finalize (GObject *object)
 {
   _GladeAdaptorChooserWidgetPrivate *priv = GET_PRIVATE (object);
 
   g_clear_pointer (&priv->search_text, g_free);
-  g_clear_object (&priv->project);
 
   G_OBJECT_CLASS (_glade_adaptor_chooser_widget_parent_class)->finalize (object);
 }
@@ -513,6 +520,7 @@ _glade_adaptor_chooser_widget_class_init (_GladeAdaptorChooserWidgetClass *klass
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
 
+  object_class->dispose = _glade_adaptor_chooser_widget_dispose;
   object_class->finalize = _glade_adaptor_chooser_widget_finalize;
   object_class->set_property = _glade_adaptor_chooser_widget_set_property;
   object_class->get_property = _glade_adaptor_chooser_widget_get_property;
@@ -574,15 +582,6 @@ _glade_adaptor_chooser_widget_new (_GladeAdaptorChooserWidgetFlags flags, GladeP
                                    NULL));
 }
 
-static void
-on_project_weak_notify (gpointer data, GObject *project)
-{
-  _GladeAdaptorChooserWidget *chooser = data;
-  _GladeAdaptorChooserWidgetPrivate *priv = GET_PRIVATE (chooser);
-
-  priv->project = NULL;
-}
-
 void
 _glade_adaptor_chooser_widget_set_project (_GladeAdaptorChooserWidget *chooser,
                                            GladeProject               *project)
@@ -594,18 +593,17 @@ _glade_adaptor_chooser_widget_set_project (_GladeAdaptorChooserWidget *chooser,
 
   if (priv->project)
     {
-      g_object_weak_unref (G_OBJECT (priv->project), on_project_weak_notify, chooser);
+      g_object_remove_weak_pointer (G_OBJECT (priv->project), (gpointer *) &priv->project);
       priv->project = NULL;
     }
 
   if (project)
     {
       priv->project = project;
-      g_object_weak_ref (G_OBJECT (project), on_project_weak_notify, chooser);
-    }
+      g_object_add_weak_pointer (G_OBJECT (project), (gpointer *) &priv->project);
 
-
-  gtk_tree_model_filter_refilter (priv->treemodelfilter);
+      gtk_tree_model_filter_refilter (priv->treemodelfilter);
+    }
 }
 
 void
diff --git a/gladeui/glade-design-layout.c b/gladeui/glade-design-layout.c
index edccdb76b..5fec0d6ff 100644
--- a/gladeui/glade-design-layout.c
+++ b/gladeui/glade-design-layout.c
@@ -1841,13 +1841,7 @@ glade_design_layout_set_property (GObject *object,
   switch (prop_id)
     {
       case PROP_DESIGN_VIEW:
-        {
-          priv->view = GLADE_DESIGN_VIEW (g_value_get_object (value));
-          priv->project = glade_design_view_get_project (priv->view);
-          g_signal_connect (priv->project, "notify::pointer-mode",
-                            G_CALLBACK (on_pointer_mode_notify),
-                            GLADE_DESIGN_LAYOUT (object));
-        }
+        priv->view = GLADE_DESIGN_VIEW (g_value_get_object (value));
         break;
 
       default:
@@ -1907,8 +1901,15 @@ glade_design_layout_constructor (GType                  type,
   self = GLADE_DESIGN_LAYOUT (object);
   priv = glade_design_layout_get_instance_private (self);
 
-  g_signal_connect (priv->project,
-                    "selection-changed",
+  /* Keep a weak reference to project */
+  priv->project = glade_design_view_get_project (priv->view);
+  g_object_add_weak_pointer (G_OBJECT (priv->project), (gpointer *) &priv->project);
+
+  g_signal_connect (priv->project, "notify::pointer-mode",
+                    G_CALLBACK (on_pointer_mode_notify),
+                    self);
+
+  g_signal_connect (priv->project, "selection-changed",
                     G_CALLBACK (on_project_selection_changed),
                     self);
 
@@ -1941,12 +1942,17 @@ glade_design_layout_finalize (GObject *object)
   g_clear_object (&priv->default_context);
   g_clear_object (&priv->drag_dest);
   
-  g_signal_handlers_disconnect_by_func (priv->project,
-                                        on_project_selection_changed,
-                                        layout);
-  g_signal_handlers_disconnect_by_func (priv->project,
-                                        on_pointer_mode_notify,
-                                        layout);
+  if (priv->project)
+    {
+      g_signal_handlers_disconnect_by_func (priv->project,
+                                            on_project_selection_changed,
+                                            layout);
+      g_signal_handlers_disconnect_by_func (priv->project,
+                                            on_pointer_mode_notify,
+                                            layout);
+
+      priv->project = NULL;
+    }
 
   G_OBJECT_CLASS (glade_design_layout_parent_class)->finalize (object);
 }
diff --git a/gladeui/glade-design-view.c b/gladeui/glade-design-view.c
index da24037ef..82887ac59 100644
--- a/gladeui/glade-design-view.c
+++ b/gladeui/glade-design-view.c
@@ -252,19 +252,23 @@ glade_design_view_set_project (GladeDesignView *view, GladeProject *project)
 
   if (priv->project)
     {
+      g_object_remove_weak_pointer (G_OBJECT (priv->project), (gpointer *) &priv->project);
+
       g_signal_handlers_disconnect_by_data (priv->project, view);
       g_signal_handlers_disconnect_by_data (priv->project, priv->scrolled_window);
 
       g_object_set_data (G_OBJECT (priv->project), GLADE_DESIGN_VIEW_KEY, NULL);
     }
 
-  g_set_object (&priv->project, project);
+  priv->project = project;
 
   if (!project)
     return;
 
   g_assert (GLADE_IS_PROJECT (project));
 
+  g_object_add_weak_pointer (G_OBJECT (project), (gpointer *) &priv->project);
+
   g_signal_connect (project, "add-widget",
                     G_CALLBACK (on_project_add_widget), view);
   g_signal_connect (project, "remove-widget",
diff --git a/gladeui/glade-editable.c b/gladeui/glade-editable.c
index de345eec7..43458955a 100644
--- a/gladeui/glade-editable.c
+++ b/gladeui/glade-editable.c
@@ -79,7 +79,7 @@ glade_editable_load_default (GladeEditable  *editable,
 
   if (old_widget != widget)
     {
-      if (old_widget)
+      if (old_project)
         {
           g_signal_handlers_disconnect_by_func (old_project, G_CALLBACK (project_changed), editable);
           g_signal_handlers_disconnect_by_func (old_project, G_CALLBACK (project_closed), editable);
@@ -95,9 +95,9 @@ glade_editable_load_default (GladeEditable  *editable,
           g_object_set_qdata (G_OBJECT (editable), glade_editable_widget_quark, widget);
           g_object_set_qdata (G_OBJECT (editable), glade_editable_project_quark, project);
 
-          g_signal_connect (project, "changed", 
+          g_signal_connect (project, "changed",
                             G_CALLBACK (project_changed), editable);
-          g_signal_connect (project, "close", 
+          g_signal_connect (project, "close",
                             G_CALLBACK (project_closed), editable);
         }
     }
diff --git a/gladeui/glade-project.c b/gladeui/glade-project.c
index 94505b9ee..6766b4190 100644
--- a/gladeui/glade-project.c
+++ b/gladeui/glade-project.c
@@ -255,7 +255,29 @@ glade_project_dispose (GObject *object)
   /* Emit close signal */
   g_signal_emit (object, glade_project_signals[CLOSE], 0);
 
-  gtk_widget_destroy (priv->prefs_dialog);
+  /* Disconnect from model */
+#define MODEL_DISCONNECT(func) g_signal_handlers_disconnect_by_func (priv->model, G_CALLBACK (func), project)
+  MODEL_DISCONNECT (gtk_tree_model_row_changed);
+  MODEL_DISCONNECT (gtk_tree_model_row_inserted);
+  MODEL_DISCONNECT (gtk_tree_model_row_has_child_toggled);
+  MODEL_DISCONNECT (gtk_tree_model_row_deleted);
+  MODEL_DISCONNECT (gtk_tree_model_rows_reordered);
+
+  /* Destroy preferences dialog */
+  g_clear_pointer (&priv->prefs_dialog, gtk_widget_destroy);
+
+  /* Clear selection */
+  g_clear_pointer (&priv->selection, g_list_free);
+  g_clear_handle_id (&priv->selection_changed_id,  g_source_remove);
+
+  /* Clear undo/redo stack */
+  g_clear_pointer (&priv->undo_stack, glade_project_list_unref);
+
+  /* NOTE: prev_redo_item and first_modification always point to undo_stack
+   * So we should never try to free it
+   */
+  priv->prev_redo_item = NULL;
+  priv->first_modification = NULL;
 
   /* Destroy running previews */
   if (priv->previews)
@@ -264,17 +286,8 @@ glade_project_dispose (GObject *object)
       priv->previews = NULL;
     }
 
-  if (priv->selection_changed_id > 0)
-    priv->selection_changed_id = 
-      (g_source_remove (priv->selection_changed_id), 0);
-
-  glade_project_selection_clear (project, TRUE);
-
   g_clear_object (&priv->css_provider);
   g_clear_object (&priv->css_monitor);
-  
-  glade_project_list_unref (priv->undo_stack);
-  priv->undo_stack = NULL;
 
   /* Remove objects from the project */
   while (priv->tree)
@@ -283,11 +296,11 @@ glade_project_dispose (GObject *object)
 
       glade_project_remove_object (project, toplevel);
 
-      /* NOTE: Due to Gtk+ keeping a reference to the window internally,
-       * gtk_window_new() does not return a reference to the caller.
-       * To delete a GtkWindow, call gtk_widget_destroy().
+      /*
+       * FIXME: GladeWidgets are leaked so this is a workaround to make sure
+       * at least the runtime widgets (including windows) are destroyed!
        */
-      if (GTK_IS_WINDOW (toplevel))
+      if (GTK_IS_WIDGET (toplevel))
         gtk_widget_destroy (GTK_WIDGET (toplevel));
     }
 
@@ -296,6 +309,7 @@ glade_project_dispose (GObject *object)
 
   g_assert (priv->tree == NULL);
   g_assert (priv->objects == NULL);
+  g_assert (gtk_tree_model_iter_n_children (priv->model, NULL) == 0);
 
   if (priv->unknown_catalogs)
     {
@@ -313,7 +327,7 @@ glade_project_dispose (GObject *object)
     }
 
   g_object_unref (priv->model);
-  
+
   G_OBJECT_CLASS (glade_project_parent_class)->dispose (object);
 }
 
@@ -1662,7 +1676,7 @@ glade_project_read_comment_properties (GladeProject *project,
                                        GladeXmlNode *root_node)
 {
   GladeProjectPrivate *priv = project->priv;
-  gchar *license, *name, *description, *copyright, *authors;
+  g_autofree gchar *license = NULL, *name = NULL, *description = NULL, *copyright = NULL, *authors = NULL;
   GladeXmlNode *node;
 
   license = name = description = copyright = authors = NULL;
@@ -1706,17 +1720,13 @@ glade_project_read_comment_properties (GladeProject *project,
       g_free (val);
     }
 
-  _glade_project_properties_set_license_data (GLADE_PROJECT_PROPERTIES (priv->prefs_dialog),
-                                              license,
-                                              name,
-                                              description,
-                                              copyright,
-                                              authors);
-  g_free (license);
-  g_free (name);
-  g_free (description);
-  g_free (copyright);
-  g_free (authors);
+  if (priv->prefs_dialog)
+    _glade_project_properties_set_license_data (GLADE_PROJECT_PROPERTIES (priv->prefs_dialog),
+                                                license,
+                                                name,
+                                                description,
+                                                copyright,
+                                                authors);
 }
 
 static inline void
@@ -2210,7 +2220,9 @@ glade_project_update_properties_title (GladeProject *project)
   /* Update prefs dialogs here... */
   name = glade_project_get_name (project);
   title = g_strdup_printf (_("%s document properties"), name);
-  gtk_window_set_title (GTK_WINDOW (project->priv->prefs_dialog), title);
+
+  if (project->priv->prefs_dialog)
+    gtk_window_set_title (GTK_WINDOW (project->priv->prefs_dialog), title);
   g_free (title);
   g_free (name); 
 }
@@ -2392,7 +2404,10 @@ glade_project_write_license_data (GladeProject    *project,
                                   GladeXmlContext *context,
                                   GladeXmlNode    *root)
 {
-  gchar *license, *name, *description, *copyright, *authors;
+  g_autofree gchar *license = NULL, *name = NULL, *description = NULL, *copyright = NULL, *authors = NULL;
+
+  if (!project->priv->prefs_dialog)
+    return;
   
   _glade_project_properties_get_license_data (GLADE_PROJECT_PROPERTIES (project->priv->prefs_dialog),
                                               &license,
@@ -2401,9 +2416,6 @@ glade_project_write_license_data (GladeProject    *project,
                                               &copyright,
                                               &authors);
 
-  if (!license)
-    return;
-  
   glade_project_write_comment_property (project, context, root,
                                         "interface-license-type",
                                         license);
@@ -2419,12 +2431,6 @@ glade_project_write_license_data (GladeProject    *project,
   glade_project_write_comment_property (project, context, root,
                                         "interface-authors",
                                         authors);
-
-  g_free (license);
-  g_free (name);
-  g_free (description);
-  g_free (copyright);
-  g_free (authors);
 }
 
 static gint
@@ -4410,17 +4416,16 @@ glade_project_selection_changed (GladeProject *project)
                  glade_project_signals[SELECTION_CHANGED], 0);
 
   /* Cancel any idle we have */
-  if (project->priv->selection_changed_id > 0)
-    project->priv->selection_changed_id = 
-      (g_source_remove (project->priv->selection_changed_id), 0);
+  g_clear_handle_id (&project->priv->selection_changed_id,  g_source_remove);
 }
 
 static gboolean
-selection_change_idle (GladeProject *project)
+selection_change_idle (gpointer data)
 {
+  GladeProject *project = data;
   project->priv->selection_changed_id = 0;
   glade_project_selection_changed (project);
-  return FALSE;
+  return G_SOURCE_REMOVE;
 }
 
 void
@@ -4428,9 +4433,10 @@ glade_project_queue_selection_changed (GladeProject *project)
 {
   g_return_if_fail (GLADE_IS_PROJECT (project));
 
-  if (project->priv->selection_changed_id == 0)
-    project->priv->selection_changed_id = 
-      g_idle_add ((GSourceFunc) selection_change_idle, project);
+  if (project->priv->selection_changed_id)
+    return;
+
+  project->priv->selection_changed_id = g_idle_add (selection_change_idle, project);
 }
 
 static void
@@ -5025,7 +5031,8 @@ glade_project_properties (GladeProject *project)
 {
   g_return_if_fail (GLADE_IS_PROJECT (project));
 
-  gtk_window_present (GTK_WINDOW (project->priv->prefs_dialog));
+  if (project->priv->prefs_dialog)
+    gtk_window_present (GTK_WINDOW (project->priv->prefs_dialog));
 }
 
 gchar *


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