diff --git a/gio/gdelayedsettingsbackend.c b/gio/gdelayedsettingsbackend.c index 93ced25db..6fff6f71c 100644 --- a/gio/gdelayedsettingsbackend.c +++ b/gio/gdelayedsettingsbackend.c @@ -156,7 +156,8 @@ add_to_tree (gpointer key, gpointer value, gpointer user_data) { - g_tree_insert (user_data, g_strdup (key), g_variant_ref (value)); + /* A value may be %NULL if its key has been reset */ + g_tree_insert (user_data, g_strdup (key), (value != NULL) ? g_variant_ref (value) : NULL); return FALSE; } diff --git a/gio/gsettings.c b/gio/gsettings.c index c189a2e62..e96c94e11 100644 --- a/gio/gsettings.c +++ b/gio/gsettings.c @@ -343,8 +343,6 @@ struct _GSettingsPrivate GSettingsBackend *backend; GSettingsSchema *schema; gchar *path; - - GDelayedSettingsBackend *delayed; }; enum @@ -642,7 +640,7 @@ g_settings_get_property (GObject *object, break; case PROP_DELAY_APPLY: - g_value_set_boolean (value, settings->priv->delayed != NULL); + g_value_set_boolean (value, G_IS_DELAYED_SETTINGS_BACKEND (settings->priv->backend)); break; default: @@ -2256,19 +2254,20 @@ g_settings_set_strv (GSettings *settings, void g_settings_delay (GSettings *settings) { + GDelayedSettingsBackend *delayed = NULL; + g_return_if_fail (G_IS_SETTINGS (settings)); - if (settings->priv->delayed) + if (G_IS_DELAYED_SETTINGS_BACKEND (settings->priv->backend)) return; - settings->priv->delayed = - g_delayed_settings_backend_new (settings->priv->backend, - settings, - settings->priv->main_context); + delayed = g_delayed_settings_backend_new (settings->priv->backend, + settings, + settings->priv->main_context); g_settings_backend_unwatch (settings->priv->backend, G_OBJECT (settings)); g_object_unref (settings->priv->backend); - settings->priv->backend = G_SETTINGS_BACKEND (settings->priv->delayed); + settings->priv->backend = G_SETTINGS_BACKEND (delayed); g_settings_backend_watch (settings->priv->backend, &listener_vtable, G_OBJECT (settings), settings->priv->main_context); @@ -2288,7 +2287,7 @@ g_settings_delay (GSettings *settings) void g_settings_apply (GSettings *settings) { - if (settings->priv->delayed) + if (G_IS_DELAYED_SETTINGS_BACKEND (settings->priv->backend)) { GDelayedSettingsBackend *delayed; @@ -2311,7 +2310,7 @@ g_settings_apply (GSettings *settings) void g_settings_revert (GSettings *settings) { - if (settings->priv->delayed) + if (G_IS_DELAYED_SETTINGS_BACKEND (settings->priv->backend)) { GDelayedSettingsBackend *delayed; @@ -2336,7 +2335,7 @@ g_settings_get_has_unapplied (GSettings *settings) { g_return_val_if_fail (G_IS_SETTINGS (settings), FALSE); - return settings->priv->delayed && + return G_IS_DELAYED_SETTINGS_BACKEND (settings->priv->backend) && g_delayed_settings_backend_get_has_unapplied ( G_DELAYED_SETTINGS_BACKEND (settings->priv->backend)); } @@ -2424,7 +2423,10 @@ g_settings_is_writable (GSettings *settings, * @settings. * * The schema for the child settings object must have been declared - * in the schema of @settings using a element. + * in the schema of @settings using a `` element. + * + * The created child settings object will inherit the #GSettings:delay-apply + * mode from @settings. * * Returns: (not nullable) (transfer full): a 'child' settings object * diff --git a/gio/tests/gsettings.c b/gio/tests/gsettings.c index 42eeccd7a..dad1623b7 100644 --- a/gio/tests/gsettings.c +++ b/gio/tests/gsettings.c @@ -56,6 +56,15 @@ check_and_free (GVariant *value, g_variant_unref (value); } +/* Wrapper around g_assert_cmpstr() which gets a setting from a #GSettings + * using g_settings_get(). */ +#define settings_assert_cmpstr(settings, key, op, expected_value) G_STMT_START { \ + gchar *__str; \ + g_settings_get ((settings), (key), "s", &__str); \ + g_assert_cmpstr (__str, op, (expected_value)); \ + g_free (__str); \ +} G_STMT_END + /* Just to get warmed up: Read and set a string, and * verify that can read the changed string back @@ -88,15 +97,10 @@ test_basic (void) g_object_unref (b); g_free (path); - g_settings_get (settings, "greeting", "s", &str); - g_assert_cmpstr (str, ==, "Hello, earthlings"); - g_free (str); + settings_assert_cmpstr (settings, "greeting", ==, "Hello, earthlings"); g_settings_set (settings, "greeting", "s", "goodbye world"); - g_settings_get (settings, "greeting", "s", &str); - g_assert_cmpstr (str, ==, "goodbye world"); - g_free (str); - str = NULL; + settings_assert_cmpstr (settings, "greeting", ==, "goodbye world"); if (!backend_set && g_test_undefined ()) { @@ -110,10 +114,7 @@ test_basic (void) g_object_unref (tmp_settings); } - g_settings_get (settings, "greeting", "s", &str); - g_assert_cmpstr (str, ==, "goodbye world"); - g_free (str); - str = NULL; + settings_assert_cmpstr (settings, "greeting", ==, "goodbye world"); g_settings_reset (settings, "greeting"); str = g_settings_get_string (settings, "greeting"); @@ -342,10 +343,7 @@ test_basic_types (void) g_settings_get (settings, "test-double", "d", &d); g_assert_cmpfloat (d, ==, G_MAXDOUBLE); - g_settings_get (settings, "test-string", "s", &str); - g_assert_cmpstr (str, ==, "a string, it seems"); - g_free (str); - str = NULL; + settings_assert_cmpstr (settings, "test-string", ==, "a string, it seems"); g_settings_get (settings, "test-objectpath", "o", &str); g_assert_cmpstr (str, ==, "/a/object/path"); @@ -484,7 +482,6 @@ test_delay_apply (void) { GSettings *settings; GSettings *settings2; - gchar *str; gboolean writable; GVariant *v; const gchar *s; @@ -530,20 +527,14 @@ test_delay_apply (void) writable = g_settings_is_writable (settings, "greeting"); g_assert_true (writable); - g_settings_get (settings, "greeting", "s", &str); - g_assert_cmpstr (str, ==, "greetings from test_delay_apply"); - g_free (str); - str = NULL; + settings_assert_cmpstr (settings, "greeting", ==, "greetings from test_delay_apply"); v = g_settings_get_user_value (settings, "greeting"); s = g_variant_get_string (v, NULL); g_assert_cmpstr (s, ==, "greetings from test_delay_apply"); g_variant_unref (v); - g_settings_get (settings2, "greeting", "s", &str); - g_assert_cmpstr (str, ==, "top o' the morning"); - g_free (str); - str = NULL; + settings_assert_cmpstr (settings2, "greeting", ==, "top o' the morning"); g_assert_true (g_settings_get_has_unapplied (settings)); g_assert_false (g_settings_get_has_unapplied (settings2)); @@ -556,15 +547,8 @@ test_delay_apply (void) g_assert_false (changed_cb_called); g_assert_true (changed_cb_called2); - g_settings_get (settings, "greeting", "s", &str); - g_assert_cmpstr (str, ==, "greetings from test_delay_apply"); - g_free (str); - str = NULL; - - g_settings_get (settings2, "greeting", "s", &str); - g_assert_cmpstr (str, ==, "greetings from test_delay_apply"); - g_free (str); - str = NULL; + settings_assert_cmpstr (settings, "greeting", ==, "greetings from test_delay_apply"); + settings_assert_cmpstr (settings2, "greeting", ==, "greetings from test_delay_apply"); g_assert_false (g_settings_get_has_unapplied (settings)); g_assert_false (g_settings_get_has_unapplied (settings2)); @@ -572,9 +556,7 @@ test_delay_apply (void) g_settings_reset (settings, "greeting"); g_settings_apply (settings); - g_settings_get (settings, "greeting", "s", &str); - g_assert_cmpstr (str, ==, "Hello, earthlings"); - g_free (str); + settings_assert_cmpstr (settings, "greeting", ==, "Hello, earthlings"); g_object_unref (settings2); g_object_unref (settings); @@ -588,30 +570,20 @@ test_delay_revert (void) { GSettings *settings; GSettings *settings2; - gchar *str; settings = g_settings_new ("org.gtk.test"); settings2 = g_settings_new ("org.gtk.test"); g_settings_set (settings2, "greeting", "s", "top o' the morning"); - g_settings_get (settings, "greeting", "s", &str); - g_assert_cmpstr (str, ==, "top o' the morning"); - g_free (str); + settings_assert_cmpstr (settings, "greeting", ==, "top o' the morning"); g_settings_delay (settings); g_settings_set (settings, "greeting", "s", "greetings from test_delay_revert"); - g_settings_get (settings, "greeting", "s", &str); - g_assert_cmpstr (str, ==, "greetings from test_delay_revert"); - g_free (str); - str = NULL; - - g_settings_get (settings2, "greeting", "s", &str); - g_assert_cmpstr (str, ==, "top o' the morning"); - g_free (str); - str = NULL; + settings_assert_cmpstr (settings, "greeting", ==, "greetings from test_delay_revert"); + settings_assert_cmpstr (settings2, "greeting", ==, "top o' the morning"); g_assert_true (g_settings_get_has_unapplied (settings)); @@ -619,15 +591,8 @@ test_delay_revert (void) g_assert_false (g_settings_get_has_unapplied (settings)); - g_settings_get (settings, "greeting", "s", &str); - g_assert_cmpstr (str, ==, "top o' the morning"); - g_free (str); - str = NULL; - - g_settings_get (settings2, "greeting", "s", &str); - g_assert_cmpstr (str, ==, "top o' the morning"); - g_free (str); - str = NULL; + settings_assert_cmpstr (settings, "greeting", ==, "top o' the morning"); + settings_assert_cmpstr (settings2, "greeting", ==, "top o' the morning"); g_object_unref (settings2); g_object_unref (settings); @@ -654,7 +619,7 @@ test_delay_child (void) g_assert_nonnull (child); g_object_get (child, "delay-apply", &delay, NULL); - g_assert_false (delay); + g_assert_true (delay); g_settings_get (child, "test-byte", "y", &byte); g_assert_cmpuint (byte, ==, 36); @@ -665,18 +630,66 @@ test_delay_child (void) g_settings_get (base, "test-byte", "y", &byte); g_assert_cmpuint (byte, ==, 36); + /* apply the child and the changes should be saved */ + g_settings_apply (child); + g_settings_get (base, "test-byte", "y", &byte); + g_assert_cmpuint (byte, ==, 42); + g_object_unref (child); g_object_unref (settings); g_object_unref (base); } +static void +test_delay_reset_key (void) +{ + GSettings *direct_settings = NULL, *delayed_settings = NULL; + + g_test_summary ("Test that resetting a key on a delayed settings instance works"); + + delayed_settings = g_settings_new ("org.gtk.test"); + direct_settings = g_settings_new ("org.gtk.test"); + + g_settings_set (direct_settings, "greeting", "s", "ey up"); + + settings_assert_cmpstr (delayed_settings, "greeting", ==, "ey up"); + + /* Set up a delayed settings backend. */ + g_settings_delay (delayed_settings); + + g_settings_set (delayed_settings, "greeting", "s", "how do"); + + settings_assert_cmpstr (delayed_settings, "greeting", ==, "how do"); + settings_assert_cmpstr (direct_settings, "greeting", ==, "ey up"); + + g_assert_true (g_settings_get_has_unapplied (delayed_settings)); + + g_settings_reset (delayed_settings, "greeting"); + + /* There are still unapplied settings, because the reset is resetting to the + * value from the schema, not the value from @direct_settings. */ + g_assert_true (g_settings_get_has_unapplied (delayed_settings)); + + settings_assert_cmpstr (delayed_settings, "greeting", ==, "Hello, earthlings"); + settings_assert_cmpstr (direct_settings, "greeting", ==, "ey up"); + + /* Apply the settings changes (i.e. the reset). */ + g_settings_apply (delayed_settings); + + g_assert_false (g_settings_get_has_unapplied (delayed_settings)); + + settings_assert_cmpstr (delayed_settings, "greeting", ==, "Hello, earthlings"); + settings_assert_cmpstr (direct_settings, "greeting", ==, "Hello, earthlings"); + + g_object_unref (direct_settings); + g_object_unref (delayed_settings); +} + static void keys_changed_cb (GSettings *settings, const GQuark *keys, gint n_keys) { - gchar *str; - g_assert_cmpint (n_keys, ==, 2); g_assert_true ((keys[0] == g_quark_from_static_string ("greeting") && @@ -684,15 +697,8 @@ keys_changed_cb (GSettings *settings, (keys[1] == g_quark_from_static_string ("greeting") && keys[0] == g_quark_from_static_string ("farewell"))); - g_settings_get (settings, "greeting", "s", &str); - g_assert_cmpstr (str, ==, "greetings from test_atomic"); - g_free (str); - str = NULL; - - g_settings_get (settings, "farewell", "s", &str); - g_assert_cmpstr (str, ==, "atomic bye-bye"); - g_free (str); - str = NULL; + settings_assert_cmpstr (settings, "greeting", ==, "greetings from test_atomic"); + settings_assert_cmpstr (settings, "farewell", ==, "atomic bye-bye"); } /* Check that delay-applied changes appear atomically. @@ -704,7 +710,6 @@ test_atomic (void) { GSettings *settings; GSettings *settings2; - gchar *str; settings = g_settings_new ("org.gtk.test"); settings2 = g_settings_new ("org.gtk.test"); @@ -724,25 +729,10 @@ test_atomic (void) g_settings_apply (settings); - g_settings_get (settings, "greeting", "s", &str); - g_assert_cmpstr (str, ==, "greetings from test_atomic"); - g_free (str); - str = NULL; - - g_settings_get (settings, "farewell", "s", &str); - g_assert_cmpstr (str, ==, "atomic bye-bye"); - g_free (str); - str = NULL; - - g_settings_get (settings2, "greeting", "s", &str); - g_assert_cmpstr (str, ==, "greetings from test_atomic"); - g_free (str); - str = NULL; - - g_settings_get (settings2, "farewell", "s", &str); - g_assert_cmpstr (str, ==, "atomic bye-bye"); - g_free (str); - str = NULL; + settings_assert_cmpstr (settings, "greeting", ==, "greetings from test_atomic"); + settings_assert_cmpstr (settings, "farewell", ==, "atomic bye-bye"); + settings_assert_cmpstr (settings2, "greeting", ==, "greetings from test_atomic"); + settings_assert_cmpstr (settings2, "farewell", ==, "atomic bye-bye"); g_object_unref (settings2); g_object_unref (settings); @@ -851,13 +841,7 @@ test_l10n_context (void) setlocale (LC_MESSAGES, "de_DE.UTF-8"); /* Only do the test if translation is actually working... */ if (g_str_equal (dgettext ("test", "\"Unnamed\""), "\"Unbenannt\"")) - { - g_settings_get (settings, "backspace", "s", &str); - - g_assert_cmpstr (str, ==, "Löschen"); - g_free (str); - str = NULL; - } + settings_assert_cmpstr (settings, "backspace", ==, "Löschen"); else g_printerr ("warning: translation is not working... skipping test. "); @@ -2767,14 +2751,10 @@ test_null_backend (void) g_assert_cmpstr (str, ==, "org.gtk.test"); g_free (str); - g_settings_get (settings, "greeting", "s", &str); - g_assert_cmpstr (str, ==, "Hello, earthlings"); - g_free (str); + settings_assert_cmpstr (settings, "greeting", ==, "Hello, earthlings"); g_settings_set (settings, "greeting", "s", "goodbye world"); - g_settings_get (settings, "greeting", "s", &str); - g_assert_cmpstr (str, ==, "Hello, earthlings"); - g_free (str); + settings_assert_cmpstr (settings, "greeting", ==, "Hello, earthlings"); writable = g_settings_is_writable (settings, "greeting"); g_assert_false (writable); @@ -2784,9 +2764,7 @@ test_null_backend (void) g_settings_delay (settings); g_settings_set (settings, "greeting", "s", "goodbye world"); g_settings_apply (settings); - g_settings_get (settings, "greeting", "s", &str); - g_assert_cmpstr (str, ==, "Hello, earthlings"); - g_free (str); + settings_assert_cmpstr (settings, "greeting", ==, "Hello, earthlings"); g_object_unref (settings); g_object_unref (backend); @@ -3114,6 +3092,7 @@ main (int argc, char *argv[]) g_test_add_func ("/gsettings/delay-apply", test_delay_apply); g_test_add_func ("/gsettings/delay-revert", test_delay_revert); g_test_add_func ("/gsettings/delay-child", test_delay_child); + g_test_add_func ("/gsettings/delay-reset-key", test_delay_reset_key); g_test_add_func ("/gsettings/atomic", test_atomic); g_test_add_func ("/gsettings/simple-binding", test_simple_binding);