[glib/gsettings] add GSettingsDelayedBackend



commit 521bfaa2e6bd24b4924925fa140f700f546c4490
Author: Ryan Lortie <desrt desrt ca>
Date:   Tue Sep 1 13:41:51 2009 -0400

    add GSettingsDelayedBackend

 gio/Makefile.am               |    2 +
 gio/gio.symbols               |   10 ++
 gio/gsettingsdelayedbackend.c |  329 +++++++++++++++++++++++++++++++++++++++++
 gio/gsettingsdelayedbackend.h |   59 ++++++++
 4 files changed, 400 insertions(+), 0 deletions(-)
---
diff --git a/gio/Makefile.am b/gio/Makefile.am
index 146991e..883aa5f 100644
--- a/gio/Makefile.am
+++ b/gio/Makefile.am
@@ -238,6 +238,7 @@ libgio_2_0_la_SOURCES =		\
 	gresolver.c		\
 	gseekable.c 		\
 	gsettingsbackend.c	\
+	gsettingsdelayedbackend.c \
 	gsettingsschema.c	\
 	gsimpleasyncresult.c 	\
 	gsocket.c		\
@@ -368,6 +369,7 @@ gio_headers =			\
 	gresolver.h		\
 	gseekable.h 		\
 	gsettingsbackend.h	\
+	gsettingsdelayedbackend.h \
 	gsettingsschema.h	\
 	gsimpleasyncresult.h 	\
 	gsocket.h		\
diff --git a/gio/gio.symbols b/gio/gio.symbols
index fcc73b4..feacfa2 100644
--- a/gio/gio.symbols
+++ b/gio/gio.symbols
@@ -1286,3 +1286,13 @@ g_settings_schema_new
 g_settings_schema_type_check_key
 #endif
 #endif
+
+#if IN_HEADER(_gsettingsdelayedbackend_h_)
+#if IN_FILE(_gsettingsdelayedbackend_c_)
+g_settings_delayed_backend_apply
+g_settings_delayed_backend_get_type
+g_settings_delayed_backend_new
+g_settings_delayed_backend_revert
+g_settings_delayed_backend_get_has_unapplied
+#endif
+#endif
diff --git a/gio/gsettingsdelayedbackend.c b/gio/gsettingsdelayedbackend.c
new file mode 100644
index 0000000..ce1d735
--- /dev/null
+++ b/gio/gsettingsdelayedbackend.c
@@ -0,0 +1,329 @@
+/*
+ * Copyright © 2009 Codethink Limited
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of version 3 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * See the included COPYING file for more information.
+ */
+
+#include "gsettingsdelayedbackend.h"
+
+#include <string.h>
+
+#include "gioalias.h"
+
+enum
+{
+  PROP_NONE,
+  PROP_BACKEND,
+  PROP_BASE_PATH,
+  PROP_HAS_UNAPPLIED
+};
+
+struct _GSettingsDelayedBackendPrivate {
+  GSettingsBackend *backend;
+  guint handler_id;
+  gchar *base_path;
+  GTree *delayed;
+};
+
+G_DEFINE_TYPE (GSettingsDelayedBackend,
+               g_settings_delayed_backend,
+               G_TYPE_SETTINGS_BACKEND)
+
+static gboolean
+g_settings_delayed_backend_add_to_tree (gpointer key,
+                                        gpointer value,
+                                        gpointer user_data)
+{
+  gpointer *args = user_data;
+
+  g_tree_insert (args[0],
+                 g_strjoin (NULL, args[1], key, NULL),
+                 g_variant_ref (value));
+
+  return FALSE;
+}
+
+static void
+g_settings_delayed_backend_write (GSettingsBackend *backend,
+                                  const gchar      *prefix,
+                                  GTree            *tree,
+                                  gpointer          origin_tag)
+{
+  GSettingsDelayedBackend *delayed = G_SETTINGS_DELAYED_BACKEND (backend);
+  gconstpointer args[2] = { delayed->priv->delayed, prefix };
+  gboolean was_empty;
+
+  was_empty = g_tree_nnodes (delayed->priv->delayed) == 0;
+
+  g_tree_foreach (tree, g_settings_delayed_backend_add_to_tree, args);
+
+  g_settings_backend_changed_tree (backend, prefix, tree, origin_tag);
+
+  if (was_empty)
+    g_object_notify (G_OBJECT (delayed), "has-unapplied");
+}
+
+static GVariant *
+g_settings_delayed_backend_read (GSettingsBackend   *backend,
+                                 const gchar        *key,
+                                 const GVariantType *expected_type)
+{
+  GSettingsDelayedBackend *delayed = G_SETTINGS_DELAYED_BACKEND (backend);
+  GVariant *result = NULL;
+  gchar *path;
+
+  if ((result = g_tree_lookup (delayed->priv->delayed, key))) 
+    return g_variant_ref (result);
+
+  path = g_strconcat (delayed->priv->base_path, key, NULL);
+  result = g_settings_backend_read (delayed->priv->backend,
+                                    path, expected_type);
+  g_free (path);
+
+  return result;
+}
+
+gboolean
+g_settings_delayed_backend_get_has_unapplied (GSettingsDelayedBackend *delayed)
+{
+  return g_tree_nnodes (delayed->priv->delayed) > 0;
+}
+
+void
+g_settings_delayed_backend_apply (GSettingsDelayedBackend *delayed)
+{
+  if (g_tree_nnodes (delayed->priv->delayed))
+    {
+      GTree *tmp;
+
+      tmp = delayed->priv->delayed;
+      delayed->priv->delayed = g_settings_backend_new_tree ();
+
+      g_settings_backend_write (delayed->priv->backend,
+                                delayed->priv->base_path,
+                                tmp, delayed->priv);
+      g_tree_unref (tmp);
+
+      g_object_notify (G_OBJECT (delayed), "has-unapplied");
+    }
+}
+
+void
+g_settings_delayed_backend_revert (GSettingsDelayedBackend *delayed)
+{
+  if (g_tree_nnodes (delayed->priv->delayed))
+    {
+      GTree *tmp;
+
+      tmp = delayed->priv->delayed;
+      delayed->priv->delayed = g_settings_backend_new_tree ();
+      g_settings_backend_changed_tree (G_SETTINGS_BACKEND (delayed),
+                                       "", tmp, NULL);
+      g_tree_destroy (tmp);
+
+      g_object_notify (G_OBJECT (delayed), "has-unapplied");
+    }
+}
+
+static gboolean
+g_settings_delayed_backend_get_writable (GSettingsBackend *backend,
+                                         const gchar      *name)
+{
+  GSettingsDelayedBackend *delayed = G_SETTINGS_DELAYED_BACKEND (backend);
+  gboolean sensitive;
+  gchar *path;
+
+  path = g_strconcat (delayed->priv->base_path, name, NULL);
+  sensitive = g_settings_backend_get_writable (delayed->priv->backend, path);
+  g_free (path);
+
+  return sensitive;
+}
+
+static void
+g_settings_delayed_backend_subscribe (GSettingsBackend *base,
+                                      const char       *name)
+{
+}
+
+static void
+g_settings_delayed_backend_get_property (GObject *object, guint prop_id,
+                                         GValue *value, GParamSpec *pspec)
+{
+  GSettingsDelayedBackend *delayed = G_SETTINGS_DELAYED_BACKEND (object);
+
+  switch (prop_id)
+    {
+      gboolean has;
+
+    case PROP_HAS_UNAPPLIED:
+      has = g_settings_delayed_backend_get_has_unapplied (delayed);
+      g_value_set_boolean (value, has);
+      break;
+
+    default:
+      g_assert_not_reached ();
+    }
+}
+
+static void
+g_settings_delayed_backend_set_property (GObject *object, guint prop_id,
+                                         const GValue *value, GParamSpec *pspec)
+{
+  GSettingsDelayedBackend *delayed = G_SETTINGS_DELAYED_BACKEND (object);
+
+  switch (prop_id)
+    {
+    case PROP_BACKEND:
+      g_assert (delayed->priv->backend == NULL);
+      delayed->priv->backend = g_value_dup_object (value);
+      break;
+
+    case PROP_BASE_PATH:
+      g_assert (delayed->priv->base_path == NULL);
+      delayed->priv->base_path = g_value_dup_string (value);
+      break;
+
+    default:
+      g_assert_not_reached ();
+    }
+}
+
+static void
+g_settings_delayed_backend_backend_changed (GSettingsBackend    *backend,
+                                            const gchar         *prefix,
+                                            const gchar * const *items,
+                                            gint                 n_items,
+                                            gpointer             origin_tag,
+                                            gpointer             user_data)
+{
+  GSettingsDelayedBackend *delayed = G_SETTINGS_DELAYED_BACKEND (user_data);
+
+  if (origin_tag == delayed->priv)
+    return;
+
+  if (g_str_has_prefix (prefix, delayed->priv->base_path))
+    {
+      g_settings_backend_changed (G_SETTINGS_BACKEND (delayed),
+                                  prefix + strlen (delayed->priv->base_path),
+                                  items, n_items, origin_tag);
+    }
+
+  else if (g_str_has_prefix (delayed->priv->base_path, prefix))
+    {
+      const gchar **my_items;
+      const gchar *relative;
+      gint relative_length;
+      gint i, j;
+
+      relative = delayed->priv->base_path + strlen (prefix);
+      relative_length = strlen (relative);
+
+      my_items = g_new (const gchar *, n_items + 1);
+
+      for (i = j = 0; i < n_items; i++)
+        if (g_str_has_prefix (items[i], relative))
+          my_items[j++] = items[i] + relative_length;
+      my_items[j] = NULL;
+
+      if (j > 0)
+        g_settings_backend_changed (G_SETTINGS_BACKEND (delayed),
+                                    "", my_items, j, origin_tag);
+      g_free (my_items);
+    }
+
+  else
+    /* do nothing */;
+}
+
+static void
+g_settings_delayed_backend_constructed (GObject *object)
+{
+  GSettingsDelayedBackend *delayed = G_SETTINGS_DELAYED_BACKEND (object);
+
+  g_assert (delayed->priv->backend != NULL);
+  g_assert (delayed->priv->base_path != NULL);
+
+  delayed->priv->handler_id = 
+    g_signal_connect (delayed->priv->backend, "changed",
+                      G_CALLBACK (g_settings_delayed_backend_backend_changed),
+                      delayed);
+
+  g_settings_backend_subscribe (delayed->priv->backend,
+                                delayed->priv->base_path);
+}
+
+static void
+g_settings_delayed_backend_finalize (GObject *object)
+{
+  GSettingsDelayedBackend *delayed = G_SETTINGS_DELAYED_BACKEND (object);
+
+  g_signal_handler_disconnect (delayed->priv->backend,
+                               delayed->priv->handler_id);
+  g_settings_backend_unsubscribe (delayed->priv->backend,
+                                  delayed->priv->base_path);
+  g_object_unref (delayed->priv->backend);
+  g_free (delayed->priv->base_path);
+}
+
+static void
+g_settings_delayed_backend_class_init (GSettingsDelayedBackendClass *class)
+{
+  GSettingsBackendClass *backend_class = G_SETTINGS_BACKEND_CLASS (class);
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+  g_type_class_add_private (class, sizeof (GSettingsDelayedBackendPrivate));
+
+  backend_class->write = g_settings_delayed_backend_write;
+  backend_class->read = g_settings_delayed_backend_read;
+  backend_class->get_writable = g_settings_delayed_backend_get_writable;
+  backend_class->subscribe = g_settings_delayed_backend_subscribe;
+  backend_class->unsubscribe = g_settings_delayed_backend_subscribe;
+
+  object_class->get_property = g_settings_delayed_backend_get_property;
+  object_class->set_property = g_settings_delayed_backend_set_property;
+  object_class->constructed = g_settings_delayed_backend_constructed;
+  object_class->finalize = g_settings_delayed_backend_finalize;
+
+  g_object_class_install_property (object_class, PROP_BACKEND,
+    g_param_spec_object ("backend", "backend backend", "backend",
+                         G_TYPE_SETTINGS_BACKEND, G_PARAM_CONSTRUCT_ONLY |
+                         G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (object_class, PROP_BASE_PATH,
+    g_param_spec_string ("base-path", "base path", "base",
+                         "", G_PARAM_CONSTRUCT_ONLY |
+                         G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (object_class, PROP_HAS_UNAPPLIED,
+    g_param_spec_boolean ("has-unapplied", "has unapplied", "unapplied",
+                          FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+}
+
+static void
+g_settings_delayed_backend_init (GSettingsDelayedBackend *delayed)
+{
+  delayed->priv =
+    G_TYPE_INSTANCE_GET_PRIVATE (delayed, G_TYPE_SETTINGS_DELAYED_BACKEND,
+                                 GSettingsDelayedBackendPrivate);
+
+  delayed->priv->delayed = g_settings_backend_new_tree ();
+}
+
+GSettingsBackend *
+g_settings_delayed_backend_new (GSettingsBackend *backend,
+                       const gchar      *base_path)
+{
+  return g_object_new (G_TYPE_SETTINGS_DELAYED_BACKEND,
+                       "backend", backend,
+                       "base-path", base_path,
+                       NULL);
+}
+
+#define _gsettingsdelayedbackend_c_
+#include "gioaliasdef.c"
diff --git a/gio/gsettingsdelayedbackend.h b/gio/gsettingsdelayedbackend.h
new file mode 100644
index 0000000..e222398
--- /dev/null
+++ b/gio/gsettingsdelayedbackend.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright © 2009 Codethink Limited
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of version 3 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * See the included COPYING file for more information.
+ */
+
+#ifndef _gsettingsdelayedbackend_h_
+#define _gsettingsdelayedbackend_h_
+
+#include <glib-object.h>
+
+#include <gio/gsettingsbackend.h>
+
+#define G_TYPE_SETTINGS_DELAYED_BACKEND                     (g_settings_delayed_backend_get_type ())
+#define G_SETTINGS_DELAYED_BACKEND(inst)                    (G_TYPE_CHECK_INSTANCE_CAST ((inst),                     \
+                                                             G_TYPE_SETTINGS_DELAYED_BACKEND,                        \
+                                                             GSettingsDelayedBackend))
+#define G_SETTINGS_DELAYED_BACKEND_CLASS(class)             (G_TYPE_CHECK_CLASS_CAST ((class),                       \
+                                                             G_TYPE_SETTINGS_DELAYED_BACKEND,                        \
+                                                             GSettingsDelayedBackendClass))
+#define G_IS_SETTINGS_DELAYED_BACKEND(inst)                 (G_TYPE_CHECK_INSTANCE_TYPE ((inst),                     \
+                                                             G_TYPE_SETTINGS_DELAYED_BACKEND))
+#define G_IS_SETTINGS_DELAYED_BACKEND_CLASS(class)          (G_TYPE_CHECK_CLASS_TYPE ((class),                       \
+                                                             G_TYPE_SETTINGS_DELAYED_BACKEND))
+#define G_SETTINGS_DELAYED_BACKEND_GET_CLASS(inst)          (G_TYPE_INSTANCE_GET_CLASS ((inst),                      \
+                                                             G_TYPE_SETTINGS_DELAYED_BACKEND,                        \
+                                                             GSettingsDelayedBackendClass))
+
+typedef struct _GSettingsDelayedBackendPrivate              GSettingsDelayedBackendPrivate;
+typedef struct _GSettingsDelayedBackendClass                GSettingsDelayedBackendClass;
+typedef struct _GSettingsDelayedBackend                     GSettingsDelayedBackend;
+
+struct _GSettingsDelayedBackendClass
+{
+  GSettingsBackendClass parent_class;
+};
+
+struct _GSettingsDelayedBackend
+{
+  GSettingsBackend parent_instance;
+  GSettingsDelayedBackendPrivate *priv;
+};
+
+G_BEGIN_DECLS
+
+GType                           g_settings_delayed_backend_get_type     (void);
+GSettingsBackend *              g_settings_delayed_backend_new          (GSettingsBackend        *backend,     
+                                                                         const gchar             *base_path);
+void                            g_settings_delayed_backend_revert       (GSettingsDelayedBackend *delayed);
+void                            g_settings_delayed_backend_apply        (GSettingsDelayedBackend *delayed);
+gboolean                        g_settings_delayed_backend_get_has_unapplied (GSettingsDelayedBackend *delayed);
+
+G_END_DECLS
+
+#endif /* _gsettingsdelayedbackend_h_ */



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