mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-08-23 09:28:54 +02:00
Bug 622124 - implement flags for GSettings
Add a <flags> tag to the schema file format and a flags='' attribute to go along with. Add some extra test cases for those. Add new g_settings_{get,set}_flags() calls and support binding to GParamSpecFlags properties. Add test cases.
This commit is contained in:
@@ -2168,6 +2168,8 @@ g_settings_get_strv
|
|||||||
g_settings_set_strv
|
g_settings_set_strv
|
||||||
g_settings_get_enum
|
g_settings_get_enum
|
||||||
g_settings_set_enum
|
g_settings_set_enum
|
||||||
|
g_settings_get_flags
|
||||||
|
g_settings_set_flags
|
||||||
|
|
||||||
<SUBSECTION MappedGet>
|
<SUBSECTION MappedGet>
|
||||||
GSettingsGetMapping
|
GSettingsGetMapping
|
||||||
|
@@ -1477,6 +1477,8 @@ g_settings_get_boolean
|
|||||||
g_settings_set_boolean
|
g_settings_set_boolean
|
||||||
g_settings_get_enum
|
g_settings_get_enum
|
||||||
g_settings_set_enum
|
g_settings_set_enum
|
||||||
|
g_settings_get_flags
|
||||||
|
g_settings_set_flags
|
||||||
g_settings_sync
|
g_settings_sync
|
||||||
g_settings_list_items
|
g_settings_list_items
|
||||||
g_settings_get_mapped
|
g_settings_get_mapped
|
||||||
|
@@ -35,14 +35,32 @@
|
|||||||
#include "strinfo.c"
|
#include "strinfo.c"
|
||||||
|
|
||||||
/* Handling of <enum> {{{1 */
|
/* Handling of <enum> {{{1 */
|
||||||
typedef GString EnumState;
|
typedef struct
|
||||||
|
{
|
||||||
|
GString *strinfo;
|
||||||
|
|
||||||
|
gboolean is_flags;
|
||||||
|
} EnumState;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
enum_state_free (gpointer data)
|
enum_state_free (gpointer data)
|
||||||
{
|
{
|
||||||
EnumState *state = data;
|
EnumState *state = data;
|
||||||
|
|
||||||
g_string_free (state, TRUE);
|
g_string_free (state->strinfo, TRUE);
|
||||||
|
g_slice_free (EnumState, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
EnumState *
|
||||||
|
enum_state_new (gboolean is_flags)
|
||||||
|
{
|
||||||
|
EnumState *state;
|
||||||
|
|
||||||
|
state = g_slice_new (EnumState);
|
||||||
|
state->strinfo = g_string_new (NULL);
|
||||||
|
state->is_flags = is_flags;
|
||||||
|
|
||||||
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -58,12 +76,14 @@ enum_state_add_value (EnumState *state,
|
|||||||
{
|
{
|
||||||
g_set_error (error, G_MARKUP_ERROR,
|
g_set_error (error, G_MARKUP_ERROR,
|
||||||
G_MARKUP_ERROR_INVALID_CONTENT,
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
||||||
"enum nick must be a minimum of 2 characters");
|
"nick must be a minimum of 2 characters");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
value = g_ascii_strtoll (valuestr, &end, 0);
|
value = g_ascii_strtoll (valuestr, &end, 0);
|
||||||
if (*end || value > G_MAXINT32 || value < G_MININT32)
|
if (*end || state->is_flags ?
|
||||||
|
(value > G_MAXUINT32 || value < 0) :
|
||||||
|
(value > G_MAXINT32 || value < G_MININT32))
|
||||||
{
|
{
|
||||||
g_set_error (error, G_MARKUP_ERROR,
|
g_set_error (error, G_MARKUP_ERROR,
|
||||||
G_MARKUP_ERROR_INVALID_CONTENT,
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
||||||
@@ -71,15 +91,38 @@ enum_state_add_value (EnumState *state,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strinfo_builder_contains (state, nick))
|
if (strinfo_builder_contains (state->strinfo, nick))
|
||||||
{
|
{
|
||||||
g_set_error (error, G_MARKUP_ERROR,
|
g_set_error (error, G_MARKUP_ERROR,
|
||||||
G_MARKUP_ERROR_INVALID_CONTENT,
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
||||||
"<value nick='%s'> already specified", nick);
|
"<value nick='%s'/> already specified", nick);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
strinfo_builder_append_item (state, nick, value);
|
if (strinfo_builder_contains_value (state->strinfo, value))
|
||||||
|
{
|
||||||
|
g_set_error (error, G_MARKUP_ERROR,
|
||||||
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
||||||
|
"value='%s' already specified", valuestr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state->is_flags && (value & (value - 1)))
|
||||||
|
{
|
||||||
|
g_set_error (error, G_MARKUP_ERROR,
|
||||||
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
||||||
|
"flags values must have at most 1 bit set");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Since we reject exact duplicates of value='' and we only allow one
|
||||||
|
* bit to be set, it's not possible to have overlaps.
|
||||||
|
*
|
||||||
|
* If we loosen the one-bit-set restriction we need an overlap check.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
strinfo_builder_append_item (state->strinfo, nick, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -91,7 +134,7 @@ enum_state_end (EnumState **state_ptr,
|
|||||||
state = *state_ptr;
|
state = *state_ptr;
|
||||||
*state_ptr = NULL;
|
*state_ptr = NULL;
|
||||||
|
|
||||||
if (state->len == 0)
|
if (state->strinfo->len == 0)
|
||||||
g_set_error_literal (error,
|
g_set_error_literal (error,
|
||||||
G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
|
G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
|
||||||
"<enum> must contain at least one <value>");
|
"<enum> must contain at least one <value>");
|
||||||
@@ -116,6 +159,7 @@ typedef struct
|
|||||||
|
|
||||||
GString *strinfo;
|
GString *strinfo;
|
||||||
gboolean is_enum;
|
gboolean is_enum;
|
||||||
|
gboolean is_flags;
|
||||||
|
|
||||||
GVariant *minimum;
|
GVariant *minimum;
|
||||||
GVariant *maximum;
|
GVariant *maximum;
|
||||||
@@ -131,16 +175,20 @@ typedef struct
|
|||||||
static KeyState *
|
static KeyState *
|
||||||
key_state_new (const gchar *type_string,
|
key_state_new (const gchar *type_string,
|
||||||
const gchar *gettext_domain,
|
const gchar *gettext_domain,
|
||||||
EnumState *enum_data)
|
gboolean is_enum,
|
||||||
|
gboolean is_flags,
|
||||||
|
GString *strinfo)
|
||||||
{
|
{
|
||||||
KeyState *state;
|
KeyState *state;
|
||||||
|
|
||||||
state = g_slice_new0 (KeyState);
|
state = g_slice_new0 (KeyState);
|
||||||
state->type = g_variant_type_new (type_string);
|
state->type = g_variant_type_new (type_string);
|
||||||
state->have_gettext_domain = gettext_domain != NULL;
|
state->have_gettext_domain = gettext_domain != NULL;
|
||||||
|
state->is_enum = is_enum;
|
||||||
|
state->is_flags = is_flags;
|
||||||
|
|
||||||
if ((state->is_enum = (enum_data != NULL)))
|
if (strinfo)
|
||||||
state->strinfo = g_string_new_len (enum_data->str, enum_data->len);
|
state->strinfo = g_string_new_len (strinfo->str, strinfo->len);
|
||||||
else
|
else
|
||||||
state->strinfo = g_string_new (NULL);
|
state->strinfo = g_string_new (NULL);
|
||||||
|
|
||||||
@@ -159,6 +207,7 @@ key_state_override (KeyState *state,
|
|||||||
copy->strinfo = g_string_new_len (state->strinfo->str,
|
copy->strinfo = g_string_new_len (state->strinfo->str,
|
||||||
state->strinfo->len);
|
state->strinfo->len);
|
||||||
copy->is_enum = state->is_enum;
|
copy->is_enum = state->is_enum;
|
||||||
|
copy->is_flags = state->is_flags;
|
||||||
copy->is_override = TRUE;
|
copy->is_override = TRUE;
|
||||||
|
|
||||||
if (state->minimum)
|
if (state->minimum)
|
||||||
@@ -251,6 +300,12 @@ key_state_check_range (KeyState *state,
|
|||||||
"<%s> is not a valid member of "
|
"<%s> is not a valid member of "
|
||||||
"the specified enumerated type", tag);
|
"the specified enumerated type", tag);
|
||||||
|
|
||||||
|
else if (state->is_flags)
|
||||||
|
g_set_error (error, G_MARKUP_ERROR,
|
||||||
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
||||||
|
"<%s> contains string not in the "
|
||||||
|
"specified flags type", tag);
|
||||||
|
|
||||||
else
|
else
|
||||||
g_set_error (error, G_MARKUP_ERROR,
|
g_set_error (error, G_MARKUP_ERROR,
|
||||||
G_MARKUP_ERROR_INVALID_CONTENT,
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
||||||
@@ -442,11 +497,11 @@ key_state_start_aliases (KeyState *state,
|
|||||||
G_MARKUP_ERROR_INVALID_CONTENT,
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
||||||
"<aliases> already specified for this key");
|
"<aliases> already specified for this key");
|
||||||
|
|
||||||
if (!state->is_enum && !state->has_choices)
|
if (!state->is_flags && !state->is_enum && !state->has_choices)
|
||||||
g_set_error_literal (error, G_MARKUP_ERROR,
|
g_set_error_literal (error, G_MARKUP_ERROR,
|
||||||
G_MARKUP_ERROR_INVALID_CONTENT,
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
||||||
"<aliases> can only be specified for keys with "
|
"<aliases> can only be specified for keys with "
|
||||||
"enumerated types or after <choices>");
|
"enumerated or flags types or after <choices>");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -582,6 +637,7 @@ key_state_serialise (KeyState *state)
|
|||||||
state->strinfo = NULL;
|
state->strinfo = NULL;
|
||||||
|
|
||||||
g_variant_builder_add (&builder, "(y@au)",
|
g_variant_builder_add (&builder, "(y@au)",
|
||||||
|
state->is_flags ? 'f' :
|
||||||
state->is_enum ? 'e' : 'c',
|
state->is_enum ? 'e' : 'c',
|
||||||
array);
|
array);
|
||||||
}
|
}
|
||||||
@@ -771,13 +827,15 @@ schema_state_add_child (SchemaState *state,
|
|||||||
static KeyState *
|
static KeyState *
|
||||||
schema_state_add_key (SchemaState *state,
|
schema_state_add_key (SchemaState *state,
|
||||||
GHashTable *enum_table,
|
GHashTable *enum_table,
|
||||||
|
GHashTable *flags_table,
|
||||||
const gchar *name,
|
const gchar *name,
|
||||||
const gchar *type_string,
|
const gchar *type_string,
|
||||||
const gchar *enum_type,
|
const gchar *enum_type,
|
||||||
|
const gchar *flags_type,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
GString *enum_data;
|
|
||||||
SchemaState *node;
|
SchemaState *node;
|
||||||
|
GString *strinfo;
|
||||||
KeyState *key;
|
KeyState *key;
|
||||||
|
|
||||||
if (state->list_of)
|
if (state->list_of)
|
||||||
@@ -820,29 +878,37 @@ schema_state_add_key (SchemaState *state,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((type_string == NULL) == (enum_type == NULL))
|
if ((type_string != NULL) + (enum_type != NULL) + (flags_type != NULL) != 1)
|
||||||
{
|
{
|
||||||
g_set_error (error, G_MARKUP_ERROR,
|
g_set_error (error, G_MARKUP_ERROR,
|
||||||
G_MARKUP_ERROR_MISSING_ATTRIBUTE,
|
G_MARKUP_ERROR_MISSING_ATTRIBUTE,
|
||||||
"exactly one of 'type' or 'enum' must "
|
"exactly one of 'type', 'enum' or 'flags' must "
|
||||||
"be specified as an attribute to <key>");
|
"be specified as an attribute to <key>");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enum_type != NULL)
|
if (type_string == NULL) /* flags or enums was specified */
|
||||||
{
|
{
|
||||||
enum_data = g_hash_table_lookup (enum_table, enum_type);
|
EnumState *enum_state;
|
||||||
|
|
||||||
if (enum_data == NULL)
|
if (enum_type)
|
||||||
|
enum_state = g_hash_table_lookup (enum_table, enum_type);
|
||||||
|
else
|
||||||
|
enum_state = g_hash_table_lookup (flags_table, flags_type);
|
||||||
|
|
||||||
|
|
||||||
|
if (enum_state == NULL)
|
||||||
{
|
{
|
||||||
g_set_error (error, G_MARKUP_ERROR,
|
g_set_error (error, G_MARKUP_ERROR,
|
||||||
G_MARKUP_ERROR_INVALID_CONTENT,
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
||||||
"<enum id='%s'> not (yet) defined.", enum_type);
|
"<%s id='%s'> not (yet) defined.",
|
||||||
|
flags_type ? "flags" : "enum",
|
||||||
|
flags_type ? flags_type : enum_type);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_assert (type_string == NULL);
|
type_string = flags_type ? "as" : "s";
|
||||||
type_string = "s";
|
strinfo = enum_state->strinfo;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -854,10 +920,11 @@ schema_state_add_key (SchemaState *state,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum_data = NULL;
|
strinfo = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
key = key_state_new (type_string, state->gettext_domain, enum_data);
|
key = key_state_new (type_string, state->gettext_domain,
|
||||||
|
enum_type != NULL, flags_type != NULL, strinfo);
|
||||||
g_hash_table_insert (state->keys, g_strdup (name), key);
|
g_hash_table_insert (state->keys, g_strdup (name), key);
|
||||||
|
|
||||||
return key;
|
return key;
|
||||||
@@ -922,13 +989,14 @@ override_state_end (KeyState **key_state,
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
GHashTable *schema_table; /* string -> SchemaState */
|
GHashTable *schema_table; /* string -> SchemaState */
|
||||||
GHashTable *enum_table; /* string -> GString */
|
GHashTable *flags_table; /* string -> EnumState */
|
||||||
|
GHashTable *enum_table; /* string -> EnumState */
|
||||||
|
|
||||||
gchar *schemalist_domain; /* the <schemalist> gettext domain */
|
gchar *schemalist_domain; /* the <schemalist> gettext domain */
|
||||||
|
|
||||||
SchemaState *schema_state; /* non-NULL when inside <schema> */
|
SchemaState *schema_state; /* non-NULL when inside <schema> */
|
||||||
KeyState *key_state; /* non-NULL when inside <key> */
|
KeyState *key_state; /* non-NULL when inside <key> */
|
||||||
GString *enum_state; /* non-NULL when inside <enum> */
|
EnumState *enum_state; /* non-NULL when inside <enum> */
|
||||||
|
|
||||||
GString *string; /* non-NULL when accepting text */
|
GString *string; /* non-NULL when accepting text */
|
||||||
} ParseState;
|
} ParseState;
|
||||||
@@ -1047,18 +1115,22 @@ parse_state_start_schema (ParseState *state,
|
|||||||
static void
|
static void
|
||||||
parse_state_start_enum (ParseState *state,
|
parse_state_start_enum (ParseState *state,
|
||||||
const gchar *id,
|
const gchar *id,
|
||||||
|
gboolean is_flags,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
if (g_hash_table_lookup (state->enum_table, id))
|
GHashTable *table = is_flags ? state->flags_table : state->enum_table;
|
||||||
|
|
||||||
|
if (g_hash_table_lookup (table, id))
|
||||||
{
|
{
|
||||||
g_set_error (error, G_MARKUP_ERROR,
|
g_set_error (error, G_MARKUP_ERROR,
|
||||||
G_MARKUP_ERROR_INVALID_CONTENT,
|
G_MARKUP_ERROR_INVALID_CONTENT,
|
||||||
"<enum id='%s'> already specified", id);
|
"<%s id='%s'> already specified",
|
||||||
|
is_flags ? "flags" : "enum", id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->enum_state = g_string_new (NULL);
|
state->enum_state = enum_state_new (is_flags);
|
||||||
g_hash_table_insert (state->enum_table, g_strdup (id), state->enum_state);
|
g_hash_table_insert (table, g_strdup (id), state->enum_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* GMarkup Parser Functions {{{1 */
|
/* GMarkup Parser Functions {{{1 */
|
||||||
@@ -1117,12 +1189,19 @@ start_element (GMarkupParseContext *context,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (strcmp (element_name, "enum") == 0 ||
|
else if (strcmp (element_name, "enum") == 0)
|
||||||
strcmp (element_name, "flags") == 0)
|
|
||||||
{
|
{
|
||||||
const gchar *id;
|
const gchar *id;
|
||||||
if (COLLECT (STRING, "id", &id))
|
if (COLLECT (STRING, "id", &id))
|
||||||
parse_state_start_enum (state, id, error);
|
parse_state_start_enum (state, id, FALSE, error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (strcmp (element_name, "flags") == 0)
|
||||||
|
{
|
||||||
|
const gchar *id;
|
||||||
|
if (COLLECT (STRING, "id", &id))
|
||||||
|
parse_state_start_enum (state, id, TRUE, error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1133,16 +1212,19 @@ start_element (GMarkupParseContext *context,
|
|||||||
{
|
{
|
||||||
if (strcmp (element_name, "key") == 0)
|
if (strcmp (element_name, "key") == 0)
|
||||||
{
|
{
|
||||||
const gchar *name, *type_string, *enum_type;
|
const gchar *name, *type_string, *enum_type, *flags_type;
|
||||||
|
|
||||||
if (COLLECT (STRING, "name", &name,
|
if (COLLECT (STRING, "name", &name,
|
||||||
OPTIONAL | STRING, "type", &type_string,
|
OPTIONAL | STRING, "type", &type_string,
|
||||||
OPTIONAL | STRING, "enum", &enum_type))
|
OPTIONAL | STRING, "enum", &enum_type,
|
||||||
|
OPTIONAL | STRING, "flags", &flags_type))
|
||||||
|
|
||||||
state->key_state = schema_state_add_key (state->schema_state,
|
state->key_state = schema_state_add_key (state->schema_state,
|
||||||
state->enum_table,
|
state->enum_table,
|
||||||
|
state->flags_table,
|
||||||
name, type_string,
|
name, type_string,
|
||||||
enum_type, error);
|
enum_type, flags_type,
|
||||||
|
error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (strcmp (element_name, "child") == 0)
|
else if (strcmp (element_name, "child") == 0)
|
||||||
@@ -1481,6 +1563,9 @@ parse_gschema_files (gchar **files,
|
|||||||
state.enum_table = g_hash_table_new_full (g_str_hash, g_str_equal,
|
state.enum_table = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||||
g_free, enum_state_free);
|
g_free, enum_state_free);
|
||||||
|
|
||||||
|
state.flags_table = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||||
|
g_free, enum_state_free);
|
||||||
|
|
||||||
state.schema_table = g_hash_table_new_full (g_str_hash, g_str_equal,
|
state.schema_table = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||||
g_free, schema_state_free);
|
g_free, schema_state_free);
|
||||||
|
|
||||||
|
@@ -392,6 +392,34 @@ g_settings_set_mapping (const GValue *value,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (G_VALUE_HOLDS_FLAGS (value))
|
||||||
|
{
|
||||||
|
GVariantBuilder builder;
|
||||||
|
GFlagsValue *flagsval;
|
||||||
|
GFlagsClass *fclass;
|
||||||
|
guint flags;
|
||||||
|
|
||||||
|
fclass = g_type_class_peek (G_VALUE_TYPE (value));
|
||||||
|
flags = g_value_get_flags (value);
|
||||||
|
|
||||||
|
g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
|
||||||
|
while (flags)
|
||||||
|
{
|
||||||
|
flagsval = g_flags_get_first_value (fclass, flags);
|
||||||
|
|
||||||
|
if (flagsval == NULL)
|
||||||
|
{
|
||||||
|
g_variant_builder_clear (&builder);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_variant_builder_add (&builder, "s", flagsval->value_nick);
|
||||||
|
flags &= ~flagsval->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_variant_builder_end (&builder);
|
||||||
|
}
|
||||||
|
|
||||||
type_string = g_variant_type_dup_string (expected_type);
|
type_string = g_variant_type_dup_string (expected_type);
|
||||||
g_critical ("No GSettings bind handler for type \"%s\".", type_string);
|
g_critical ("No GSettings bind handler for type \"%s\".", type_string);
|
||||||
g_free (type_string);
|
g_free (type_string);
|
||||||
@@ -447,8 +475,7 @@ g_settings_get_mapping (GValue *value,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING) &&
|
else if (G_VALUE_HOLDS_ENUM (value))
|
||||||
G_VALUE_HOLDS_ENUM (value))
|
|
||||||
{
|
{
|
||||||
GEnumClass *eclass;
|
GEnumClass *eclass;
|
||||||
GEnumValue *evalue;
|
GEnumValue *evalue;
|
||||||
@@ -469,6 +496,38 @@ g_settings_get_mapping (GValue *value,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE ("as")))
|
||||||
|
{
|
||||||
|
if (G_VALUE_HOLDS_FLAGS (value))
|
||||||
|
{
|
||||||
|
GFlagsClass *fclass;
|
||||||
|
GFlagsValue *fvalue;
|
||||||
|
const gchar *nick;
|
||||||
|
GVariantIter iter;
|
||||||
|
guint flags = 0;
|
||||||
|
|
||||||
|
fclass = g_type_class_peek (G_VALUE_TYPE (value));
|
||||||
|
|
||||||
|
g_variant_iter_init (&iter, variant);
|
||||||
|
while (g_variant_iter_next (&iter, "&s", &nick))
|
||||||
|
{
|
||||||
|
fvalue = g_flags_get_value_by_nick (fclass, nick);
|
||||||
|
|
||||||
|
if (fvalue)
|
||||||
|
flags |= fvalue->value;
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_warning ("Unable to lookup flags nick '%s' via GType\n",
|
||||||
|
nick);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_value_set_flags (value, flags);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE ("ay")))
|
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE ("ay")))
|
||||||
{
|
{
|
||||||
g_value_set_string (value, g_variant_get_byte_array (variant, NULL));
|
g_value_set_string (value, g_variant_get_byte_array (variant, NULL));
|
||||||
@@ -512,6 +571,8 @@ g_settings_mapping_is_compatible (GType gvalue_type,
|
|||||||
g_variant_type_equal (variant_type, G_VARIANT_TYPE_SIGNATURE));
|
g_variant_type_equal (variant_type, G_VARIANT_TYPE_SIGNATURE));
|
||||||
else if (G_TYPE_IS_ENUM (gvalue_type))
|
else if (G_TYPE_IS_ENUM (gvalue_type))
|
||||||
ok = g_variant_type_equal (variant_type, G_VARIANT_TYPE_STRING);
|
ok = g_variant_type_equal (variant_type, G_VARIANT_TYPE_STRING);
|
||||||
|
else if (G_TYPE_IS_FLAGS (gvalue_type))
|
||||||
|
ok = g_variant_type_equal (variant_type, G_VARIANT_TYPE ("as"));
|
||||||
|
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
194
gio/gsettings.c
194
gio/gsettings.c
@@ -831,7 +831,7 @@ g_settings_new_with_backend_and_path (const gchar *schema,
|
|||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Internal read/write utilities, enum conversion, validation {{{1 */
|
/* Internal read/write utilities, enum/flags conversion, validation {{{1 */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
GSettings *settings;
|
GSettings *settings;
|
||||||
@@ -839,7 +839,9 @@ typedef struct
|
|||||||
|
|
||||||
GSettingsSchema *schema;
|
GSettingsSchema *schema;
|
||||||
|
|
||||||
gboolean is_enum;
|
guint is_flags : 1;
|
||||||
|
guint is_enum : 1;
|
||||||
|
|
||||||
const guint32 *strinfo;
|
const guint32 *strinfo;
|
||||||
gsize strinfo_length;
|
gsize strinfo_length;
|
||||||
|
|
||||||
@@ -879,9 +881,16 @@ g_settings_get_key_info (GSettingsKeyInfo *info,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'e':
|
case 'e':
|
||||||
/* enumerated types, ... */
|
/* enumerated types... */
|
||||||
info->is_enum = TRUE;
|
info->is_enum = TRUE;
|
||||||
case 'c':
|
goto choice;
|
||||||
|
|
||||||
|
case 'f':
|
||||||
|
/* flags... */
|
||||||
|
info->is_flags = TRUE;
|
||||||
|
goto choice;
|
||||||
|
|
||||||
|
choice: case 'c':
|
||||||
/* ..., choices, aliases */
|
/* ..., choices, aliases */
|
||||||
info->strinfo = g_variant_get_fixed_array (data,
|
info->strinfo = g_variant_get_fixed_array (data,
|
||||||
&info->strinfo_length,
|
&info->strinfo_length,
|
||||||
@@ -956,7 +965,7 @@ g_settings_range_check (GSettingsKeyInfo *info,
|
|||||||
g_variant_iter_init (&iter, value);
|
g_variant_iter_init (&iter, value);
|
||||||
while (ok && (child = g_variant_iter_next_value (&iter)))
|
while (ok && (child = g_variant_iter_next_value (&iter)))
|
||||||
{
|
{
|
||||||
ok = g_settings_range_check (info, value);
|
ok = g_settings_range_check (info, child);
|
||||||
g_variant_unref (child);
|
g_variant_unref (child);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -992,6 +1001,7 @@ g_settings_range_fixup (GSettingsKeyInfo *info,
|
|||||||
GVariantIter iter;
|
GVariantIter iter;
|
||||||
GVariant *child;
|
GVariant *child;
|
||||||
|
|
||||||
|
g_variant_iter_init (&iter, value);
|
||||||
g_variant_builder_init (&builder, g_variant_get_type (value));
|
g_variant_builder_init (&builder, g_variant_get_type (value));
|
||||||
|
|
||||||
while ((child = g_variant_iter_next_value (&iter)))
|
while ((child = g_variant_iter_next_value (&iter)))
|
||||||
@@ -1123,7 +1133,64 @@ g_settings_from_enum (GSettingsKeyInfo *info,
|
|||||||
if (string == NULL)
|
if (string == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return g_variant_ref_sink (g_variant_new_string (string));
|
return g_variant_new_string (string);
|
||||||
|
}
|
||||||
|
|
||||||
|
static guint
|
||||||
|
g_settings_to_flags (GSettingsKeyInfo *info,
|
||||||
|
GVariant *value)
|
||||||
|
{
|
||||||
|
GVariantIter iter;
|
||||||
|
const gchar *flag;
|
||||||
|
guint result;
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
g_variant_iter_init (&iter, value);
|
||||||
|
while (g_variant_iter_next (&iter, "&s", &flag))
|
||||||
|
{
|
||||||
|
gboolean it_worked;
|
||||||
|
guint flag_value;
|
||||||
|
|
||||||
|
it_worked = strinfo_enum_from_string (info->strinfo,
|
||||||
|
info->strinfo_length,
|
||||||
|
flag, &flag_value);
|
||||||
|
/* as in g_settings_to_enum() */
|
||||||
|
g_assert (it_worked);
|
||||||
|
|
||||||
|
result |= flag_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GVariant *
|
||||||
|
g_settings_from_flags (GSettingsKeyInfo *info,
|
||||||
|
guint value)
|
||||||
|
{
|
||||||
|
GVariantBuilder builder;
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
|
||||||
|
|
||||||
|
for (i = 0; i < 32; i++)
|
||||||
|
if (value & (1u << i))
|
||||||
|
{
|
||||||
|
const gchar *string;
|
||||||
|
|
||||||
|
string = strinfo_string_from_enum (info->strinfo,
|
||||||
|
info->strinfo_length,
|
||||||
|
1u << i);
|
||||||
|
|
||||||
|
if (string == NULL)
|
||||||
|
{
|
||||||
|
g_variant_builder_clear (&builder);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_variant_builder_add (&builder, "s", string);
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_variant_builder_end (&builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Public Get/Set API {{{1 (get, get_value, set, set_value, get_mapped) */
|
/* Public Get/Set API {{{1 (get, get_value, set, set_value, get_mapped) */
|
||||||
@@ -1235,7 +1302,7 @@ g_settings_get_enum (GSettings *settings,
|
|||||||
* schema for @settings or is not marked as an enumerated type, or for
|
* schema for @settings or is not marked as an enumerated type, or for
|
||||||
* @value not to be a valid value for the named type.
|
* @value not to be a valid value for the named type.
|
||||||
*
|
*
|
||||||
* After performing the write, accessing @key directly
|
* After performing the write, accessing @key directly with
|
||||||
* g_settings_get_string() will return the 'nick' associated with
|
* g_settings_get_string() will return the 'nick' associated with
|
||||||
* @value.
|
* @value.
|
||||||
**/
|
**/
|
||||||
@@ -1271,7 +1338,118 @@ g_settings_set_enum (GSettings *settings,
|
|||||||
|
|
||||||
success = g_settings_write_to_backend (&info, variant);
|
success = g_settings_write_to_backend (&info, variant);
|
||||||
g_settings_free_key_info (&info);
|
g_settings_free_key_info (&info);
|
||||||
g_variant_unref (variant);
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_settings_get_flags:
|
||||||
|
* @settings: a #GSettings object
|
||||||
|
* @key: the key to get the value for
|
||||||
|
* @returns: the flags value
|
||||||
|
*
|
||||||
|
* Gets the value that is stored in @settings for @key and converts it
|
||||||
|
* to the flags value that it represents.
|
||||||
|
*
|
||||||
|
* In order to use this function the type of the value must be an array
|
||||||
|
* of strings and it must be marked in the schema file as an flags type.
|
||||||
|
*
|
||||||
|
* It is a programmer error to give a @key that isn't contained in the
|
||||||
|
* schema for @settings or is not marked as a flags type.
|
||||||
|
*
|
||||||
|
* If the value stored in the configuration database is not a valid
|
||||||
|
* value for the flags type then this function will return the default
|
||||||
|
* value.
|
||||||
|
*
|
||||||
|
* Since: 2.26
|
||||||
|
**/
|
||||||
|
guint
|
||||||
|
g_settings_get_flags (GSettings *settings,
|
||||||
|
const gchar *key)
|
||||||
|
{
|
||||||
|
GSettingsKeyInfo info;
|
||||||
|
GVariant *value;
|
||||||
|
guint result;
|
||||||
|
|
||||||
|
g_return_val_if_fail (G_IS_SETTINGS (settings), -1);
|
||||||
|
g_return_val_if_fail (key != NULL, -1);
|
||||||
|
|
||||||
|
g_settings_get_key_info (&info, settings, key);
|
||||||
|
|
||||||
|
if (!info.is_flags)
|
||||||
|
{
|
||||||
|
g_critical ("g_settings_get_flags() called on key `%s' which is not "
|
||||||
|
"associated with a flags type", info.key);
|
||||||
|
g_settings_free_key_info (&info);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = g_settings_read_from_backend (&info);
|
||||||
|
|
||||||
|
if (value == NULL)
|
||||||
|
value = g_settings_get_translated_default (&info);
|
||||||
|
|
||||||
|
if (value == NULL)
|
||||||
|
value = g_variant_ref (info.default_value);
|
||||||
|
|
||||||
|
result = g_settings_to_flags (&info, value);
|
||||||
|
g_settings_free_key_info (&info);
|
||||||
|
g_variant_unref (value);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_settings_set_flags:
|
||||||
|
* @settings: a #GSettings object
|
||||||
|
* @key: a key, within @settings
|
||||||
|
* @value: a flags value
|
||||||
|
* @returns: %TRUE, if the set succeeds
|
||||||
|
*
|
||||||
|
* Looks up the flags type nicks for the bits specified by @value, puts
|
||||||
|
* them in an array of strings and writes the array to @key, withing
|
||||||
|
* @settings.
|
||||||
|
*
|
||||||
|
* It is a programmer error to give a @key that isn't contained in the
|
||||||
|
* schema for @settings or is not marked as a flags type, or for @value
|
||||||
|
* to contain any bits that are not value for the named type.
|
||||||
|
*
|
||||||
|
* After performing the write, accessing @key directly with
|
||||||
|
* g_settings_get_strv() will return an array of 'nicks'; one for each
|
||||||
|
* bit in @value.
|
||||||
|
**/
|
||||||
|
gboolean
|
||||||
|
g_settings_set_flags (GSettings *settings,
|
||||||
|
const gchar *key,
|
||||||
|
guint value)
|
||||||
|
{
|
||||||
|
GSettingsKeyInfo info;
|
||||||
|
GVariant *variant;
|
||||||
|
gboolean success;
|
||||||
|
|
||||||
|
g_return_val_if_fail (G_IS_SETTINGS (settings), FALSE);
|
||||||
|
g_return_val_if_fail (key != NULL, FALSE);
|
||||||
|
|
||||||
|
g_settings_get_key_info (&info, settings, key);
|
||||||
|
|
||||||
|
if (!info.is_flags)
|
||||||
|
{
|
||||||
|
g_critical ("g_settings_set_flags() called on key `%s' which is not "
|
||||||
|
"associated with a flags type", info.key);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(variant = g_settings_from_flags (&info, value)))
|
||||||
|
{
|
||||||
|
g_critical ("g_settings_set_flags(): invalid flags value 0x%08x "
|
||||||
|
"for key `%s' in schema `%s'. Doing nothing.",
|
||||||
|
value, info.key, info.settings->priv->schema_name);
|
||||||
|
g_settings_free_key_info (&info);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
success = g_settings_write_to_backend (&info, variant);
|
||||||
|
g_settings_free_key_info (&info);
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
@@ -126,6 +126,11 @@ gint g_settings_get_enum (GSettin
|
|||||||
gboolean g_settings_set_enum (GSettings *settings,
|
gboolean g_settings_set_enum (GSettings *settings,
|
||||||
const gchar *key,
|
const gchar *key,
|
||||||
gint value);
|
gint value);
|
||||||
|
guint g_settings_get_flags (GSettings *settings,
|
||||||
|
const gchar *key);
|
||||||
|
gboolean g_settings_set_flags (GSettings *settings,
|
||||||
|
const gchar *key,
|
||||||
|
guint value);
|
||||||
GSettings * g_settings_get_child (GSettings *settings,
|
GSettings * g_settings_get_child (GSettings *settings,
|
||||||
const gchar *name);
|
const gchar *name);
|
||||||
|
|
||||||
|
@@ -309,3 +309,11 @@ strinfo_builder_contains (GString *builder,
|
|||||||
strinfo_find_string ((const guint32 *) builder->str,
|
strinfo_find_string ((const guint32 *) builder->str,
|
||||||
builder->len / 4, string, TRUE) != -1;
|
builder->len / 4, string, TRUE) != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
G_GNUC_UNUSED static gboolean
|
||||||
|
strinfo_builder_contains_value (GString *builder,
|
||||||
|
guint value)
|
||||||
|
{
|
||||||
|
return strinfo_string_from_enum ((const guint32 *) builder->str,
|
||||||
|
builder->len / 4, value) != NULL;
|
||||||
|
}
|
||||||
|
@@ -300,8 +300,15 @@ schema_tests = \
|
|||||||
schema-tests/enum-with-choice.gschema.xml \
|
schema-tests/enum-with-choice.gschema.xml \
|
||||||
schema-tests/enum-with-invalid-alias.gschema.xml \
|
schema-tests/enum-with-invalid-alias.gschema.xml \
|
||||||
schema-tests/enum-with-repeated-alias.gschema.xml \
|
schema-tests/enum-with-repeated-alias.gschema.xml \
|
||||||
|
schema-tests/enum-with-repeated-nick.gschema.xml \
|
||||||
|
schema-tests/enum-with-repeated-value.gschema.xml \
|
||||||
schema-tests/enum-with-shadow-alias.gschema.xml \
|
schema-tests/enum-with-shadow-alias.gschema.xml \
|
||||||
schema-tests/enum.gschema.xml \
|
schema-tests/enum.gschema.xml \
|
||||||
|
schema-tests/flags-aliased-default.gschema.xml \
|
||||||
|
schema-tests/flags-bad-default.gschema.xml \
|
||||||
|
schema-tests/flags-more-than-one-bit.gschema.xml \
|
||||||
|
schema-tests/flags-with-enum-attr.gschema.xml \
|
||||||
|
schema-tests/flags-with-enum-tag.gschema.xml \
|
||||||
schema-tests/extend-and-shadow-indirect.gschema.xml \
|
schema-tests/extend-and-shadow-indirect.gschema.xml \
|
||||||
schema-tests/extend-and-shadow.gschema.xml \
|
schema-tests/extend-and-shadow.gschema.xml \
|
||||||
schema-tests/extend-missing.gschema.xml \
|
schema-tests/extend-missing.gschema.xml \
|
||||||
|
@@ -71,6 +71,8 @@ static const SchemaTest tests[] = {
|
|||||||
{ "enum-with-aliases", NULL, NULL },
|
{ "enum-with-aliases", NULL, NULL },
|
||||||
{ "enum-with-invalid-alias", NULL, "*'banger' is not in enumerated type*" },
|
{ "enum-with-invalid-alias", NULL, "*'banger' is not in enumerated type*" },
|
||||||
{ "enum-with-repeated-alias", NULL, "*<alias value='sausages'/> already specified*" },
|
{ "enum-with-repeated-alias", NULL, "*<alias value='sausages'/> already specified*" },
|
||||||
|
{ "enum-with-repeated-nick", NULL, "*<value nick='spam'/> already specified*" },
|
||||||
|
{ "enum-with-repeated-value", NULL, "*value='1' already specified*" },
|
||||||
{ "enum-with-chained-alias", NULL, "*'sausages' is not in enumerated type*" },
|
{ "enum-with-chained-alias", NULL, "*'sausages' is not in enumerated type*" },
|
||||||
{ "enum-with-shadow-alias", NULL, "*'mash' is already a member of the enum*" },
|
{ "enum-with-shadow-alias", NULL, "*'mash' is already a member of the enum*" },
|
||||||
{ "enum-with-choice", NULL, "*<choices> can not be specified*" },
|
{ "enum-with-choice", NULL, "*<choices> can not be specified*" },
|
||||||
@@ -80,7 +82,7 @@ static const SchemaTest tests[] = {
|
|||||||
{ "bad-choice", NULL, "*<default> contains string not in <choices>*" },
|
{ "bad-choice", NULL, "*<default> contains string not in <choices>*" },
|
||||||
{ "choice-bad", NULL, "*<default> contains string not in <choices>*" },
|
{ "choice-bad", NULL, "*<default> contains string not in <choices>*" },
|
||||||
{ "choice-badtype", NULL, "*<choices> not allowed for keys of type 'i'*" },
|
{ "choice-badtype", NULL, "*<choices> not allowed for keys of type 'i'*" },
|
||||||
{ "bare-alias", NULL, "*enumerated types or after <choices>*" },
|
{ "bare-alias", NULL, "*enumerated or flags types or after <choices>*" },
|
||||||
{ "choice-alias", NULL, NULL },
|
{ "choice-alias", NULL, NULL },
|
||||||
{ "default-in-aliases", NULL, "*<default> contains string not in <choices>*" },
|
{ "default-in-aliases", NULL, "*<default> contains string not in <choices>*" },
|
||||||
{ "choice-invalid-alias", NULL, "*'befor' is not in <choices>*" },
|
{ "choice-invalid-alias", NULL, "*'befor' is not in <choices>*" },
|
||||||
@@ -109,7 +111,12 @@ static const SchemaTest tests[] = {
|
|||||||
{ "override-range-error", NULL, "*<override> is not contained in the specified range*"},
|
{ "override-range-error", NULL, "*<override> is not contained in the specified range*"},
|
||||||
{ "override-then-key", NULL, "*shadows <key name='foo'> in <schema id='base'>*" },
|
{ "override-then-key", NULL, "*shadows <key name='foo'> in <schema id='base'>*" },
|
||||||
{ "override-twice", NULL, "*<override name='foo'> already specified*" },
|
{ "override-twice", NULL, "*<override name='foo'> already specified*" },
|
||||||
{ "override-type-error", NULL, "*invalid character in number*" }
|
{ "override-type-error", NULL, "*invalid character in number*" },
|
||||||
|
{ "flags-aliased-default", NULL, "*<default> * not in the specified flags type*" },
|
||||||
|
{ "flags-bad-default", NULL, "*<default> * not in the specified flags type*" },
|
||||||
|
{ "flags-more-than-one-bit", NULL, "*flags values must have at most 1 bit set*" },
|
||||||
|
{ "flags-with-enum-attr", NULL, "*<enum id='flags'> not (yet) defined*" },
|
||||||
|
{ "flags-with-enum-tag", NULL, "*<flags id='flags'> not (yet) defined*" }
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@@ -1249,8 +1249,6 @@ test_strinfo (void)
|
|||||||
g_assert (!strinfo_is_string_valid (strinfo, length, "quux"));
|
g_assert (!strinfo_is_string_valid (strinfo, length, "quux"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_enums (void)
|
test_enums (void)
|
||||||
{
|
{
|
||||||
@@ -1276,6 +1274,11 @@ test_enums (void)
|
|||||||
g_settings_set_string (settings, "test", "qux");
|
g_settings_set_string (settings, "test", "qux");
|
||||||
g_test_trap_assert_failed ();
|
g_test_trap_assert_failed ();
|
||||||
g_test_trap_assert_stderr ("*g_settings_range_check*");
|
g_test_trap_assert_stderr ("*g_settings_range_check*");
|
||||||
|
|
||||||
|
if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
|
||||||
|
g_settings_get_flags (settings, "test");
|
||||||
|
g_test_trap_assert_failed ();
|
||||||
|
g_test_trap_assert_stderr ("*not associated with a flags*");
|
||||||
}
|
}
|
||||||
|
|
||||||
str = g_settings_get_string (settings, "test");
|
str = g_settings_get_string (settings, "test");
|
||||||
@@ -1303,6 +1306,78 @@ test_enums (void)
|
|||||||
g_assert_cmpint (g_settings_get_enum (settings, "test"), ==, TEST_ENUM_QUUX);
|
g_assert_cmpint (g_settings_get_enum (settings, "test"), ==, TEST_ENUM_QUUX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_flags (void)
|
||||||
|
{
|
||||||
|
GSettings *settings, *direct;
|
||||||
|
gchar **strv;
|
||||||
|
gchar *str;
|
||||||
|
|
||||||
|
settings = g_settings_new ("org.gtk.test.enums");
|
||||||
|
direct = g_settings_new ("org.gtk.test.enums.direct");
|
||||||
|
|
||||||
|
if (!backend_set)
|
||||||
|
{
|
||||||
|
if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
|
||||||
|
g_settings_get_flags (direct, "test");
|
||||||
|
g_test_trap_assert_failed ();
|
||||||
|
g_test_trap_assert_stderr ("*not associated with a flags*");
|
||||||
|
|
||||||
|
if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
|
||||||
|
g_settings_set_flags (settings, "f-test", 0x42);
|
||||||
|
g_test_trap_assert_failed ();
|
||||||
|
g_test_trap_assert_stderr ("*invalid flags value 0x00000042*");
|
||||||
|
|
||||||
|
if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
|
||||||
|
g_settings_set_strv (settings, "f-test",
|
||||||
|
(const gchar **) g_strsplit ("rock", ",", 0));
|
||||||
|
g_test_trap_assert_failed ();
|
||||||
|
g_test_trap_assert_stderr ("*g_settings_range_check*");
|
||||||
|
|
||||||
|
if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
|
||||||
|
g_settings_get_enum (settings, "f-test");
|
||||||
|
g_test_trap_assert_failed ();
|
||||||
|
g_test_trap_assert_stderr ("*not associated with an enum*");
|
||||||
|
}
|
||||||
|
|
||||||
|
strv = g_settings_get_strv (settings, "f-test");
|
||||||
|
str = g_strjoinv (",", strv);
|
||||||
|
g_assert_cmpstr (str, ==, "");
|
||||||
|
g_strfreev (strv);
|
||||||
|
g_free (str);
|
||||||
|
|
||||||
|
g_settings_set_flags (settings, "f-test",
|
||||||
|
TEST_FLAGS_WALKING | TEST_FLAGS_TALKING);
|
||||||
|
|
||||||
|
strv = g_settings_get_strv (settings, "f-test");
|
||||||
|
str = g_strjoinv (",", strv);
|
||||||
|
g_assert_cmpstr (str, ==, "talking,walking");
|
||||||
|
g_strfreev (strv);
|
||||||
|
g_free (str);
|
||||||
|
|
||||||
|
g_assert_cmpint (g_settings_get_flags (settings, "f-test"), ==,
|
||||||
|
TEST_FLAGS_WALKING | TEST_FLAGS_TALKING);
|
||||||
|
|
||||||
|
strv = g_strsplit ("speaking,laughing", ",", 0);
|
||||||
|
g_settings_set_strv (direct, "f-test", (const gchar **) strv);
|
||||||
|
g_strfreev (strv);
|
||||||
|
|
||||||
|
strv = g_settings_get_strv (direct, "f-test");
|
||||||
|
str = g_strjoinv (",", strv);
|
||||||
|
g_assert_cmpstr (str, ==, "speaking,laughing");
|
||||||
|
g_strfreev (strv);
|
||||||
|
g_free (str);
|
||||||
|
|
||||||
|
strv = g_settings_get_strv (settings, "f-test");
|
||||||
|
str = g_strjoinv (",", strv);
|
||||||
|
g_assert_cmpstr (str, ==, "talking,laughing");
|
||||||
|
g_strfreev (strv);
|
||||||
|
g_free (str);
|
||||||
|
|
||||||
|
g_assert_cmpint (g_settings_get_flags (settings, "f-test"), ==,
|
||||||
|
TEST_FLAGS_TALKING | TEST_FLAGS_LAUGHING);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_range (void)
|
test_range (void)
|
||||||
{
|
{
|
||||||
@@ -1408,6 +1483,7 @@ main (int argc, char *argv[])
|
|||||||
g_test_add_func ("/gsettings/child-schema", test_child_schema);
|
g_test_add_func ("/gsettings/child-schema", test_child_schema);
|
||||||
g_test_add_func ("/gsettings/strinfo", test_strinfo);
|
g_test_add_func ("/gsettings/strinfo", test_strinfo);
|
||||||
g_test_add_func ("/gsettings/enums", test_enums);
|
g_test_add_func ("/gsettings/enums", test_enums);
|
||||||
|
g_test_add_func ("/gsettings/flags", test_flags);
|
||||||
g_test_add_func ("/gsettings/range", test_range);
|
g_test_add_func ("/gsettings/range", test_range);
|
||||||
|
|
||||||
result = g_test_run ();
|
result = g_test_run ();
|
||||||
|
@@ -99,9 +99,18 @@
|
|||||||
<alias value='qux' target='quux'/>
|
<alias value='qux' target='quux'/>
|
||||||
</aliases>
|
</aliases>
|
||||||
</key>
|
</key>
|
||||||
|
<key name='f-test' flags='org.gtk.test.TestFlags'>
|
||||||
|
<default>[]</default>
|
||||||
|
<aliases>
|
||||||
|
<alias value='speaking' target='talking'/>
|
||||||
|
</aliases>
|
||||||
|
</key>
|
||||||
</schema>
|
</schema>
|
||||||
|
|
||||||
<schema id='org.gtk.test.enums.direct' path='/tests/enums/'>
|
<schema id='org.gtk.test.enums.direct' path='/tests/enums/'>
|
||||||
|
<key name='f-test' type='as'>
|
||||||
|
<default>[]</default>
|
||||||
|
</key>
|
||||||
<key name='test' type='s'>
|
<key name='test' type='s'>
|
||||||
<default>'bar'</default>
|
<default>'bar'</default>
|
||||||
</key>
|
</key>
|
||||||
|
10
gio/tests/schema-tests/enum-with-repeated-nick.gschema.xml
Normal file
10
gio/tests/schema-tests/enum-with-repeated-nick.gschema.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<schemalist>
|
||||||
|
<enum id='org.gtk.test.MyEnum'>
|
||||||
|
<value nick='nospam' value='0'/>
|
||||||
|
<value nick='spam' value='1'/>
|
||||||
|
<value nick='ham' value='2'/>
|
||||||
|
<value nick='eggs' value='3'/>
|
||||||
|
<value nick='bangers' value='4'/>
|
||||||
|
<value nick='spam' value='5'/>
|
||||||
|
</enum>
|
||||||
|
</schemalist>
|
10
gio/tests/schema-tests/enum-with-repeated-value.gschema.xml
Normal file
10
gio/tests/schema-tests/enum-with-repeated-value.gschema.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<schemalist>
|
||||||
|
<enum id='org.gtk.test.MyEnum'>
|
||||||
|
<value nick='nospam' value='0'/>
|
||||||
|
<value nick='spam' value='1'/>
|
||||||
|
<value nick='ham' value='2'/>
|
||||||
|
<value nick='eggs' value='3'/>
|
||||||
|
<value nick='bangers' value='4'/>
|
||||||
|
<value nick='mash' value='1'/>
|
||||||
|
</enum>
|
||||||
|
</schemalist>
|
19
gio/tests/schema-tests/flags-aliased-default.gschema.xml
Normal file
19
gio/tests/schema-tests/flags-aliased-default.gschema.xml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<schemalist>
|
||||||
|
<flags id='flags'>
|
||||||
|
<value nick='none' value='0'/>
|
||||||
|
<value nick='mourning' value='1'/>
|
||||||
|
<value nick='laughing' value='2'/>
|
||||||
|
<value nick='talking' value='4'/>
|
||||||
|
<value nick='walking' value='8'/>
|
||||||
|
</flags>
|
||||||
|
|
||||||
|
<schema id='xyz'>
|
||||||
|
<key name='abc' flags='flags'>
|
||||||
|
<aliases>
|
||||||
|
<alias value='speaking' target='talking'/>
|
||||||
|
</aliases>
|
||||||
|
<default>['speaking']</default>
|
||||||
|
</key>
|
||||||
|
</schema>
|
||||||
|
</schemalist>
|
||||||
|
|
16
gio/tests/schema-tests/flags-bad-default.gschema.xml
Normal file
16
gio/tests/schema-tests/flags-bad-default.gschema.xml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<schemalist>
|
||||||
|
<flags id='flags'>
|
||||||
|
<value nick='none' value='0'/>
|
||||||
|
<value nick='mourning' value='1'/>
|
||||||
|
<value nick='laughing' value='2'/>
|
||||||
|
<value nick='talking' value='4'/>
|
||||||
|
<value nick='walking' value='8'/>
|
||||||
|
</flags>
|
||||||
|
|
||||||
|
<schema id='xyz'>
|
||||||
|
<key name='abc' flags='flags'>
|
||||||
|
<default>['speaking']</default>
|
||||||
|
</key>
|
||||||
|
</schema>
|
||||||
|
</schemalist>
|
||||||
|
|
10
gio/tests/schema-tests/flags-more-than-one-bit.gschema.xml
Normal file
10
gio/tests/schema-tests/flags-more-than-one-bit.gschema.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<schemalist>
|
||||||
|
<flags id='flags'>
|
||||||
|
<value nick='none' value='0'/>
|
||||||
|
<value nick='mourning' value='1'/>
|
||||||
|
<value nick='laughing' value='2'/>
|
||||||
|
<value nick='talking' value='4'/>
|
||||||
|
<value nick='walking' value='24'/>
|
||||||
|
</flags>
|
||||||
|
</schemalist>
|
||||||
|
|
14
gio/tests/schema-tests/flags-with-enum-attr.gschema.xml
Normal file
14
gio/tests/schema-tests/flags-with-enum-attr.gschema.xml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<schemalist>
|
||||||
|
<flags id='flags'>
|
||||||
|
<value nick='none' value='0'/>
|
||||||
|
<value nick='mourning' value='1'/>
|
||||||
|
<value nick='laughing' value='2'/>
|
||||||
|
<value nick='talking' value='4'/>
|
||||||
|
<value nick='walking' value='8'/>
|
||||||
|
</flags>
|
||||||
|
|
||||||
|
<schema id='foo'>
|
||||||
|
<key name='xyz' enum='flags'/>
|
||||||
|
</schema>
|
||||||
|
</schemalist>
|
||||||
|
|
14
gio/tests/schema-tests/flags-with-enum-tag.gschema.xml
Normal file
14
gio/tests/schema-tests/flags-with-enum-tag.gschema.xml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<schemalist>
|
||||||
|
<enum id='flags'>
|
||||||
|
<value nick='none' value='0'/>
|
||||||
|
<value nick='mourning' value='1'/>
|
||||||
|
<value nick='laughing' value='2'/>
|
||||||
|
<value nick='talking' value='4'/>
|
||||||
|
<value nick='walking' value='8'/>
|
||||||
|
</enum>
|
||||||
|
|
||||||
|
<schema id='foo'>
|
||||||
|
<key name='xyz' flags='flags'/>
|
||||||
|
</schema>
|
||||||
|
</schemalist>
|
||||||
|
|
@@ -5,3 +5,12 @@ typedef enum
|
|||||||
TEST_ENUM_BAZ,
|
TEST_ENUM_BAZ,
|
||||||
TEST_ENUM_QUUX
|
TEST_ENUM_QUUX
|
||||||
} TestEnum;
|
} TestEnum;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
TEST_FLAGS_NONE = 0,
|
||||||
|
TEST_FLAGS_MOURNING = (1 << 0),
|
||||||
|
TEST_FLAGS_LAUGHING = (1 << 1),
|
||||||
|
TEST_FLAGS_TALKING = (1 << 2),
|
||||||
|
TEST_FLAGS_WALKING = (1 << 3)
|
||||||
|
} TestFlags;
|
||||||
|
Reference in New Issue
Block a user