Add org.freedesktop.IBus.Config.GetValues to get all values in one RPC.
authorPeng Huang <shawn.p.huang@gmail.com>
Tue, 5 Jul 2011 14:45:20 +0000 (10:45 -0400)
committerPeng Huang <shawn.p.huang@gmail.com>
Tue, 5 Jul 2011 14:45:20 +0000 (10:45 -0400)
BUG=http://crosbug.com/16287
TEST=Linux desktop

Review URL: http://codereview.appspot.com/4667056

debian/control
debian/libibus-1.0-0.symbols
gconf/config.c
ibus/config.py
ibus/interface/iconfig.py
memconf/config.c
src/ibusconfig.c
src/ibusconfig.h
src/ibusconfigservice.c
src/ibusconfigservice.h
src/tests/ibus-config.c

index 22f77d4a60bb8439c5307bc3808695c844230401..0d5a89dcceee115a7a8819845fb031a8c43198ed 100644 (file)
@@ -8,6 +8,7 @@ Build-Depends: debhelper (>= 7),
  autoconf,
  automake,
  dpatch,
+ gtk-doc-tools,
  gobject-introspection (>= 0.6.8),
  libgirepository1.0-dev (>= 0.6.8),
  intltool (>= 0.40.0),
index 455e9fb05c62f9cc5ea152f21af156886f740bf9..778b4ead1e36a96c3b51daa12a2d0df93cf5ee02 100644 (file)
@@ -97,6 +97,9 @@ libibus-1.0.so.0 libibus-1.0-0 #MINVER#
  ibus_config_get_value@Base 1.3.99.20101019
  ibus_config_get_value_async@Base 1.3.99.20101115
  ibus_config_get_value_async_finish@Base 1.3.99.20101115
+ ibus_config_get_values@Base 1.3.99.20110616
+ ibus_config_get_values_async@Base 1.3.99.20110616
+ ibus_config_get_values_async_finish@Base 1.3.99.20110616
  ibus_config_new@Base 1.3.99.20101019
  ibus_config_new_async@Base 1.3.99.20110606
  ibus_config_new_async_finish@Base 1.3.99.20110606
@@ -119,7 +122,7 @@ libibus-1.0.so.0 libibus-1.0-0 #MINVER#
  ibus_engine_desc_get_longname@Base 1.3.99.20101019
  ibus_engine_desc_get_name@Base 1.3.99.20101019
  ibus_engine_desc_get_rank@Base 1.3.99.20101019
- ibus_engine_desc_get_symbol@Base 1.3.99.20110704
+ ibus_engine_desc_get_symbol@Base 1.3.99.20110616
  ibus_engine_desc_get_type@Base 1.3.99.20101019
  ibus_engine_desc_new@Base 1.3.99.20101019
  ibus_engine_desc_new_from_xml_node@Base 1.3.99.20101019
index df1976c72e661c503ec7dcd37183346a677e2f1e..64f1c47db402e1434646fc16a83d8323eb66f377 100644 (file)
@@ -30,6 +30,9 @@ static GVariant    *ibus_config_gconf_get_value     (IBusConfigService      *con
                                                      const gchar            *section,
                                                      const gchar            *name,
                                                      GError                **error);
+static GVariant    *ibus_config_gconf_get_values    (IBusConfigService      *config,
+                                                     const gchar            *section,
+                                                     GError                **error);
 static gboolean     ibus_config_gconf_unset_value   (IBusConfigService      *config,
                                                      const gchar            *section,
                                                      const gchar            *name,
@@ -47,6 +50,7 @@ ibus_config_gconf_class_init (IBusConfigGConfClass *class)
     IBUS_OBJECT_CLASS (object_class)->destroy = (IBusObjectDestroyFunc) ibus_config_gconf_destroy;
     IBUS_CONFIG_SERVICE_CLASS (object_class)->set_value   = ibus_config_gconf_set_value;
     IBUS_CONFIG_SERVICE_CLASS (object_class)->get_value   = ibus_config_gconf_get_value;
+    IBUS_CONFIG_SERVICE_CLASS (object_class)->get_values  = ibus_config_gconf_get_values;
     IBUS_CONFIG_SERVICE_CLASS (object_class)->unset_value = ibus_config_gconf_unset_value;
 }
 
@@ -59,15 +63,20 @@ _value_changed_cb (GConfClient     *client,
     gchar *p, *section, *name;
 
     g_return_if_fail (key != NULL);
-    g_return_if_fail (value != NULL);
 
     p = g_strdup (key);
     section = p + sizeof (GCONF_PREFIX);
     name = rindex (p, '/') + 1;
     *(name - 1) = '\0';
-
-
-    GVariant *variant = _from_gconf_value (value);
+    
+    GVariant *variant;
+    if (value) {
+        variant = _from_gconf_value (value);
+    }
+    else {
+        /* Use a empty typle for a unset value */
+        variant = g_variant_new_tuple (NULL, 0);
+    }
     g_return_if_fail (variant != NULL);
     ibus_config_service_value_changed ((IBusConfigService *) config,
                                        section,
@@ -264,7 +273,6 @@ ibus_config_gconf_get_value (IBusConfigService      *config,
                              const gchar            *name,
                              GError                **error)
 {
-
     gchar *key = g_strdup_printf (GCONF_PREFIX"/%s/%s", section, name);
 
     GConfValue *gv = gconf_client_get (((IBusConfigGConf *) config)->client, key, NULL);
@@ -283,6 +291,32 @@ ibus_config_gconf_get_value (IBusConfigService      *config,
     return variant;
 }
 
+static GVariant *
+ibus_config_gconf_get_values (IBusConfigService      *config,
+                              const gchar            *section,
+                              GError                **error)
+{
+    gchar *dir = g_strdup_printf (GCONF_PREFIX"/%s", section);
+    gint len = strlen(dir) + 1;
+    GSList *entries = gconf_client_all_entries (((IBusConfigGConf *) config)->client, dir, NULL);
+    g_free (dir);
+
+    GSList *p;
+    GVariantBuilder *builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
+    for (p = entries; p != NULL; p = p->next) {
+        GConfEntry *entry = (GConfEntry *)p->data;
+        if (entry->key != NULL && entry->value != NULL) {
+            const gchar *name = entry->key + len;
+            GVariant *value = _from_gconf_value (entry->value);
+            g_variant_builder_add (builder, "{sv}", name, value);
+        }
+        gconf_entry_free (entry);
+    }
+    g_slist_free (entries);
+
+    return g_variant_builder_end (builder);
+}
+
 static gboolean
 ibus_config_gconf_unset_value (IBusConfigService      *config,
                                const gchar            *section,
index 0f6e80f036910565e8f1b91ddc7dcdf85323c993..7a0557f443d897e8edd5fb2c15eefb52a666d4c6 100644 (file)
@@ -43,6 +43,9 @@ class ConfigBase(object.Object):
     def get_value(self, section, name):
         pass
 
+    def get_values(self, section):
+        pass
+
     def set_value(self, section, name, value):
         pass
 
@@ -62,6 +65,9 @@ class ConfigProxy(interface.IConfig):
     def GetValue(self, section, name):
         return self.__config.get_value(section, name)
 
+    def GetValues(self, section):
+        return self.__config.get_values(section)
+
     def SetValue(self, section, name, value):
         return self.__config.set_value(section, name, value)
 
@@ -139,6 +145,12 @@ class Config(object.Object):
         except:
             return default_value
 
+    def get_values(self, section):
+        try:
+            return self.__config.GetValues(section)
+        except:
+            return None
+
     def set_value(self, section, name, value):
         try:
             return self.__config.SetValue(section, name, value)
index 8637800afbe23cada167fa4d96b9291cb214ad28..5f3f0404f1b1d46508b826a399fdf21ace0258d0 100644 (file)
@@ -46,6 +46,9 @@ class IConfig(dbus.service.Object):
     @method(in_signature="ss", out_signature="v")
     def GetValue(self, section, name): pass
 
+    @method(in_signature="s", out_signature="s{sv}")
+    def GetValues(self, section): pass
+
     @method(in_signature="ssv")
     def SetValue(self, section, name, value): pass
 
index a5aa19037a3009ba2b71c44d94ca47bdc4bde8c0..dd18f2e70299aa1dcc10ee9b48d294a2a80bdbd5 100644 (file)
@@ -48,6 +48,9 @@ static GVariant    *ibus_config_memconf_get_value   (IBusConfigService      *con
                                                      const gchar            *section,
                                                      const gchar            *name,
                                                      GError                **error);
+static GVariant    *ibus_config_memconf_get_values  (IBusConfigService      *config,
+                                                     const gchar            *section,
+                                                     GError                **error);
 static gboolean     ibus_config_memconf_unset_value (IBusConfigService      *config,
                                                      const gchar            *section,
                                                      const gchar            *name,
@@ -63,6 +66,7 @@ ibus_config_memconf_class_init (IBusConfigMemconfClass *class)
     IBUS_OBJECT_CLASS (object_class)->destroy = (IBusObjectDestroyFunc) ibus_config_memconf_destroy;
     IBUS_CONFIG_SERVICE_CLASS (object_class)->set_value   = ibus_config_memconf_set_value;
     IBUS_CONFIG_SERVICE_CLASS (object_class)->get_value   = ibus_config_memconf_get_value;
+    IBUS_CONFIG_SERVICE_CLASS (object_class)->get_values  = ibus_config_memconf_get_values;
     IBUS_CONFIG_SERVICE_CLASS (object_class)->unset_value = ibus_config_memconf_unset_value;
 }
 
@@ -130,6 +134,32 @@ ibus_config_memconf_get_value (IBusConfigService *config,
     return value;
 }
 
+static GVariant *
+ibus_config_memconf_get_values (IBusConfigService *config,
+                                const gchar       *section,
+                                GError           **error)
+{
+    g_assert (IBUS_IS_CONFIG_MEMCONF (config));
+    g_assert (section);
+    g_assert (error == NULL || *error == NULL);
+
+    GHashTableIter iter;
+    const gchar *key;
+    GVariant *value;
+    
+    GVariantBuilder *builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
+    g_hash_table_iter_init (&iter, IBUS_CONFIG_MEMCONF (config)->values);
+    while (g_hash_table_iter_next (&iter, (gpointer *)&key, (gpointer *)&value)) {
+        gchar **v = g_strsplit (key, ":", 2);
+        if (g_strcmp0 (v[0], section) == 0) {
+            g_variant_builder_add (builder, "{sv}", v[1], value); 
+        }
+        g_strfreev(v);
+    }
+
+    return g_variant_builder_end (builder);
+}
+
 static gboolean
 ibus_config_memconf_unset_value (IBusConfigService *config,
                                  const gchar       *section,
@@ -146,6 +176,10 @@ ibus_config_memconf_unset_value (IBusConfigService *config,
     g_free (key);
 
     if (retval) {
+        ibus_config_service_value_changed (config,
+                                           section,
+                                           name,
+                                           g_variant_new_tuple (NULL, 0));
     }
     else {
         if (error && *error) {
index 736c30a284c75c205d9130187f763bd0bf364226..36ef44b5e326ef2c245ea374e50f1bdf0b405d6a 100644 (file)
@@ -300,7 +300,7 @@ ibus_config_get_value_async_finish (IBusConfig    *config,
                                                  result,
                                                  error);
     if (retval != NULL) {
-        g_variant_get (retval, "(v)", &value);
+        g_variant_get (retval, "(@a{sv})", &value);
         g_variant_ref (value);
         g_variant_unref (retval);
     }
@@ -308,6 +308,79 @@ ibus_config_get_value_async_finish (IBusConfig    *config,
     return value;
 }
 
+GVariant *
+ibus_config_get_values (IBusConfig  *config,
+                        const gchar *section)
+{
+    g_assert (IBUS_IS_CONFIG (config));
+    g_assert (section != NULL);
+
+    GError *error = NULL;
+    GVariant *result;
+    result = g_dbus_proxy_call_sync ((GDBusProxy *) config,
+                                     "GetValues",
+                                     g_variant_new ("(s)", section),
+                                     G_DBUS_CALL_FLAGS_NONE,
+                                     -1,
+                                     NULL,
+                                     &error);
+    if (result == NULL) {
+        g_warning ("%s.GetValues: %s", IBUS_INTERFACE_CONFIG, error->message);
+        g_error_free (error);
+        return NULL;
+    }
+
+    GVariant *value = NULL;
+    g_variant_get (result, "(@a{sv})", &value);
+    g_variant_ref (value);
+    g_variant_unref (result);
+
+    return value;
+}
+
+void
+ibus_config_get_values_async (IBusConfig         *config,
+                              const gchar        *section,
+                              gint                timeout_ms,
+                              GCancellable       *cancellable,
+                              GAsyncReadyCallback callback,
+                              gpointer            user_data)
+{
+    g_assert (IBUS_IS_CONFIG (config));
+    g_assert (section != NULL);
+
+    g_dbus_proxy_call ((GDBusProxy *)config,
+                       "GetValues",
+                       g_variant_new ("(s)", section),
+                       G_DBUS_CALL_FLAGS_NONE,
+                       timeout_ms,
+                       cancellable,
+                       callback,
+                       user_data);
+}
+
+GVariant *
+ibus_config_get_values_async_finish (IBusConfig    *config,
+                                     GAsyncResult  *result,
+                                     GError       **error)
+{
+    g_assert (IBUS_IS_CONFIG (config));
+    g_assert (G_IS_ASYNC_RESULT (result));
+    g_assert (error == NULL || *error == NULL);
+
+    GVariant *value = NULL;
+    GVariant *retval = g_dbus_proxy_call_finish ((GDBusProxy *)config,
+                                                 result,
+                                                 error);
+    if (retval != NULL) {
+        g_variant_get (retval, "(v)", &value);
+        g_variant_ref (value);
+        g_variant_unref (retval);
+    }
+
+    return value;
+}
+    
 gboolean
 ibus_config_set_value (IBusConfig   *config,
                        const gchar  *section,
index 1bc97936a57adcf521dbaeb036202c6ed50afadc..07f5ce81d590ff67dc6d08e4fb1652d007214535 100644 (file)
@@ -179,6 +179,55 @@ GVariant        *ibus_config_get_value_async_finish
                                              GAsyncResult       *result,
                                              GError            **error);
 
+/**
+ * ibus_config_get_values:
+ * @config: An IBusConfig
+ * @section: Section name of the configuration option.
+ * @returns: A #GVariant or %NULL. Free with g_variant_unref().
+ *
+ * Get all values in a section synchronously.
+ *
+ * @see_also: ibus_config_set_value.
+ */
+GVariant        *ibus_config_get_values     (IBusConfig         *config,
+                                             const gchar        *section);
+
+/**
+ * ibus_config_get_values_async:
+ * @config: An IBusConfig
+ * @section: Section name of the configuration option.
+ * @timeout_ms: The timeout in milliseconds or -1 to use the default timeout.
+ * @cancellable: A #GCancellable or %NULL.
+ * @callback: Callback function to invoke when the return value is ready.
+ * @user_data: The data to pass to callback.
+ *
+ * Get all values in a section asynchronously.
+ *
+ * @see_also: ibus_config_get_values.
+ */
+void             ibus_config_get_values_async(IBusConfig         *config,
+                                              const gchar        *section,
+                                              gint                timeout_ms,
+                                              GCancellable       *cancellable,
+                                              GAsyncReadyCallback callback,
+                                              gpointer            user_data);
+
+/**
+ * ibus_config_get_values_async_finish:
+ * @config: A #IBusConfig.
+ * @result: A #GAsyncResult.
+ * @error: Return location for error or %NULL.
+ * @returns: A #GVariant or %NULL if error is set. Free with g_variant_unref().
+ * 
+ * Finish get values in a section.
+ *
+ * @see_also: ibus_config_get_values_async.
+ */
+GVariant        *ibus_config_get_values_async_finish
+                                            (IBusConfig         *config,
+                                             GAsyncResult       *result,
+                                             GError            **error);
+
 /**
  * ibus_config_set_value:
  * @config: An IBusConfig
index 64207300ef82d7eedcd6d0222181942427690fce..937dfdd41225a0303c07ace2a698f93c6a3a2a58 100644 (file)
@@ -79,6 +79,9 @@ static GVariant *ibus_config_service_get_value       (IBusConfigService      *co
                                                       const gchar            *section,
                                                       const gchar            *name,
                                                       GError                **error);
+static GVariant *ibus_config_service_get_values      (IBusConfigService      *config,
+                                                      const gchar            *section,
+                                                      GError                **error);
 static gboolean  ibus_config_service_unset_value     (IBusConfigService      *config,
                                                       const gchar            *section,
                                                       const gchar            *name,
@@ -99,6 +102,10 @@ static const gchar introspection_xml[] =
     "      <arg direction='in'  type='s' name='name' />"
     "      <arg direction='out' type='v' name='value' />"
     "    </method>"
+    "    <method name='GetValues'>"
+    "      <arg direction='in'  type='s' name='section' />"
+    "      <arg direction='out' type='a{sv}' name='values' />"
+    "    </method>"
     "    <method name='UnsetValue'>"
     "      <arg direction='in'  type='s' name='section' />"
     "      <arg direction='in'  type='s' name='name' />"
@@ -129,6 +136,7 @@ ibus_config_service_class_init (IBusConfigServiceClass *class)
 
     class->set_value   = ibus_config_service_set_value;
     class->get_value   = ibus_config_service_get_value;
+    class->get_values  = ibus_config_service_get_values;
     class->unset_value = ibus_config_service_unset_value;
 }
 
@@ -235,6 +243,27 @@ ibus_config_service_service_method_call (IBusService           *service,
         return;
     }
 
+    if (g_strcmp0 (method_name, "GetValues") == 0) {
+        gchar *section;
+        GVariant *value;
+        GError *error = NULL;
+
+        g_variant_get (parameters, "(&s)", &section);
+
+        value = IBUS_CONFIG_SERVICE_GET_CLASS (config)->get_values (config,
+                                                                     section,
+                                                                     &error);
+        if (value) {
+            g_dbus_method_invocation_return_value (invocation,
+                    g_variant_new ("(@a{sv})", value));
+        }
+        else {
+            g_dbus_method_invocation_return_gerror (invocation, error);
+            g_error_free (error);
+        }
+        return;
+    }
+
     if (g_strcmp0 (method_name, "UnsetValue") == 0) {
         gchar *section;
         gchar *name;
@@ -327,6 +356,18 @@ ibus_config_service_get_value (IBusConfigService *config,
     return NULL;
 }
 
+static GVariant *
+ibus_config_service_get_values (IBusConfigService *config,
+                                const gchar       *section,
+                                GError           **error)
+{
+    if (error) {
+        *error = g_error_new (G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
+                              "Cannot get values %s", section);
+    }
+    return NULL;
+}
+
 static gboolean
 ibus_config_service_unset_value (IBusConfigService *config,
                                  const gchar       *section,
index 1aab32f4cceccd535524f9b28aa63e9c3f924310..23dcfc6d924c5063de6d38e3f8cd554c738c701d 100644 (file)
@@ -200,10 +200,13 @@ struct _IBusConfigServiceClass {
                                  const gchar          *section,
                                  const gchar          *name,
                                  GError              **error);
+    GVariant *  (* get_values)  (IBusConfigService    *config,
+                                 const gchar          *section,
+                                 GError              **error);
 
     /*< private >*/
     /* padding */
-    gpointer pdummy[13];
+    gpointer pdummy[12];
 };
 
 GType                ibus_config_service_get_type   (void);
index baf950f083469a975857f6941fb0b4e551e1a37c..8967adba2265dee5537e4f87c13e0fa4534737fc 100644 (file)
@@ -70,6 +70,62 @@ test_create_config_async (void)
     g_main_loop_unref (loop);
 }
 
+static void
+test_config_set_get (void)
+{
+    IBusConfig *config = ibus_config_new (ibus_bus_get_connection (bus),
+                                          NULL,
+                                          NULL);
+    g_assert (config);
+
+    ibus_config_set_value (config, "test", "v1", g_variant_new_int32(1));
+    ibus_config_set_value (config, "test", "v2", g_variant_new_string("2"));
+
+    GVariant *var;
+    var = ibus_config_get_value (config, "test", "v1");
+    g_assert (var);
+    g_assert_cmpint (g_variant_get_int32(var), ==, 1);
+    g_variant_unref (var);
+
+    var = ibus_config_get_value (config, "test", "v2");
+    g_assert (var);
+    g_assert_cmpstr (g_variant_get_string(var, NULL), ==, "2");
+    g_variant_unref (var);
+
+    var = ibus_config_get_values (config, "test");
+    g_assert (var);
+
+    GVariantIter iter;
+    gchar *name;
+    GVariant *value;
+    g_variant_iter_init (&iter, var);
+    gint value_bits = 0;
+    while (g_variant_iter_next (&iter, "{&sv}", &name, &value)) {
+        if (g_strcmp0 (name, "v1") == 0) {
+            g_assert_cmpint (g_variant_get_int32(value), ==, 1);
+            value_bits |= 1;
+        }
+        else if (g_strcmp0 (name, "v2") == 0) {
+            g_assert_cmpstr (g_variant_get_string(value, NULL), ==, "2");
+            value_bits |= (1 << 1);
+        }
+        else {
+            g_warning ("unknow value name=%s", name);
+        }
+        ibus_config_unset (config, "test", name);
+        g_variant_unref (value);
+    }
+    g_assert_cmpint (value_bits, ==, 1 | (1 << 1));
+    g_variant_unref (var);
+
+    var = ibus_config_get_values (config, "test");
+    g_assert (var);
+    g_assert_cmpint (g_variant_n_children (var), ==, 0);
+    g_variant_unref (var);
+
+    g_object_unref (config);
+}
+
 gint
 main (gint    argc,
       gchar **argv)
@@ -81,6 +137,7 @@ main (gint    argc,
     bus = ibus_bus_new ();
 
     g_test_add_func ("/ibus/create-config-async", test_create_config_async);
+    g_test_add_func ("/ibus/config-set-get", test_config_set_get);
 
     result = g_test_run ();
     g_object_unref (bus);