[gnome-session] [capplet] Fix bug where editing an app and quickly exiting didn't work



commit a8014dc330b8b6e8b7e1028534a30bca588f3a25
Author: Vincent Untz <vuntz gnome org>
Date:   Tue Jun 23 23:24:15 2009 +0200

    [capplet] Fix bug where editing an app and quickly exiting didn't work
    
    Because of interesting references between all objects, we need to
    correctly unref objects in dispose. Else, saving GspApp objects didn't
    always work when exiting (user files weren't removed if identical to
    system ones) because the GspAppManager object was already finalized.

 capplet/gsm-properties-dialog.c |   13 ++++++++-----
 capplet/gsp-app-manager.c       |   19 ++++++++++++++++++-
 capplet/gsp-app.c               |   18 +++++++++++++++++-
 3 files changed, 43 insertions(+), 7 deletions(-)
---
diff --git a/capplet/gsm-properties-dialog.c b/capplet/gsm-properties-dialog.c
index 47c0f36..2ef1314 100644
--- a/capplet/gsm-properties-dialog.c
+++ b/capplet/gsm-properties-dialog.c
@@ -640,17 +640,20 @@ gsm_properties_dialog_dispose (GObject *object)
 
         dialog = GSM_PROPERTIES_DIALOG (object);
 
-        if (dialog->priv->manager != NULL) {
-                g_object_unref (dialog->priv->manager);
-                dialog->priv->manager = NULL;
-        }
-
         if (dialog->priv->xml != NULL) {
                 g_object_unref (dialog->priv->xml);
                 dialog->priv->xml = NULL;
         }
 
         G_OBJECT_CLASS (gsm_properties_dialog_parent_class)->dispose (object);
+
+        /* it's important to do this after chaining to the parent dispose
+         * method because we want to make sure the treeview has been disposed
+         * and removed all its references to GspApp objects */
+        if (dialog->priv->manager != NULL) {
+                g_object_unref (dialog->priv->manager);
+                dialog->priv->manager = NULL;
+        }
 }
 
 static void
diff --git a/capplet/gsp-app-manager.c b/capplet/gsp-app-manager.c
index 9ced072..bcd6d40 100644
--- a/capplet/gsp-app-manager.c
+++ b/capplet/gsp-app-manager.c
@@ -55,6 +55,7 @@ static guint gsp_app_manager_signals[LAST_SIGNAL] = { 0 };
 
 G_DEFINE_TYPE (GspAppManager, gsp_app_manager, G_TYPE_OBJECT)
 
+static void     gsp_app_manager_dispose      (GObject       *object);
 static void     gsp_app_manager_finalize     (GObject       *object);
 static void     _gsp_app_manager_app_unref   (GspApp        *app,
                                               GspAppManager *manager);
@@ -98,6 +99,7 @@ gsp_app_manager_class_init (GspAppManagerClass *class)
 {
         GObjectClass *gobject_class = G_OBJECT_CLASS (class);
 
+        gobject_class->dispose  = gsp_app_manager_dispose;
         gobject_class->finalize = gsp_app_manager_finalize;
 
         gsp_app_manager_signals[ADDED] =
@@ -134,7 +136,7 @@ gsp_app_manager_init (GspAppManager *manager)
 }
 
 static void
-gsp_app_manager_finalize (GObject *object)
+gsp_app_manager_dispose (GObject *object)
 {
         GspAppManager *manager;
 
@@ -143,11 +145,26 @@ gsp_app_manager_finalize (GObject *object)
 
         manager = GSP_APP_MANAGER (object);
 
+        /* we unref GspApp objects in dispose since they might need to
+         * reference us during their dispose/finalize */
         g_slist_foreach (manager->priv->apps,
                          (GFunc) _gsp_app_manager_app_unref, manager);
         g_slist_free (manager->priv->apps);
         manager->priv->apps = NULL;
 
+        G_OBJECT_CLASS (gsp_app_manager_parent_class)->dispose (object);
+}
+
+static void
+gsp_app_manager_finalize (GObject *object)
+{
+        GspAppManager *manager;
+
+        g_return_if_fail (object != NULL);
+        g_return_if_fail (GSP_IS_APP_MANAGER (object));
+
+        manager = GSP_APP_MANAGER (object);
+
         g_slist_foreach (manager->priv->dirs,
                          (GFunc) _gsp_xdg_dir_free, NULL);
         g_slist_free (manager->priv->dirs);
diff --git a/capplet/gsp-app.c b/capplet/gsp-app.c
index b9c8be6..759430a 100644
--- a/capplet/gsp-app.c
+++ b/capplet/gsp-app.c
@@ -89,6 +89,7 @@ static guint gsp_app_signals[LAST_SIGNAL] = { 0 };
 
 G_DEFINE_TYPE (GspApp, gsp_app, G_TYPE_OBJECT)
 
+static void     gsp_app_dispose  (GObject *object);
 static void     gsp_app_finalize (GObject *object);
 static gboolean _gsp_app_save    (gpointer data);
 
@@ -118,6 +119,7 @@ gsp_app_class_init (GspAppClass *class)
 {
         GObjectClass *gobject_class = G_OBJECT_CLASS (class);
 
+        gobject_class->dispose  = gsp_app_dispose;
         gobject_class->finalize = gsp_app_finalize;
 
         gsp_app_signals[CHANGED] =
@@ -200,7 +202,7 @@ _gsp_app_free_reusable_data (GspApp *app)
 }
 
 static void
-gsp_app_finalize (GObject *object)
+gsp_app_dispose (GObject *object)
 {
         GspApp *app;
 
@@ -209,6 +211,7 @@ gsp_app_finalize (GObject *object)
 
         app = GSP_APP (object);
 
+        /* we save in dispose since we might need to reference GspAppManager */
         if (app->priv->save_timeout) {
                 g_source_remove (app->priv->save_timeout);
                 app->priv->save_timeout = 0;
@@ -217,6 +220,19 @@ gsp_app_finalize (GObject *object)
                 _gsp_app_save (app);
         }
 
+        G_OBJECT_CLASS (gsp_app_parent_class)->dispose (object);
+}
+
+static void
+gsp_app_finalize (GObject *object)
+{
+        GspApp *app;
+
+        g_return_if_fail (object != NULL);
+        g_return_if_fail (GSP_IS_APP (object));
+
+        app = GSP_APP (object);
+
         if (app->priv->basename) {
                 g_free (app->priv->basename);
                 app->priv->basename = NULL;



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