Merge branch 'wip/muktupavels/per-desktop-overrides' into 'master'

GSettings: per-desktop overrides

Closes #1013

See merge request GNOME/glib!105
This commit is contained in:
Philip Withnall 2018-06-25 10:32:44 +00:00
commit 4993f2b7e5
8 changed files with 259 additions and 25 deletions

View File

@ -179,6 +179,8 @@ typedef struct
GString *unparsed_default_value;
GVariant *default_value;
GVariantDict *desktop_overrides;
GString *strinfo;
gboolean is_enum;
gboolean is_flags;
@ -731,6 +733,11 @@ key_state_serialise (KeyState *state)
g_variant_builder_add (&builder, "(y(**))", 'r',
state->minimum, state->maximum);
/* per-desktop overrides */
if (state->desktop_overrides)
g_variant_builder_add (&builder, "(y@a{sv})", 'd',
g_variant_dict_end (state->desktop_overrides));
state->serialised = g_variant_builder_end (&builder);
}
@ -770,6 +777,9 @@ key_state_free (gpointer data)
if (state->serialised)
g_variant_unref (state->serialised);
if (state->desktop_overrides)
g_variant_dict_unref (state->desktop_overrides);
g_slice_free (KeyState, state);
}
@ -1882,6 +1892,8 @@ set_overrides (GHashTable *schema_table,
gchar **groups;
gint i;
g_debug ("Processing override file '%s'", filename);
key_file = g_key_file_new ();
if (!g_key_file_load_from_file (key_file, filename, 0, &error))
{
@ -1904,18 +1916,31 @@ set_overrides (GHashTable *schema_table,
for (i = 0; groups[i]; i++)
{
const gchar *group = groups[i];
const gchar *schema_name;
const gchar *desktop_id;
SchemaState *schema;
gchar **pieces;
gchar **keys;
gint j;
schema = g_hash_table_lookup (schema_table, group);
pieces = g_strsplit (group, ":", 2);
schema_name = pieces[0];
desktop_id = pieces[1];
g_debug ("Processing group '%s' (schema '%s', %s)",
group, schema_name, desktop_id ? desktop_id : "all desktops");
schema = g_hash_table_lookup (schema_table, schema_name);
if (schema == NULL)
/* Having the schema not be installed is expected to be a
* common case. Don't even emit an error message about
* that.
*/
continue;
{
/* Having the schema not be installed is expected to be a
* common case. Don't even emit an error message about
* that.
*/
g_strfreev (pieces);
continue;
}
keys = g_key_file_get_keys (key_file, group, NULL, NULL);
g_assert (keys != NULL);
@ -1943,6 +1968,32 @@ set_overrides (GHashTable *schema_table,
fprintf (stderr, _(" and --strict was specified; exiting.\n"));
g_key_file_free (key_file);
g_strfreev (pieces);
g_strfreev (groups);
g_strfreev (keys);
return FALSE;
}
if (desktop_id != NULL && state->l10n)
{
/* Let's avoid the n*m case of per-desktop localised
* default values, and just forbid it.
*/
fprintf (stderr,
_("cannot provide per-desktop overrides for localised "
"key '%s' in schema '%s' (override file '%s')"),
key, group, filename);
if (!strict)
{
fprintf (stderr, _("; ignoring override for this key.\n"));
continue;
}
fprintf (stderr, _(" and --strict was specified; exiting.\n"));
g_key_file_free (key_file);
g_strfreev (pieces);
g_strfreev (groups);
g_strfreev (keys);
@ -1973,6 +2024,7 @@ set_overrides (GHashTable *schema_table,
fprintf (stderr, _("--strict was specified; exiting.\n"));
g_key_file_free (key_file);
g_strfreev (pieces);
g_strfreev (groups);
g_strfreev (keys);
@ -2001,6 +2053,7 @@ set_overrides (GHashTable *schema_table,
fprintf (stderr, _(" and --strict was specified; exiting.\n"));
g_key_file_free (key_file);
g_strfreev (pieces);
g_strfreev (groups);
g_strfreev (keys);
@ -2029,6 +2082,7 @@ set_overrides (GHashTable *schema_table,
fprintf (stderr, _(" and --strict was specified; exiting.\n"));
g_key_file_free (key_file);
g_strfreev (pieces);
g_strfreev (groups);
g_strfreev (keys);
@ -2036,11 +2090,24 @@ set_overrides (GHashTable *schema_table,
}
}
g_variant_unref (state->default_value);
state->default_value = value;
if (desktop_id != NULL)
{
if (state->desktop_overrides == NULL)
state->desktop_overrides = g_variant_dict_new (NULL);
g_variant_dict_insert_value (state->desktop_overrides, desktop_id, value);
g_variant_unref (value);
}
else
{
g_variant_unref (state->default_value);
state->default_value = value;
}
g_free (string);
}
g_strfreev (pieces);
g_strfreev (keys);
}
@ -2076,6 +2143,7 @@ main (int argc, char **argv)
/* These options are only for use in the gschema-compile tests */
{ "schema-file", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_FILENAME_ARRAY, &schema_files, NULL, NULL },
{ "override-file", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_FILENAME_ARRAY, &override_files, NULL, NULL },
{ NULL }
};

View File

@ -1204,10 +1204,7 @@ g_settings_get_value (GSettings *settings,
value = g_settings_read_from_backend (settings, &skey, FALSE, FALSE);
if (value == NULL)
value = g_settings_schema_key_get_translated_default (&skey);
if (value == NULL)
value = g_variant_ref (skey.default_value);
value = g_settings_schema_key_get_default_value (&skey);
g_settings_schema_key_clear (&skey);
@ -1304,10 +1301,7 @@ g_settings_get_default_value (GSettings *settings,
value = g_settings_read_from_backend (settings, &skey, FALSE, TRUE);
if (value == NULL)
value = g_settings_schema_key_get_translated_default (&skey);
if (value == NULL)
value = g_variant_ref (skey.default_value);
value = g_settings_schema_key_get_default_value (&skey);
g_settings_schema_key_clear (&skey);
@ -1360,10 +1354,7 @@ g_settings_get_enum (GSettings *settings,
value = g_settings_read_from_backend (settings, &skey, FALSE, FALSE);
if (value == NULL)
value = g_settings_schema_key_get_translated_default (&skey);
if (value == NULL)
value = g_variant_ref (skey.default_value);
value = g_settings_schema_key_get_default_value (&skey);
result = g_settings_schema_key_to_enum (&skey, value);
g_settings_schema_key_clear (&skey);
@ -1473,10 +1464,7 @@ g_settings_get_flags (GSettings *settings,
value = g_settings_read_from_backend (settings, &skey, FALSE, FALSE);
if (value == NULL)
value = g_settings_schema_key_get_translated_default (&skey);
if (value == NULL)
value = g_variant_ref (skey.default_value);
value = g_settings_schema_key_get_default_value (&skey);
result = g_settings_schema_key_to_flags (&skey, value);
g_settings_schema_key_clear (&skey);
@ -1751,6 +1739,13 @@ g_settings_get_mapped (GSettings *settings,
if (okay) goto okay;
}
if ((value = g_settings_schema_key_get_per_desktop_default (&skey)))
{
okay = mapping (value, &result, user_data);
g_variant_unref (value);
if (okay) goto okay;
}
if (mapping (skey.default_value, &result, user_data))
goto okay;
@ -2658,6 +2653,20 @@ g_settings_binding_key_changed (GSettings *settings,
}
}
if (variant == NULL)
{
variant = g_settings_schema_key_get_per_desktop_default (&binding->key);
if (variant &&
!binding->get_mapping (&value, variant, binding->user_data))
{
g_error ("Per-desktop default value for key '%s' in schema '%s' "
"was rejected by the binding mapping function.",
binding->key.name, g_settings_schema_get_id (binding->key.schema));
g_variant_unref (variant);
variant = NULL;
}
}
if (variant == NULL)
{
variant = g_variant_ref (binding->key.default_value);

View File

@ -37,6 +37,7 @@ struct _GSettingsSchemaKey
const GVariantType *type;
GVariant *minimum, *maximum;
GVariant *default_value;
GVariant *desktop_overrides;
gint ref_count;
};
@ -58,6 +59,7 @@ gboolean g_settings_schema_key_type_check (GSettin
GVariant * g_settings_schema_key_range_fixup (GSettingsSchemaKey *key,
GVariant *value);
GVariant * g_settings_schema_key_get_translated_default (GSettingsSchemaKey *key);
GVariant * g_settings_schema_key_get_per_desktop_default (GSettingsSchemaKey *key);
gint g_settings_schema_key_to_enum (GSettingsSchemaKey *key,
GVariant *value);

View File

@ -27,6 +27,7 @@
#include <glibintl.h>
#include <locale.h>
#include <string.h>
#include <stdlib.h>
/**
* SECTION:gsettingsschema
@ -1283,6 +1284,11 @@ g_settings_schema_key_init (GSettingsSchemaKey *key,
endian_fixup (&key->maximum);
break;
case 'd':
g_variant_get (data, "@a{sv}", &key->desktop_overrides);
endian_fixup (&key->desktop_overrides);
break;
default:
g_warning ("unknown schema extension '%c'", code);
break;
@ -1303,6 +1309,9 @@ g_settings_schema_key_clear (GSettingsSchemaKey *key)
if (key->maximum)
g_variant_unref (key->maximum);
if (key->desktop_overrides)
g_variant_unref (key->desktop_overrides);
g_variant_unref (key->default_value);
g_settings_schema_unref (key->schema);
@ -1410,6 +1419,35 @@ g_settings_schema_key_get_translated_default (GSettingsSchemaKey *key)
return value;
}
GVariant *
g_settings_schema_key_get_per_desktop_default (GSettingsSchemaKey *key)
{
static const gchar * const *current_desktops;
GVariant *value = NULL;
gint i;
if (!key->desktop_overrides)
return NULL;
if (g_once_init_enter (&current_desktops))
{
const gchar *xdg_current_desktop = g_getenv ("XDG_CURRENT_DESKTOP");
gchar **tmp;
if (xdg_current_desktop != NULL && xdg_current_desktop[0] != '\0')
tmp = g_strsplit (xdg_current_desktop, G_SEARCHPATH_SEPARATOR_S, -1);
else
tmp = g_new0 (gchar *, 0 + 1);
g_once_init_leave (&current_desktops, (const gchar **) tmp);
}
for (i = 0; value == NULL && current_desktops[i] != NULL; i++)
value = g_variant_lookup_value (key->desktop_overrides, current_desktops[i], NULL);
return value;
}
gint
g_settings_schema_key_to_enum (GSettingsSchemaKey *key,
GVariant *value)
@ -1698,6 +1736,9 @@ g_settings_schema_key_get_default_value (GSettingsSchemaKey *key)
value = g_settings_schema_key_get_translated_default (key);
if (!value)
value = g_settings_schema_key_get_per_desktop_default (key);
if (!value)
value = g_variant_ref (key->default_value);

View File

@ -372,12 +372,14 @@ test.mo: de.po
EXTRA_DIST += de.po
dist_uninstalled_test_data += \
org.gtk.test.gschema.xml.orig \
org.gtk.test.gschema.override.orig \
org.gtk.schemasourcecheck.gschema.xml \
testenum.h \
enums.xml.template
# Generated while running the testcase itself...
CLEANFILES += \
org.gtk.test.gschema.xml \
org.gtk.test.gschema.override \
org.gtk.test.enums.xml \
gsettings.store \
gschemas.compiled \

View File

@ -2246,6 +2246,7 @@ G_GNUC_END_IGNORE_DEPRECATIONS
"org.gtk.test.range.direct",
"org.gtk.test.mapped",
"org.gtk.test.descriptions",
"org.gtk.test.per-desktop",
NULL));
}
@ -2637,6 +2638,100 @@ test_default_value (void)
g_object_unref (settings);
}
static gboolean
string_map_func (GVariant *value,
gpointer *result,
gpointer user_data)
{
const gchar *str;
str = g_variant_get_string (value, NULL);
*result = g_variant_new_string (str);
return TRUE;
}
/* Test that per-desktop values from org.gtk.test.gschema.override
* does not change default value if current desktop is not listed in
* $XDG_CURRENT_DESKTOP.
*/
static void
test_per_desktop (void)
{
GSettings *settings;
TestObject *obj;
gpointer p;
gchar *str;
settings = g_settings_new ("org.gtk.test.per-desktop");
obj = test_object_new ();
if (!g_test_subprocess ())
{
g_test_trap_subprocess ("/gsettings/per-desktop/subprocess", 0, 0);
g_test_trap_assert_passed ();
}
str = g_settings_get_string (settings, "desktop");
g_assert_cmpstr (str, ==, "GNOME");
g_free (str);
p = g_settings_get_mapped (settings, "desktop", string_map_func, NULL);
str = g_variant_dup_string (p, NULL);
g_assert_cmpstr (str, ==, "GNOME");
g_free (str);
g_variant_unref (p);
g_settings_bind (settings, "desktop", obj, "string", G_SETTINGS_BIND_DEFAULT);
g_object_get (obj, "string", &str, NULL);
g_assert_cmpstr (str, ==, "GNOME");
g_free (str);
g_object_unref (settings);
g_object_unref (obj);
}
/* Test that per-desktop values from org.gtk.test.gschema.override
* are successfully loaded based on the value of $XDG_CURRENT_DESKTOP.
*/
static void
test_per_desktop_subprocess (void)
{
GSettings *settings;
TestObject *obj;
gpointer p;
gchar *str;
g_setenv ("XDG_CURRENT_DESKTOP", "GNOME-Classic:GNOME", TRUE);
settings = g_settings_new ("org.gtk.test.per-desktop");
obj = test_object_new ();
str = g_settings_get_string (settings, "desktop");
g_assert_cmpstr (str, ==, "GNOME Classic");
g_free (str);
p = g_settings_get_mapped (settings, "desktop", string_map_func, NULL);
str = g_variant_dup_string (p, NULL);
g_assert_cmpstr (str, ==, "GNOME Classic");
g_free (str);
g_variant_unref (p);
g_settings_bind (settings, "desktop", obj, "string", G_SETTINGS_BIND_DEFAULT);
g_object_get (obj, "string", &str, NULL);
g_assert_cmpstr (str, ==, "GNOME Classic");
g_free (str);
g_object_unref (settings);
g_object_unref (obj);
}
static void
test_extended_schema (void)
{
@ -2657,6 +2752,7 @@ int
main (int argc, char *argv[])
{
gchar *schema_text;
gchar *override_text;
gchar *enums;
gint result;
@ -2679,6 +2775,7 @@ main (int argc, char *argv[])
g_setenv ("XDG_DATA_DIRS", ".", TRUE);
g_setenv ("XDG_DATA_HOME", ".", TRUE);
g_setenv ("GSETTINGS_SCHEMA_DIR", ".", TRUE);
g_setenv ("XDG_CURRENT_DESKTOP", "", TRUE);
if (!backend_set)
g_setenv ("GSETTINGS_BACKEND", "memory", TRUE);
@ -2701,6 +2798,10 @@ main (int argc, char *argv[])
g_assert (g_file_set_contents ("org.gtk.test.gschema.xml", schema_text, -1, NULL));
g_free (schema_text);
g_assert (g_file_get_contents (SRCDIR "/org.gtk.test.gschema.override.orig", &override_text, NULL, NULL));
g_assert (g_file_set_contents ("org.gtk.test.gschema.override", override_text, -1, NULL));
g_free (override_text);
/* Meson build defines this, autotools build does not */
#ifndef GLIB_COMPILE_SCHEMAS
#define GLIB_COMPILE_SCHEMAS "../glib-compile-schemas"
@ -2709,7 +2810,8 @@ main (int argc, char *argv[])
g_remove ("gschemas.compiled");
g_assert (g_spawn_command_line_sync (GLIB_COMPILE_SCHEMAS " --targetdir=. "
"--schema-file=org.gtk.test.enums.xml "
"--schema-file=org.gtk.test.gschema.xml",
"--schema-file=org.gtk.test.gschema.xml "
"--override-file=org.gtk.test.gschema.override",
NULL, NULL, &result, NULL));
g_assert (result == 0);
@ -2790,6 +2892,8 @@ main (int argc, char *argv[])
g_test_add_func ("/gsettings/read-descriptions", test_read_descriptions);
g_test_add_func ("/gsettings/test-extended-schema", test_extended_schema);
g_test_add_func ("/gsettings/default-value", test_default_value);
g_test_add_func ("/gsettings/per-desktop", test_per_desktop);
g_test_add_func ("/gsettings/per-desktop/subprocess", test_per_desktop_subprocess);
result = g_test_run ();

View File

@ -0,0 +1,2 @@
[org.gtk.test.per-desktop:GNOME-Classic]
desktop = "GNOME Classic"

View File

@ -213,4 +213,10 @@
</key>
</schema>
<schema id="org.gtk.test.per-desktop" path="/tests/per-desktop/">
<key name="desktop" type="s">
<default>"GNOME"</default>
</key>
</schema>
</schemalist>