[glib] Bug 631263 - GSettings needs range/choice APIs
- From: Ryan Lortie <ryanl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] Bug 631263 - GSettings needs range/choice APIs
- Date: Mon, 4 Oct 2010 06:59:28 +0000 (UTC)
commit d6d76783ae9fc473d7fe38683d729d6c2c8e80c4
Author: Ryan Lortie <desrt desrt ca>
Date: Mon Oct 4 02:58:46 2010 -0400
Bug 631263 - GSettings needs range/choice APIs
Add g_settings_get_range() to describe the possible values that may be
provided to g_settings_set_value() without causing an error.
Add a test case.
gio/gsettings.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++-
gio/gsettings.h | 2 +
gio/strinfo.c | 31 ++++++++++++++++++
gio/tests/gsettings.c | 43 +++++++++++++++++++++++++
4 files changed, 159 insertions(+), 1 deletions(-)
---
diff --git a/gio/gsettings.c b/gio/gsettings.c
index 34a69ce..5d7cb5e 100644
--- a/gio/gsettings.c
+++ b/gio/gsettings.c
@@ -1995,7 +1995,7 @@ g_settings_get_has_unapplied (GSettings *settings)
G_DELAYED_SETTINGS_BACKEND (settings->priv->backend));
}
-/* Extra API (reset, sync, get_child, is_writable, list_*) {{{1 */
+/* Extra API (reset, sync, get_child, is_writable, list_*, get_range) {{{1 */
/**
* g_settings_reset:
* @settings: a #GSettings object
@@ -2198,6 +2198,88 @@ g_settings_list_children (GSettings *settings)
return strv;
}
+/**
+ * g_settings_get_range:
+ * @settings: a #GSettings
+ * @key: the key to query the range of
+ * @returns: a #GVariant describing the range
+ *
+ * Queries the range of a key.
+ *
+ * This function will return a #GVariant that fully describes the range
+ * of values that are valid for @key.
+ *
+ * The type of #GVariant returned is <literal>(sv)</literal>. The
+ * string describes the type of range restriction in effect. The type
+ * and meaning of the value contained in the variant depends on the
+ * string.
+ *
+ * If the string is <literal>'type'</literal> then the variant contains
+ * an empty array. The element type of that empty array is the expected
+ * type of value and all values of that type are valid.
+ *
+ * If the string is <literal>'enum'</literal> then the variant contains
+ * an array enumerating the possible values. Each item in the array is
+ * a possible valid value and no other values are valid.
+ *
+ * If the string is <literal>'flags'</literal> then the variant contains
+ * an array. Each item in the array is a value that may appear zero or
+ * one times in an array to be used as the value for this key. For
+ * example, if the variant contained the array <literal>['x',
+ * 'y']</literal> then the valid values for the key would be
+ * <literal>[]</literal>, <literal>['x']</literal>,
+ * <literal>['y']</literal>, <literal>['x', 'y']</literal> and
+ * <literal>['y', 'x']</literal>.
+ *
+ * Finally, if the string is <literal>'range'</literal> then the variant
+ * contains a pair of like-typed values -- the minimum and maximum
+ * permissible values for this key.
+ *
+ * This information should not be used by normal programs. It is
+ * considered to be a hint for introspection purposes. Normal programs
+ * should already know what is permitted by their own schema. The
+ * format may change in any way in the future -- but particularly, new
+ * forms may be added to the possibilities described above.
+ *
+ * It is a programmer error to give a @key that isn't contained in the
+ * schema for @settings.
+ *
+ * You should free the returned value with g_variant_unref() when it is
+ * no longer needed.
+ *
+ * Since: 2.28
+ **/
+GVariant *
+g_settings_get_range (GSettings *settings,
+ const gchar *key)
+{
+ GSettingsKeyInfo info;
+ const gchar *type;
+ GVariant *range;
+
+ g_settings_get_key_info (&info, settings, key);
+
+ if (info.minimum)
+ {
+ range = g_variant_new ("(**)", info.minimum, info.maximum);
+ type = "range";
+ }
+ else if (info.strinfo)
+ {
+ range = strinfo_enumerate (info.strinfo, info.strinfo_length);
+ type = info.is_flags ? "flags" : "enum";
+ }
+ else
+ {
+ range = g_variant_new_array (info.type, NULL, 0);
+ type = "type";
+ }
+
+ g_settings_free_key_info (&info);
+
+ return g_variant_ref_sink (g_variant_new ("(sv)", type, range));
+}
+
/* Binding {{{1 */
typedef struct
{
diff --git a/gio/gsettings.h b/gio/gsettings.h
index 2b4e2f6..a90cd0b 100644
--- a/gio/gsettings.h
+++ b/gio/gsettings.h
@@ -82,6 +82,8 @@ GSettings * g_settings_new_with_backend_and_path (const g
const gchar *path);
gchar ** g_settings_list_children (GSettings *settings);
gchar ** g_settings_list_keys (GSettings *settings);
+GVariant * g_settings_get_range (GSettings *settings,
+ const gchar *key);
gboolean g_settings_set_value (GSettings *settings,
const gchar *key,
diff --git a/gio/strinfo.c b/gio/strinfo.c
index 6836b59..cfefe13 100644
--- a/gio/strinfo.c
+++ b/gio/strinfo.c
@@ -260,6 +260,37 @@ strinfo_string_from_alias (const guint32 *strinfo,
return 1 + (const gchar *) &strinfo[GUINT32_TO_LE (strinfo[index]) + 1];
}
+G_GNUC_UNUSED static GVariant *
+strinfo_enumerate (const guint32 *strinfo,
+ guint length)
+{
+ GVariantBuilder builder;
+ const gchar *ptr, *end;
+
+ ptr = (gpointer) strinfo;
+ end = ptr + 4 * length;
+
+ ptr += 4;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE_STRING_ARRAY);
+
+ while (ptr < end)
+ {
+ /* don't include aliases */
+ if (*ptr == '\xff')
+ g_variant_builder_add (&builder, "s", ptr + 1);
+
+ /* find the end of this string */
+ ptr = memchr (ptr, '\xff', end - ptr);
+ g_assert (ptr != NULL);
+
+ /* skip over the int to the next string */
+ ptr += 5;
+ }
+
+ return g_variant_builder_end (&builder);
+}
+
G_GNUC_UNUSED static void
strinfo_builder_append_item (GString *builder,
const gchar *string,
diff --git a/gio/tests/gsettings.c b/gio/tests/gsettings.c
index f86a2f8..b0168a9 100644
--- a/gio/tests/gsettings.c
+++ b/gio/tests/gsettings.c
@@ -14,6 +14,20 @@ static gboolean backend_set;
* to be compiled and installed in the same directory.
*/
+static void
+check_and_free (GVariant *value,
+ const gchar *expected)
+{
+ gchar *printed;
+
+ printed = g_variant_print (value, TRUE);
+ g_assert_cmpstr (printed, ==, expected);
+ g_free (printed);
+
+ g_variant_unref (value);
+}
+
+
/* Just to get warmed up: Read and set a string, and
* verify that can read the changed string back
*/
@@ -1843,6 +1857,34 @@ test_get_mapped (void)
g_object_unref (settings);
}
+static void
+test_get_range (void)
+{
+ GSettings *settings;
+ GVariant *range;
+
+ settings = g_settings_new ("org.gtk.test.range");
+ range = g_settings_get_range (settings, "val");
+ check_and_free (range, "('range', <(2, 44)>)");
+ g_object_unref (settings);
+
+ settings = g_settings_new ("org.gtk.test.enums");
+ range = g_settings_get_range (settings, "test");
+ check_and_free (range, "('enum', <['foo', 'bar', 'baz', 'quux']>)");
+ g_object_unref (settings);
+
+ settings = g_settings_new ("org.gtk.test.enums");
+ range = g_settings_get_range (settings, "f-test");
+ check_and_free (range, "('flags', "
+ "<['mourning', 'laughing', 'talking', 'walking']>)");
+ g_object_unref (settings);
+
+ settings = g_settings_new ("org.gtk.test");
+ range = g_settings_get_range (settings, "greeting");
+ check_and_free (range, "('type', <@as []>)");
+ g_object_unref (settings);
+}
+
int
main (int argc, char *argv[])
{
@@ -1926,6 +1968,7 @@ main (int argc, char *argv[])
g_test_add_func ("/gsettings/list-items", test_list_items);
g_test_add_func ("/gsettings/list-schemas", test_list_schemas);
g_test_add_func ("/gsettings/mapped", test_get_mapped);
+ g_test_add_func ("/gsettings/get-range", test_get_range);
result = g_test_run ();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]