[gnome-builder/wip/chergert/perspective] prefs: add template expantion for schema-id and path



commit d875cf41fd8c280b1267c5d54959b69bcc2c6810
Author: Christian Hergert <chergert redhat com>
Date:   Tue Nov 10 03:59:04 2015 -0800

    prefs: add template expantion for schema-id and path
    
    We will need to expand templates for subpages which could have a schema
    id or path defined from a mapping key. For example, to modify the settings
    for C, you might show "languages.id" page with a mapping of {id} to "c".
    
    When showing the subpage, we will ::connect() to the GSettings post-
    resolving the template.

 libide/preferences/ide-preferences-bin.c         |  340 ++++++++++++++--------
 libide/preferences/ide-preferences-bin.h         |    7 +-
 libide/preferences/ide-preferences-font-button.c |   46 ++--
 libide/preferences/ide-preferences-font-button.h |    2 +-
 libide/preferences/ide-preferences-spin-button.c |   63 +++--
 libide/preferences/ide-preferences-switch.c      |   46 ++--
 6 files changed, 312 insertions(+), 192 deletions(-)
---
diff --git a/libide/preferences/ide-preferences-bin.c b/libide/preferences/ide-preferences-bin.c
index 900d2e3..98615ee 100644
--- a/libide/preferences/ide-preferences-bin.c
+++ b/libide/preferences/ide-preferences-bin.c
@@ -16,6 +16,8 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <string.h>
+
 #include "ide-preferences-bin.h"
 
 typedef struct
@@ -45,6 +47,205 @@ enum {
 static GParamSpec *properties [LAST_PROP];
 static GHashTable *settings_cache;
 
+static gchar *
+ide_preferences_bin_expand (IdePreferencesBin *self,
+                            const gchar       *spec)
+{
+  IdePreferencesBinPrivate *priv = ide_preferences_bin_get_instance_private (self);
+  GHashTableIter iter;
+  const gchar *key;
+  const gchar *value;
+  gchar *expanded;
+
+  g_assert (IDE_IS_PREFERENCES_BIN (self));
+
+  if (spec == NULL)
+    return NULL;
+
+  expanded = g_strdup (spec);
+
+  if (priv->map == NULL)
+    goto validate;
+
+  g_hash_table_iter_init (&iter, priv->map);
+
+  while (g_hash_table_iter_next (&iter, (gpointer *)&key, (gpointer *)&value))
+    {
+      gchar *tmp = expanded;
+      gchar **split;
+
+      split = g_strsplit (tmp, key, 0);
+      expanded = g_strjoinv (value, split);
+
+      g_strfreev (split);
+      g_free (tmp);
+    }
+
+validate:
+  if (strchr (expanded, '{') != NULL)
+    {
+      g_free (expanded);
+      return NULL;
+    }
+
+  return expanded;
+}
+
+static void
+ide_preferences_bin_evict_settings (gpointer  data,
+                                          GObject  *where_object_was)
+{
+  g_assert (data != NULL);
+  g_assert (where_object_was != NULL);
+
+  g_hash_table_remove (settings_cache, (gchar *)data);
+}
+
+static void
+ide_preferences_bin_cache_settings (const gchar *hash_key,
+                                    GSettings   *settings)
+{
+  gchar *key;
+
+  g_assert (hash_key != NULL);
+  g_assert (G_IS_SETTINGS (settings));
+
+  key = g_strdup (hash_key);
+  g_hash_table_insert (settings_cache, key, settings);
+  g_object_weak_ref (G_OBJECT (settings), ide_preferences_bin_evict_settings, key);
+}
+
+static GSettings *
+ide_preferences_bin_get_settings (IdePreferencesBin *self)
+{
+  IdePreferencesBinPrivate *priv = ide_preferences_bin_get_instance_private (self);
+
+  g_return_val_if_fail (IDE_IS_PREFERENCES_BIN (self), NULL);
+
+  if (priv->settings == NULL)
+    {
+      g_autofree gchar *resolved_schema_id = NULL;
+      g_autofree gchar *resolved_path = NULL;
+      g_autofree gchar *hash_key = NULL;
+
+      resolved_schema_id = ide_preferences_bin_expand (self, priv->schema_id);
+      resolved_path = ide_preferences_bin_expand (self, priv->path);
+
+      if (resolved_schema_id == NULL)
+        return NULL;
+
+      if ((priv->path != NULL) && (resolved_path == NULL))
+        return NULL;
+
+      hash_key = g_strdup_printf ("%s|%s",
+                                  resolved_schema_id ?: "",
+                                  resolved_path ?: "");
+
+      if (!g_hash_table_contains (settings_cache, hash_key))
+        {
+          GSettingsSchemaSource *source;
+          GSettingsSchema *schema;
+
+          source = g_settings_schema_source_get_default ();
+          schema = g_settings_schema_source_lookup (source, resolved_schema_id, TRUE);
+
+          if (schema != NULL)
+            {
+              if (resolved_path)
+                priv->settings = g_settings_new_with_path (resolved_schema_id, resolved_path);
+              else
+                priv->settings = g_settings_new (resolved_schema_id);
+              ide_preferences_bin_cache_settings (hash_key, priv->settings);
+            }
+
+          g_clear_pointer (&schema, g_settings_schema_unref);
+        }
+      else
+        {
+          priv->settings = g_object_ref (g_hash_table_lookup (settings_cache, hash_key));
+        }
+
+      g_clear_pointer (&hash_key, g_free);
+      g_clear_pointer (&resolved_schema_id, g_free);
+      g_clear_pointer (&resolved_path, g_free);
+    }
+
+  return (priv->settings != NULL) ? g_object_ref (priv->settings) : NULL;
+}
+
+
+static void
+ide_preferences_bin_connect (IdePreferencesBin *self,
+                             GSettings         *settings)
+{
+  g_assert (IDE_IS_PREFERENCES_BIN (self));
+  g_assert (G_IS_SETTINGS (settings));
+
+  if (IDE_PREFERENCES_BIN_GET_CLASS (self)->connect != NULL)
+    IDE_PREFERENCES_BIN_GET_CLASS (self)->connect (self, settings);
+}
+
+static void
+ide_preferences_bin_disconnect (IdePreferencesBin *self,
+                                GSettings         *settings)
+{
+  g_assert (IDE_IS_PREFERENCES_BIN (self));
+  g_assert (G_IS_SETTINGS (settings));
+
+  if (IDE_PREFERENCES_BIN_GET_CLASS (self)->disconnect != NULL)
+    IDE_PREFERENCES_BIN_GET_CLASS (self)->disconnect (self, settings);
+}
+
+static void
+ide_preferences_bin_reload (IdePreferencesBin *self)
+{
+  IdePreferencesBinPrivate *priv = ide_preferences_bin_get_instance_private (self);
+  GSettings *settings;
+
+  g_assert (IDE_IS_PREFERENCES_BIN (self));
+
+  if (priv->settings != NULL)
+    {
+      ide_preferences_bin_disconnect (self, priv->settings);
+      g_clear_object (&priv->settings);
+    }
+
+  settings = ide_preferences_bin_get_settings (self);
+
+  if (settings != NULL)
+    {
+      ide_preferences_bin_connect (self, settings);
+      g_object_unref (settings);
+    }
+}
+
+static void
+ide_preferences_bin_constructed (GObject *object)
+{
+  IdePreferencesBin *self = (IdePreferencesBin *)object;
+
+  G_OBJECT_CLASS (ide_preferences_bin_parent_class)->constructed (object);
+
+  ide_preferences_bin_reload (self);
+}
+
+static void
+ide_preferences_bin_destroy (GtkWidget *widget)
+{
+  IdePreferencesBin *self = (IdePreferencesBin *)widget;
+  IdePreferencesBinPrivate *priv = ide_preferences_bin_get_instance_private (self);
+
+  g_assert (IDE_IS_PREFERENCES_BIN (self));
+
+  if (priv->settings != NULL)
+    {
+      ide_preferences_bin_disconnect (self, priv->settings);
+      g_clear_object (&priv->settings);
+    }
+
+  GTK_WIDGET_CLASS (ide_preferences_bin_parent_class)->destroy (widget);
+}
+
 static void
 ide_preferences_bin_finalize (GObject *object)
 {
@@ -62,9 +263,9 @@ ide_preferences_bin_finalize (GObject *object)
 
 static void
 ide_preferences_bin_get_property (GObject    *object,
-                                        guint       prop_id,
-                                        GValue     *value,
-                                        GParamSpec *pspec)
+                                  guint       prop_id,
+                                  GValue     *value,
+                                  GParamSpec *pspec)
 {
   IdePreferencesBin *self = IDE_PREFERENCES_BIN (object);
   IdePreferencesBinPrivate *priv = ide_preferences_bin_get_instance_private (self);
@@ -94,9 +295,9 @@ ide_preferences_bin_get_property (GObject    *object,
 
 static void
 ide_preferences_bin_set_property (GObject      *object,
-                                        guint         prop_id,
-                                        const GValue *value,
-                                        GParamSpec   *pspec)
+                                  guint         prop_id,
+                                  const GValue *value,
+                                  GParamSpec   *pspec)
 {
   IdePreferencesBin *self = IDE_PREFERENCES_BIN (object);
   IdePreferencesBinPrivate *priv = ide_preferences_bin_get_instance_private (self);
@@ -128,11 +329,15 @@ static void
 ide_preferences_bin_class_init (IdePreferencesBinClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
 
+  object_class->constructed = ide_preferences_bin_constructed;
   object_class->finalize = ide_preferences_bin_finalize;
   object_class->get_property = ide_preferences_bin_get_property;
   object_class->set_property = ide_preferences_bin_set_property;
 
+  widget_class->destroy = ide_preferences_bin_destroy;
+
   properties [PROP_KEYWORDS] =
     g_param_spec_string ("keywords",
                          "Keywords",
@@ -173,129 +378,9 @@ ide_preferences_bin_init (IdePreferencesBin *self)
 {
 }
 
-static gchar *
-ide_preferences_bin_expand (IdePreferencesBin *self,
-                                  const gchar             *spec)
-{
-  IdePreferencesBinPrivate *priv = ide_preferences_bin_get_instance_private (self);
-  GHashTableIter iter;
-  const gchar *key;
-  const gchar *value;
-  gchar *expanded;
-
-  g_assert (IDE_IS_PREFERENCES_BIN (self));
-
-  if (spec == NULL)
-    return NULL;
-
-  expanded = g_strdup (spec);
-
-  if (priv->map == NULL)
-    return expanded;
-
-  g_hash_table_iter_init (&iter, priv->map);
-
-  while (g_hash_table_iter_next (&iter, (gpointer *)&key, (gpointer *)&value))
-    {
-      gchar *tmp = expanded;
-      gchar **split;
-
-      split = g_strsplit (tmp, key, 0);
-      expanded = g_strjoinv (value, split);
-
-      g_strfreev (split);
-      g_free (tmp);
-    }
-
-  return expanded;
-}
-
-static void
-ide_preferences_bin_evict_settings (gpointer  data,
-                                          GObject  *where_object_was)
-{
-  g_assert (data != NULL);
-  g_assert (where_object_was != NULL);
-
-  g_hash_table_remove (settings_cache, (gchar *)data);
-}
-
-static void
-ide_preferences_bin_cache_settings (const gchar *hash_key,
-                                          GSettings   *settings)
-{
-  gchar *key;
-
-  g_assert (hash_key != NULL);
-  g_assert (G_IS_SETTINGS (settings));
-
-  key = g_strdup (hash_key);
-  g_hash_table_insert (settings_cache, key, settings);
-  g_object_weak_ref (G_OBJECT (settings), ide_preferences_bin_evict_settings, key);
-}
-
-/**
- * ide_preferences_bin_get_settings:
- *
- * Returns: (nullable) (transfer full): A #GSettings
- */
-GSettings *
-ide_preferences_bin_get_settings (IdePreferencesBin *self)
-{
-  IdePreferencesBinPrivate *priv = ide_preferences_bin_get_instance_private (self);
-
-  g_return_val_if_fail (IDE_IS_PREFERENCES_BIN (self), NULL);
-
-  if (priv->settings == NULL)
-    {
-      gchar *resolved_schema_id;
-      gchar *resolved_path;
-      gchar *hash_key;
-
-      if (priv->schema_id == NULL)
-        return NULL;
-
-      resolved_schema_id = ide_preferences_bin_expand (self, priv->schema_id);
-      resolved_path = ide_preferences_bin_expand (self, priv->path);
-      hash_key = g_strdup_printf ("%s|%s",
-                                  resolved_schema_id ?: "",
-                                  resolved_path ?: "");
-
-      if (!g_hash_table_contains (settings_cache, hash_key))
-        {
-          GSettingsSchemaSource *source;
-          GSettingsSchema *schema;
-
-          source = g_settings_schema_source_get_default ();
-          schema = g_settings_schema_source_lookup (source, resolved_schema_id, TRUE);
-
-          if (schema != NULL)
-            {
-              if (resolved_path)
-                priv->settings = g_settings_new_with_path (resolved_schema_id, resolved_path);
-              else
-                priv->settings = g_settings_new (resolved_schema_id);
-              ide_preferences_bin_cache_settings (hash_key, priv->settings);
-            }
-
-          g_clear_pointer (&schema, g_settings_schema_unref);
-        }
-      else
-        {
-          priv->settings = g_object_ref (g_hash_table_lookup (settings_cache, hash_key));
-        }
-
-      g_clear_pointer (&hash_key, g_free);
-      g_clear_pointer (&resolved_schema_id, g_free);
-      g_clear_pointer (&resolved_path, g_free);
-    }
-
-  return (priv->settings != NULL) ? g_object_ref (priv->settings) : NULL;
-}
-
 void
 _ide_preferences_bin_set_map (IdePreferencesBin *self,
-                                    GHashTable              *map)
+                              GHashTable        *map)
 {
   IdePreferencesBinPrivate *priv = ide_preferences_bin_get_instance_private (self);
 
@@ -305,5 +390,6 @@ _ide_preferences_bin_set_map (IdePreferencesBin *self,
     {
       g_clear_pointer (&priv->map, g_hash_table_unref);
       priv->map = map ? g_hash_table_ref (map) : NULL;
+      ide_preferences_bin_reload (self);
     }
 }
diff --git a/libide/preferences/ide-preferences-bin.h b/libide/preferences/ide-preferences-bin.h
index ceeeae6..bab0725 100644
--- a/libide/preferences/ide-preferences-bin.h
+++ b/libide/preferences/ide-preferences-bin.h
@@ -30,9 +30,12 @@ G_DECLARE_DERIVABLE_TYPE (IdePreferencesBin, ide_preferences_bin, IDE, PREFERENC
 struct _IdePreferencesBinClass
 {
   GtkBinClass parent_class;
-};
 
-GSettings *ide_preferences_bin_get_settings (IdePreferencesBin *self);
+  void (*connect)    (IdePreferencesBin *self,
+                      GSettings         *settings);
+  void (*disconnect) (IdePreferencesBin *self,
+                      GSettings         *settings);
+};
 
 G_END_DECLS
 
diff --git a/libide/preferences/ide-preferences-font-button.c 
b/libide/preferences/ide-preferences-font-button.c
index 70c02b1..3396b9b 100644
--- a/libide/preferences/ide-preferences-font-button.c
+++ b/libide/preferences/ide-preferences-font-button.c
@@ -22,6 +22,8 @@ struct _IdePreferencesFontButton
 {
   GtkBin                parent_instance;
 
+  gulong                handler;
+
   GSettings            *settings;
   gchar                *key;
 
@@ -103,33 +105,38 @@ ide_preferences_font_button_changed (IdePreferencesFontButton *self,
 }
 
 static void
-ide_preferences_font_button_constructed (GObject *object)
+ide_preferences_font_button_connect (IdePreferencesBin *bin,
+                                     GSettings         *settings)
 {
-  IdePreferencesFontButton *self = (IdePreferencesFontButton *)object;
+  IdePreferencesFontButton *self = (IdePreferencesFontButton *)bin;
   g_autofree gchar *signal_detail = NULL;
 
   g_assert (IDE_IS_PREFERENCES_FONT_BUTTON (self));
 
-  self->settings = ide_preferences_bin_get_settings (IDE_PREFERENCES_BIN (self));
+  signal_detail = g_strdup_printf ("changed::%s", self->key);
 
-  if (self->settings == NULL)
-    {
-      g_warning ("Failed to load settings for font button.");
-      goto chainup;
-    }
+  self->settings = g_object_ref (settings);
 
-  signal_detail = g_strdup_printf ("changed::%s", self->key);
+  self->handler =
+    g_signal_connect_object (settings,
+                             signal_detail,
+                             G_CALLBACK (ide_preferences_font_button_changed),
+                             self,
+                             G_CONNECT_SWAPPED);
 
-  g_signal_connect_object (self->settings,
-                           signal_detail,
-                           G_CALLBACK (ide_preferences_font_button_changed),
-                           self,
-                           G_CONNECT_SWAPPED);
+  ide_preferences_font_button_changed (self, self->key, settings);
+}
 
-  ide_preferences_font_button_changed (self, self->key, self->settings);
+static void
+ide_preferences_font_button_disconnect (IdePreferencesBin *bin,
+                                        GSettings         *settings)
+{
+  IdePreferencesFontButton *self = (IdePreferencesFontButton *)bin;
 
-chainup:
-  G_OBJECT_CLASS (ide_preferences_font_button_parent_class)->constructed (object);
+  g_assert (IDE_IS_PREFERENCES_FONT_BUTTON (self));
+
+  g_signal_handler_disconnect (settings, self->handler);
+  self->handler = 0;
 }
 
 static void
@@ -194,12 +201,15 @@ ide_preferences_font_button_class_init (IdePreferencesFontButtonClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+  IdePreferencesBinClass *bin_class = IDE_PREFERENCES_BIN_CLASS (klass);
 
-  object_class->constructed = ide_preferences_font_button_constructed;
   object_class->finalize = ide_preferences_font_button_finalize;
   object_class->get_property = ide_preferences_font_button_get_property;
   object_class->set_property = ide_preferences_font_button_set_property;
 
+  bin_class->connect = ide_preferences_font_button_connect;
+  bin_class->disconnect = ide_preferences_font_button_disconnect;
+
   signals [ACTIVATE] =
     g_signal_new_class_handler ("activate",
                                 G_TYPE_FROM_CLASS (klass),
diff --git a/libide/preferences/ide-preferences-font-button.h 
b/libide/preferences/ide-preferences-font-button.h
index 7c1648e..39d903c 100644
--- a/libide/preferences/ide-preferences-font-button.h
+++ b/libide/preferences/ide-preferences-font-button.h
@@ -25,7 +25,7 @@ G_BEGIN_DECLS
 
 #define IDE_TYPE_PREFERENCES_FONT_BUTTON (ide_preferences_font_button_get_type())
 
-G_DECLARE_FINAL_TYPE (IdePreferencesFontButton, ide_preferences_font_button, IDE, PREFERENCES_FONT_BUTTON, 
GtkBin)
+G_DECLARE_FINAL_TYPE (IdePreferencesFontButton, ide_preferences_font_button, IDE, PREFERENCES_FONT_BUTTON, 
IdePreferencesBin)
 
 G_END_DECLS
 
diff --git a/libide/preferences/ide-preferences-spin-button.c 
b/libide/preferences/ide-preferences-spin-button.c
index af909a3..5f7af7c 100644
--- a/libide/preferences/ide-preferences-spin-button.c
+++ b/libide/preferences/ide-preferences-spin-button.c
@@ -21,7 +21,9 @@
 
 struct _IdePreferencesSpinButton
 {
-  IdePreferencesBin  parent_instance;
+  IdePreferencesBin        parent_instance;
+
+  gulong                   handler;
 
   guint                    updating : 1;
 
@@ -163,9 +165,10 @@ ide_preferences_spin_button_setting_changed (IdePreferencesSpinButton *self,
 }
 
 static void
-ide_preferences_spin_button_constructed (GObject *object)
+ide_preferences_spin_button_connect (IdePreferencesBin *bin,
+                                     GSettings         *settings)
 {
-  IdePreferencesSpinButton *self = (IdePreferencesSpinButton *)object;
+  IdePreferencesSpinButton *self = (IdePreferencesSpinButton *)bin;
   GSettingsSchema *schema = NULL;
   GSettingsSchemaKey *key = NULL;
   GVariant *range = NULL;
@@ -179,13 +182,7 @@ ide_preferences_spin_button_constructed (GObject *object)
 
   g_assert (IDE_IS_PREFERENCES_SPIN_BUTTON (self));
 
-  self->settings = ide_preferences_bin_get_settings (IDE_PREFERENCES_BIN (self));
-
-  if (self->settings == NULL)
-    {
-      g_warning ("Failed to load settings for spin button");
-      goto chainup;
-    }
+  self->settings = g_object_ref (settings);
 
   g_object_get (self->settings, "settings-schema", &schema, NULL);
 
@@ -198,7 +195,7 @@ ide_preferences_spin_button_constructed (GObject *object)
   if (!ide_str_equal0 (type, "range") || (2 != g_variant_iter_init (&iter, values)))
     {
       gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
-      goto chainup;
+      goto cleanup;
     }
 
   lower = g_variant_iter_next_value (&iter);
@@ -211,23 +208,16 @@ ide_preferences_spin_button_constructed (GObject *object)
 
   signal_detail = g_strdup_printf ("changed::%s", self->key);
 
-  g_signal_connect_object (self->settings,
-                           signal_detail,
-                           G_CALLBACK (ide_preferences_spin_button_setting_changed),
-                           self,
-                           G_CONNECT_SWAPPED);
+  self->handler =
+    g_signal_connect_object (self->settings,
+                             signal_detail,
+                             G_CALLBACK (ide_preferences_spin_button_setting_changed),
+                             self,
+                             G_CONNECT_SWAPPED);
 
   ide_preferences_spin_button_setting_changed (self, self->key, self->settings);
 
-  g_signal_connect_object (self->spin_button,
-                           "notify::value",
-                           G_CALLBACK (ide_preferences_spin_button_value_changed),
-                           self,
-                           G_CONNECT_SWAPPED);
-
-chainup:
-  G_OBJECT_CLASS (ide_preferences_spin_button_parent_class)->constructed (object);
-
+cleanup:
   g_clear_pointer (&key, g_settings_schema_key_unref);
   g_clear_pointer (&type, g_free);
   g_clear_pointer (&signal_detail, g_free);
@@ -239,6 +229,18 @@ chainup:
 }
 
 static void
+ide_preferences_spin_button_disconnect (IdePreferencesBin *bin,
+                                        GSettings         *settings)
+{
+  IdePreferencesSpinButton *self = (IdePreferencesSpinButton *)bin;
+
+  g_assert (IDE_IS_PREFERENCES_SPIN_BUTTON (self));
+
+  g_signal_handler_disconnect (settings, self->handler);
+  self->handler = 0;
+}
+
+static void
 ide_preferences_spin_button_finalize (GObject *object)
 {
   IdePreferencesSpinButton *self = (IdePreferencesSpinButton *)object;
@@ -308,12 +310,15 @@ ide_preferences_spin_button_class_init (IdePreferencesSpinButtonClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+  IdePreferencesBinClass *bin_class = IDE_PREFERENCES_BIN_CLASS (klass);
 
-  object_class->constructed = ide_preferences_spin_button_constructed;
   object_class->finalize = ide_preferences_spin_button_finalize;
   object_class->get_property = ide_preferences_spin_button_get_property;
   object_class->set_property = ide_preferences_spin_button_set_property;
 
+  bin_class->connect = ide_preferences_spin_button_connect;
+  bin_class->disconnect = ide_preferences_spin_button_disconnect;
+
   signals [ACTIVATE] =
     g_signal_new_class_handler ("activate",
                                 G_TYPE_FROM_CLASS (klass),
@@ -365,4 +370,10 @@ ide_preferences_spin_button_init (IdePreferencesSpinButton *self)
                 "page-increment", 10.0,
                 "page-size", 10.0,
                 NULL);
+
+  g_signal_connect_object (self->spin_button,
+                           "notify::value",
+                           G_CALLBACK (ide_preferences_spin_button_value_changed),
+                           self,
+                           G_CONNECT_SWAPPED);
 }
diff --git a/libide/preferences/ide-preferences-switch.c b/libide/preferences/ide-preferences-switch.c
index df08a3e..04d8c6c 100644
--- a/libide/preferences/ide-preferences-switch.c
+++ b/libide/preferences/ide-preferences-switch.c
@@ -26,6 +26,8 @@ struct _IdePreferencesSwitch
   guint     is_radio : 1;
   guint     updating : 1;
 
+  gulong    handler;
+
   gchar     *key;
   GVariant  *target;
   GSettings *settings;
@@ -105,33 +107,38 @@ ide_preferences_switch_changed (IdePreferencesSwitch *self,
 }
 
 static void
-ide_preferences_switch_constructed (GObject *object)
+ide_preferences_switch_connect (IdePreferencesBin *bin,
+                                GSettings         *settings)
 {
-  IdePreferencesSwitch *self = (IdePreferencesSwitch *)object;
+  IdePreferencesSwitch *self = (IdePreferencesSwitch *)bin;
   g_autofree gchar *signal_detail = NULL;
 
   g_assert (IDE_IS_PREFERENCES_SWITCH (self));
 
-  self->settings = ide_preferences_bin_get_settings (IDE_PREFERENCES_BIN (self));
+  signal_detail = g_strdup_printf ("changed::%s", self->key);
 
-  if (self->settings == NULL)
-    {
-      g_warning ("Failed to load settings for switch");
-      goto chainup;
-    }
+  self->settings = g_object_ref (settings);
 
-  signal_detail = g_strdup_printf ("changed::%s", self->key);
+  self->handler =
+    g_signal_connect_object (settings,
+                             signal_detail,
+                             G_CALLBACK (ide_preferences_switch_changed),
+                             self,
+                             G_CONNECT_SWAPPED);
 
-  g_signal_connect_object (self->settings,
-                           signal_detail,
-                           G_CALLBACK (ide_preferences_switch_changed),
-                           self,
-                           G_CONNECT_SWAPPED);
+  ide_preferences_switch_changed (self, self->key, settings);
+}
 
-  ide_preferences_switch_changed (self, self->key, self->settings);
+static void
+ide_preferences_switch_disconnect (IdePreferencesBin *bin,
+                                   GSettings         *settings)
+{
+  IdePreferencesSwitch *self = (IdePreferencesSwitch *)bin;
 
-chainup:
-  G_OBJECT_CLASS (ide_preferences_switch_parent_class)->constructed (object);
+  g_assert (IDE_IS_PREFERENCES_SWITCH (self));
+
+  g_signal_handler_disconnect (settings, self->handler);
+  self->handler = 0;
 }
 
 static void
@@ -327,12 +334,15 @@ ide_preferences_switch_class_init (IdePreferencesSwitchClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+  IdePreferencesBinClass *bin_class = IDE_PREFERENCES_BIN_CLASS (klass);
 
-  object_class->constructed = ide_preferences_switch_constructed;
   object_class->finalize = ide_preferences_switch_finalize;
   object_class->get_property = ide_preferences_switch_get_property;
   object_class->set_property = ide_preferences_switch_set_property;
 
+  bin_class->connect = ide_preferences_switch_connect;
+  bin_class->disconnect = ide_preferences_switch_disconnect;
+
   signals [ACTIVATED] =
     g_signal_new_class_handler ("activated",
                                 G_TYPE_FROM_CLASS (klass),


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