diff --git a/gio/gsettingsbackend.c b/gio/gsettingsbackend.c index e33d479..cbf7221 100644 --- a/gio/gsettingsbackend.c +++ b/gio/gsettingsbackend.c @@ -19,10 +19,19 @@ #include "gioalias.h" +struct _GSettingsBackendPrivate +{ + gchar *context; +}; + G_DEFINE_ABSTRACT_TYPE (GSettingsBackend, g_settings_backend, G_TYPE_OBJECT) static guint changed_signal; +enum { + PROP_CONTEXT +}; + /** * SECTION:gsettingsbackend * @short_description: an interface for settings backend implementations @@ -265,8 +274,64 @@ g_settings_backend_subscribe (GSettingsBackend *backend, } static void +g_settings_backend_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GSettingsBackend *backend; + + switch (prop_id) + { + case PROP_CONTEXT: + backend->priv->context = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +g_settings_backend_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GSettingsBackend *backend; + + switch (prop_id) + { + case PROP_CONTEXT: + g_value_set_string (value, backend->priv->context); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +g_settings_backend_finalize (GObject *object) +{ + GSettingsBackend *backend = G_SETTINGS_BACKEND (object); + + g_free (backend->priv->context); + + G_OBJECT_CLASS (g_settings_backend_parent_class)->finalize (object); +} + +static void g_settings_backend_class_init (GSettingsBackendClass *class) { + GObjectClass *gobject_class = G_OBJECT_CLASS (class); + + gobject_class->get_property = g_settings_backend_get_property; + gobject_class->set_property = g_settings_backend_set_property; + gobject_class->finalize = g_settings_backend_finalize; + + g_type_class_add_private (class, sizeof (GSettingsBackendPrivate)); + /** * GSettingsBackend::changed: * @backend: the object on which the signal was emitted @@ -297,6 +362,14 @@ g_settings_backend_class_init (GSettingsBackendClass *class) 4, G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE, G_TYPE_STRV | G_SIGNAL_TYPE_STATIC_SCOPE, G_TYPE_INT, G_TYPE_POINTER); + + g_object_class_install_property (gobject_class, PROP_CONTEXT, + g_param_spec_string ("context", + "Context", + "A context to use when deciding which storage to use", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + } /** @@ -317,7 +390,7 @@ g_settings_backend_create_tree (void) } static gpointer -get_default_backend (gpointer user_data) +get_default_backend (const gchar *context) { GIOExtension *extension = NULL; GIOExtensionPoint *point; @@ -348,32 +421,91 @@ get_default_backend (gpointer user_data) extension = extensions->data; } + if (context) + { + GTypeClass *class; + const gchar **contexts; + + class = g_io_extension_ref_class (extension); + + contexts = g_settings_backend_class_get_supported_contexts (G_SETTINGS_BACKEND_CLASS (class)); + if (contexts) + { + gint i; + + for (i = 0; contexts[i]; i++) + { + if (strcmp (context, contexts[i]) == 0) + break; + } + + if (contexts[i] == NULL) + { + g_type_class_unref (class); + return NULL; + } + } + + g_type_class_unref (class); + } + type = g_io_extension_get_type (extension); - return g_object_new (type, NULL); + return g_object_new (type, "context", context, NULL); } /** * g_settings_backend_get_default: + * @context: a context that might be used by the backend to determine + * which storage to use * @returns: the default #GSettingsBackend * * Returns the default #GSettingsBackend. It is possible to override * the default by setting the GSETTINGS_BACKEND * environment variable to the name of a settings backend. * + * The @context parameter can be used to indicate that a different + * than the default storage is desired. E.g. the DConf backend lets + * you use "user", "system", "defaults" and "login" as contexts. + * * The user does not own the return value and it must not be freed. * * Since: 2.26 **/ GSettingsBackend * -g_settings_backend_get_default (void) +g_settings_backend_get_default (const gchar *context) { - static GOnce once = G_ONCE_INIT; + static GHashTable *backends; + GSettingsBackend *backend; + + if (!backends) + backends = g_hash_table_new (g_str_hash, g_str_equal); - return g_once (&once, get_default_backend, NULL); + backend = g_hash_table_lookup (backends, context); + + if (!backend) + { + backend = get_default_backend (context); + + g_hash_table_insert (backends, g_strdup (context), backend); + } + + return backend; } static void g_settings_backend_init (GSettingsBackend *backend) { + backend->priv = g_type_instance_get_private (backend, G_TYPE_SETTINGS_BACKEND); } + +const gchar ** +g_settings_backend_class_get_supported_contexts (GSettingsBackendClass *klass) +{ + if (klass->supported_contexts) + return (klass->supported_contexts) (klass); + + return NULL; +} + + diff --git a/gio/gsettingsbackend.h b/gio/gsettingsbackend.h index 4a0d0e1..4e05fc4 100644 --- a/gio/gsettingsbackend.h +++ b/gio/gsettingsbackend.h @@ -61,6 +61,8 @@ struct _GSettingsBackendClass const gchar *name); void (*unsubscribe) (GSettingsBackend *backend, const gchar *name); + + const gchar **(*supported_contexts) (GSettingsBackendClass *klass); }; struct _GSettingsBackend @@ -72,7 +74,7 @@ struct _GSettingsBackend }; GType g_settings_backend_get_type (void); -GSettingsBackend * g_settings_backend_get_default (void); +GSettingsBackend * g_settings_backend_get_default (const gchar *context); GTree * g_settings_backend_create_tree (void); GVariant * g_settings_backend_read (GSettingsBackend *backend, @@ -102,6 +104,8 @@ void g_settings_backend_changed_tree (GSettin GTree *tree, gpointer origin_tag); +const gchar **g_settings_backend_class_get_supported_contexts (GSettingsBackendClass *klass); + G_END_DECLS #endif /* _gsettingsbackend_h_ */