[glib] Bug 622128 - retry with default for failed mapping



commit 7cdc592ae478b71a66aa1541b81588b5b200e5f2
Author: Ryan Lortie <desrt desrt ca>
Date:   Fri Jun 25 10:52:32 2010 -0400

    Bug 622128 - retry with default for failed mapping
    
    Hold the GSettingsKeyInfo as part of the binding structure to save work
    on each get/set.  Use our copy of this structure to call the internal
    get/set APIs.  Give more descriptive error messages in the case of
    invalid data on sets and retry using the translated default then schema
    default value in case of failure to map on reads.

 gio/gsettings.c |  137 ++++++++++++++++++++++++++++++++++---------------------
 1 files changed, 85 insertions(+), 52 deletions(-)
---
diff --git a/gio/gsettings.c b/gio/gsettings.c
index 157edd3..b517237 100644
--- a/gio/gsettings.c
+++ b/gio/gsettings.c
@@ -866,9 +866,8 @@ g_settings_get_key_info (GSettingsKeyInfo *info,
 
   info->default_value = g_variant_iter_next_value (iter);
   info->type = g_variant_get_type (info->default_value);
-  info->schema = settings->priv->schema;
-  info->settings = settings;
-  info->key = key;
+  info->settings = g_object_ref (settings);
+  info->key = g_intern_string (key);
 
   while (g_variant_iter_next (iter, "(y*)", &code, &data))
     {
@@ -914,6 +913,7 @@ g_settings_free_key_info (GSettingsKeyInfo *info)
     g_variant_unref (info->maximum);
 
   g_variant_unref (info->default_value);
+  g_object_unref (info->settings);
 }
 
 static gboolean
@@ -1054,7 +1054,7 @@ g_settings_get_translated_default (GSettingsKeyInfo *info)
     /* translation not requested for this key */
     return NULL;
 
-  domain = g_settings_schema_get_gettext_domain (info->schema);
+  domain = g_settings_schema_get_gettext_domain (info->settings->priv->schema);
 
   if (info->lc_char == 't')
     translated = g_dcgettext (domain, info->unparsed, LC_TIME);
@@ -1890,7 +1890,7 @@ g_settings_list_keys (GSettings *settings)
 /* Binding {{{1 */
 typedef struct
 {
-  GSettings *settings;
+  GSettingsKeyInfo info;
   GObject *object;
 
   GSettingsBindGetMapping get_mapping;
@@ -1902,8 +1902,6 @@ typedef struct
   guint property_handler_id;
   const GParamSpec *property;
   guint key_handler_id;
-  GVariantType *type;
-  const gchar *key;
 
   /* prevent recursion */
   gboolean running;
@@ -1917,11 +1915,11 @@ g_settings_binding_free (gpointer data)
   g_assert (!binding->running);
 
   if (binding->writable_handler_id)
-    g_signal_handler_disconnect (binding->settings,
+    g_signal_handler_disconnect (binding->info.settings,
                                  binding->writable_handler_id);
 
   if (binding->key_handler_id)
-    g_signal_handler_disconnect (binding->settings,
+    g_signal_handler_disconnect (binding->info.settings,
                                  binding->key_handler_id);
 
   if (g_signal_handler_is_connected (binding->object,
@@ -1929,8 +1927,7 @@ g_settings_binding_free (gpointer data)
   g_signal_handler_disconnect (binding->object,
                                binding->property_handler_id);
 
-  g_variant_type_free (binding->type);
-  g_object_unref (binding->settings);
+  g_settings_free_key_info (&binding->info);
 
   if (binding->destroy)
     binding->destroy (binding->user_data);
@@ -1960,8 +1957,8 @@ g_settings_binding_key_changed (GSettings   *settings,
   GValue value = { 0, };
   GVariant *variant;
 
-  g_assert (settings == binding->settings);
-  g_assert (key == binding->key);
+  g_assert (settings == binding->info.settings);
+  g_assert (key == binding->info.key);
 
   if (binding->running)
     return;
@@ -1969,11 +1966,42 @@ g_settings_binding_key_changed (GSettings   *settings,
   binding->running = TRUE;
 
   g_value_init (&value, binding->property->value_type);
-  variant = g_settings_get_value (settings, key);
-  if (binding->get_mapping (&value, variant, binding->user_data))
-    g_object_set_property (binding->object,
-                           binding->property->name,
-                           &value);
+
+  variant = g_settings_read_from_backend (&binding->info);
+  if (variant && !binding->get_mapping (&value, variant, binding->user_data))
+    {
+      /* silently ignore errors in the user's config database */
+      g_variant_unref (variant);
+      variant = NULL;
+    }
+
+  if (variant == NULL)
+    {
+      variant = g_settings_get_translated_default (&binding->info);
+      if (variant &&
+          !binding->get_mapping (&value, variant, binding->user_data))
+        {
+          /* flag translation errors with a warning */
+          g_warning ("Translated default `%s' for key `%s' in schema `%s' "
+                     "was rejected by the binding mapping function",
+                     binding->info.unparsed, binding->info.key,
+                     binding->info.settings->priv->schema_name);
+          g_variant_unref (variant);
+          variant = NULL;
+        }
+    }
+
+  if (variant == NULL)
+    {
+      variant = g_variant_ref (binding->info.default_value);
+      if (!binding->get_mapping (&value, variant, binding->user_data))
+        g_error ("The schema default value for key `%s' in schema `%s' "
+                 "was rejected by the binding mapping function.",
+                 binding->info.key,
+                 binding->info.settings->priv->schema_name);
+    }
+
+  g_object_set_property (binding->object, binding->property->name, &value);
   g_variant_unref (variant);
   g_value_unset (&value);
 
@@ -1999,12 +2027,34 @@ g_settings_binding_property_changed (GObject          *object,
 
   g_value_init (&value, pspec->value_type);
   g_object_get_property (object, pspec->name, &value);
-  if ((variant = binding->set_mapping (&value, binding->type,
+  if ((variant = binding->set_mapping (&value, binding->info.type,
                                        binding->user_data)))
     {
-      g_settings_set_value (binding->settings,
-                            binding->key,
-                            g_variant_ref_sink (variant));
+      if (g_variant_is_floating (variant))
+        g_variant_ref_sink (variant);
+
+      if (!g_settings_type_check (&binding->info, variant))
+        {
+          g_critical ("binding mapping function for key `%s' returned "
+                      "GVariant of type `%s' when type `%s' was requested",
+                      binding->info.key, g_variant_get_type_string (variant),
+                      g_variant_type_dup_string (binding->info.type));
+          return;
+        }
+
+      if (!g_settings_range_check (&binding->info, variant))
+        {
+          g_critical ("GObject property `%s' on a `%s' object is out of "
+                      "schema-specified range for key `%s' of `%s': %s",
+                      binding->property->name,
+                      g_type_name (binding->property->owner_type),
+                      binding->info.key,
+                      binding->info.settings->priv->schema_name,
+                      g_variant_print (variant, TRUE));
+          return;
+        }
+
+      g_settings_write_to_backend (&binding->info, variant);
       g_variant_unref (variant);
     }
   g_value_unset (&value);
@@ -2102,9 +2152,8 @@ g_settings_bind_with_mapping (GSettings               *settings,
   objectclass = G_OBJECT_GET_CLASS (object);
 
   binding = g_slice_new0 (GSettingsBinding);
-  binding->settings = g_object_ref (settings);
+  g_settings_get_key_info (&binding->info, settings, key);
   binding->object = object;
-  binding->key = g_intern_string (key);
   binding->property = g_object_class_find_property (objectclass, property);
   binding->user_data = user_data;
   binding->destroy = destroy;
@@ -2121,47 +2170,31 @@ g_settings_bind_with_mapping (GSettings               *settings,
       return;
     }
 
-  if ((flags & G_SETTINGS_BIND_GET) && (binding->property->flags & G_PARAM_WRITABLE) == 0)
+  if ((flags & G_SETTINGS_BIND_GET) &&
+      (binding->property->flags & G_PARAM_WRITABLE) == 0)
     {
-      g_critical ("g_settings_bind: property '%s' on class '%s' is not writable",
-                  property, G_OBJECT_TYPE_NAME (object));
-      return;
-    }
-  if ((flags & G_SETTINGS_BIND_SET) && (binding->property->flags & G_PARAM_READABLE) == 0)
-    {
-      g_critical ("g_settings_bind: property '%s' on class '%s' is not readable",
-                  property, G_OBJECT_TYPE_NAME (object));
+      g_critical ("g_settings_bind: property '%s' on class '%s' is not "
+                  "writable", property, G_OBJECT_TYPE_NAME (object));
       return;
     }
-
-  {
-    GVariantIter *iter;
-    GVariant *value;
-
-    iter = g_settings_schema_get_value (settings->priv->schema, key);
-    value = g_variant_iter_next_value (iter);
-    binding->type = g_variant_type_copy (g_variant_get_type (value));
-    g_variant_iter_free (iter);
-    g_variant_unref (value);
-  }
-
-  if (binding->type == NULL)
+  if ((flags & G_SETTINGS_BIND_SET) &&
+      (binding->property->flags & G_PARAM_READABLE) == 0)
     {
-      g_critical ("g_settings_bind: no key '%s' on schema '%s'",
-                  key, settings->priv->schema_name);
+      g_critical ("g_settings_bind: property '%s' on class '%s' is not "
+                  "readable", property, G_OBJECT_TYPE_NAME (object));
       return;
     }
 
   if (((get_mapping == NULL && (flags & G_SETTINGS_BIND_GET)) ||
        (set_mapping == NULL && (flags & G_SETTINGS_BIND_SET))) &&
       !g_settings_mapping_is_compatible (binding->property->value_type,
-                                         binding->type))
+                                         binding->info.type))
     {
       g_critical ("g_settings_bind: property '%s' on class '%s' has type "
                   "'%s' which is not compatible with type '%s' of key '%s' "
                   "on schema '%s'", property, G_OBJECT_TYPE_NAME (object),
                   g_type_name (binding->property->value_type),
-                  g_variant_type_dup_string (binding->type), key,
+                  g_variant_type_dup_string (binding->info.type), key,
                   settings->priv->schema_name);
       return;
     }
@@ -2175,7 +2208,7 @@ g_settings_bind_with_mapping (GSettings               *settings,
 
       if (sensitive && sensitive->value_type == G_TYPE_BOOLEAN &&
           (sensitive->flags & G_PARAM_WRITABLE))
-        g_settings_bind_writable (settings, binding->key,
+        g_settings_bind_writable (settings, binding->info.key,
                                   object, "sensitive", FALSE);
     }
 
@@ -2206,7 +2239,7 @@ g_settings_bind_with_mapping (GSettings               *settings,
           g_free (detailed_signal);
         }
 
-      g_settings_binding_key_changed (settings, binding->key, binding);
+      g_settings_binding_key_changed (settings, binding->info.key, binding);
     }
 
   binding_quark = g_settings_binding_quark (property);



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