mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-10 03:16:17 +01:00
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.
This commit is contained in:
parent
833e389516
commit
d6d76783ae
@ -1995,7 +1995,7 @@ g_settings_get_has_unapplied (GSettings *settings)
|
|||||||
G_DELAYED_SETTINGS_BACKEND (settings->priv->backend));
|
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:
|
* g_settings_reset:
|
||||||
* @settings: a #GSettings object
|
* @settings: a #GSettings object
|
||||||
@ -2198,6 +2198,88 @@ g_settings_list_children (GSettings *settings)
|
|||||||
return strv;
|
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 */
|
/* Binding {{{1 */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
@ -82,6 +82,8 @@ GSettings * g_settings_new_with_backend_and_path (const g
|
|||||||
const gchar *path);
|
const gchar *path);
|
||||||
gchar ** g_settings_list_children (GSettings *settings);
|
gchar ** g_settings_list_children (GSettings *settings);
|
||||||
gchar ** g_settings_list_keys (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,
|
gboolean g_settings_set_value (GSettings *settings,
|
||||||
const gchar *key,
|
const gchar *key,
|
||||||
|
@ -260,6 +260,37 @@ strinfo_string_from_alias (const guint32 *strinfo,
|
|||||||
return 1 + (const gchar *) &strinfo[GUINT32_TO_LE (strinfo[index]) + 1];
|
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
|
G_GNUC_UNUSED static void
|
||||||
strinfo_builder_append_item (GString *builder,
|
strinfo_builder_append_item (GString *builder,
|
||||||
const gchar *string,
|
const gchar *string,
|
||||||
|
@ -14,6 +14,20 @@ static gboolean backend_set;
|
|||||||
* to be compiled and installed in the same directory.
|
* 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
|
/* Just to get warmed up: Read and set a string, and
|
||||||
* verify that can read the changed string back
|
* verify that can read the changed string back
|
||||||
*/
|
*/
|
||||||
@ -1843,6 +1857,34 @@ test_get_mapped (void)
|
|||||||
g_object_unref (settings);
|
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
|
int
|
||||||
main (int argc, char *argv[])
|
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-items", test_list_items);
|
||||||
g_test_add_func ("/gsettings/list-schemas", test_list_schemas);
|
g_test_add_func ("/gsettings/list-schemas", test_list_schemas);
|
||||||
g_test_add_func ("/gsettings/mapped", test_get_mapped);
|
g_test_add_func ("/gsettings/mapped", test_get_mapped);
|
||||||
|
g_test_add_func ("/gsettings/get-range", test_get_range);
|
||||||
|
|
||||||
result = g_test_run ();
|
result = g_test_run ();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user