X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgsettings.c;h=fdc3c9d10cf20465ca2d13cf7c578e8ce78e2e29;hb=ffe286e647ce9ba9bb8e1631ba3cf0194038f438;hp=0e6517e711b62ee793ab8919b194474e847a7b6a;hpb=148f731748a586ecc2d6e15afcc760a46e929a84;p=platform%2Fupstream%2Fglib.git diff --git a/gio/gsettings.c b/gio/gsettings.c index 0e6517e..fdc3c9d 100644 --- a/gio/gsettings.c +++ b/gio/gsettings.c @@ -12,9 +12,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library; if not, see . * * Author: Ryan Lortie */ @@ -24,7 +22,6 @@ #include #include -#include #include "gsettings.h" @@ -32,12 +29,14 @@ #include "gsettingsbackendinternal.h" #include "gsettings-mapping.h" #include "gsettingsschema-internal.h" +#include "gaction.h" #include "strinfo.c" /** * SECTION:gsettings * @short_description: High-level API for application settings + * @include: gio/gio.h * * The #GSettings class provides a convenient API for storing and retrieving * application settings. @@ -69,6 +68,14 @@ * useful e.g. when the schema describes an 'account', and you want to be * able to store a arbitrary number of accounts. * + * Paths must start with and end with a forward slash character ('/') + * and must not contain two sequential slash characters. Paths should + * be chosen based on a domain name associated with the program or + * library to which the settings belong. Examples of paths are + * "/org/gtk/settings/file-chooser/" and "/ca/desrt/dconf-editor/". + * Paths should not start with "/apps/", "/desktop/" or "/system/" as + * they often did in GConf. + * * Unlike other configuration systems (like GConf), GSettings does not * restrict keys to basic types like strings and numbers. GSettings stores * values as #GVariant, and allows any #GVariantType for keys. Key names @@ -79,42 +86,41 @@ * Similar to GConf, the default values in GSettings schemas can be * localized, but the localized values are stored in gettext catalogs * and looked up with the domain that is specified in the - * gettext-domain attribute of the - * schemalist or schema - * elements and the category that is specified in the l10n attribute of the - * key element. + * gettext-domain attribute of the or + * elements and the category that is specified in the l10n attribute of + * the element. * * GSettings uses schemas in a compact binary form that is created - * by the glib-compile-schemas - * utility. The input is a schema description in an XML format that can be - * described by the following DTD: - * |[FIXME: MISSING XINCLUDE CONTENT]| - * - * glib-compile-schemas expects schema files to have the extension .gschema.xml - * - * At runtime, schemas are identified by their id (as specified - * in the id attribute of the - * schema element). The - * convention for schema ids is to use a dotted name, similar in - * style to a D-Bus bus name, e.g. "org.gnome.SessionManager". In particular, - * if the settings are for a specific service that owns a D-Bus bus name, - * the D-Bus bus name and schema id should match. For schemas which deal - * with settings not associated with one named application, the id should - * not use StudlyCaps, e.g. "org.gnome.font-rendering". - * - * In addition to #GVariant types, keys can have types that have enumerated - * types. These can be described by a choice, - * enum or flags element, see - * . The underlying type of - * such a key is string, but you can use g_settings_get_enum(), - * g_settings_set_enum(), g_settings_get_flags(), g_settings_set_flags() - * access the numeric values corresponding to the string value of enum - * and flags keys. - * - * Default values - * element). The convention for schema + * ids is to use a dotted name, similar in style to a D-Bus bus name, + * e.g. "org.gnome.SessionManager". In particular, if the settings are + * for a specific service that owns a D-Bus bus name, the D-Bus bus name + * and schema id should match. For schemas which deal with settings not + * associated with one named application, the id should not use + * StudlyCaps, e.g. "org.gnome.font-rendering". + * + * In addition to #GVariant types, keys can have types that have + * enumerated types. These can be described by a , + * or element, as seen in the + * [example][schema-enumerated]. The underlying type of such a key + * is string, but you can use g_settings_get_enum(), g_settings_set_enum(), + * g_settings_get_flags(), g_settings_set_flags() access the numeric values + * corresponding to the string value of enum and flags keys. + * + * An example for default value: + * |[ * - * + * * * * "Hello, earthlings" @@ -130,10 +136,10 @@ * * * - * ]]> + * ]| * - * Ranges, choices and enumerated types - * * * @@ -176,52 +182,43 @@ * * * - * ]]> - * - * - * Vendor overrides - * - * Default values are defined in the schemas that get installed by - * an application. Sometimes, it is necessary for a vendor or distributor - * to adjust these defaults. Since patching the XML source for the schema - * is inconvenient and error-prone, - * glib-compile-schemas reads - * so-called 'vendor override' files. These are keyfiles in the same - * directory as the XML schema sources which can override default values. - * The schema id serves as the group name in the key file, and the values - * are expected in serialized GVariant form, as in the following example: - * + * ]| + * + * ## Vendor overrides + * + * Default values are defined in the schemas that get installed by + * an application. Sometimes, it is necessary for a vendor or distributor + * to adjust these defaults. Since patching the XML source for the schema + * is inconvenient and error-prone, + * [glib-compile-schemas][glib-compile-schemas] reads so-called vendor + * override' files. These are keyfiles in the same directory as the XML + * schema sources which can override default values. The schema id serves + * as the group name in the key file, and the values are expected in + * serialized GVariant form, as in the following example: + * |[ * [org.gtk.Example] * key1='string' * key2=1.5 - * - * - * - * glib-compile-schemas expects schema files to have the extension - * .gschema.override - * - * - * - * - * Binding - * - * A very convenient feature of GSettings lets you bind #GObject properties - * directly to settings, using g_settings_bind(). Once a GObject property - * has been bound to a setting, changes on either side are automatically - * propagated to the other side. GSettings handles details like - * mapping between GObject and GVariant types, and preventing infinite - * cycles. - * - * - * This makes it very easy to hook up a preferences dialog to the - * underlying settings. To make this even more convenient, GSettings - * looks for a boolean property with the name "sensitivity" and - * automatically binds it to the writability of the bound setting. - * If this 'magic' gets in the way, it can be suppressed with the - * #G_SETTINGS_BIND_NO_SENSITIVITY flag. - * - * - **/ + * ]| + * + * glib-compile-schemas expects schema files to have the extension + * `.gschema.override`. + * + * ## Binding + * + * A very convenient feature of GSettings lets you bind #GObject properties + * directly to settings, using g_settings_bind(). Once a GObject property + * has been bound to a setting, changes on either side are automatically + * propagated to the other side. GSettings handles details like mapping + * between GObject and GVariant types, and preventing infinite cycles. + * + * This makes it very easy to hook up a preferences dialog to the + * underlying settings. To make this even more convenient, GSettings + * looks for a boolean property with the name "sensitivity" and + * automatically binds it to the writability of the bound setting. + * If this 'magic' gets in the way, it can be suppressed with the + * #G_SETTINGS_BIND_NO_SENSITIVITY flag. + */ struct _GSettingsPrivate { @@ -257,7 +254,7 @@ enum static guint g_settings_signals[N_SIGNALS]; -G_DEFINE_TYPE (GSettings, g_settings, G_TYPE_OBJECT) +G_DEFINE_TYPE_WITH_PRIVATE (GSettings, g_settings, G_TYPE_OBJECT) /* Signals {{{1 */ static gboolean @@ -271,8 +268,14 @@ g_settings_real_change_event (GSettings *settings, keys = g_settings_schema_list (settings->priv->schema, &n_keys); for (i = 0; i < n_keys; i++) - g_signal_emit (settings, g_settings_signals[SIGNAL_CHANGED], - keys[i], g_quark_to_string (keys[i])); + { + const gchar *key = g_quark_to_string (keys[i]); + + if (g_str_has_suffix (key, "/")) + continue; + + g_signal_emit (settings, g_settings_signals[SIGNAL_CHANGED], keys[i], key); + } return FALSE; } @@ -289,8 +292,14 @@ g_settings_real_writable_change_event (GSettings *settings, keys = g_settings_schema_list (settings->priv->schema, &n_keys); for (i = 0; i < n_keys; i++) - g_signal_emit (settings, g_settings_signals[SIGNAL_WRITABLE_CHANGED], - keys[i], g_quark_to_string (keys[i])); + { + const gchar *key = g_quark_to_string (keys[i]); + + if (g_str_has_suffix (key, "/")) + continue; + + g_signal_emit (settings, g_settings_signals[SIGNAL_WRITABLE_CHANGED], keys[i], key); + } return FALSE; } @@ -348,8 +357,8 @@ static void settings_backend_keys_changed (GObject *target, GSettingsBackend *backend, const gchar *path, - const gchar * const *items, - gpointer origin_tag) + gpointer origin_tag, + const gchar * const *items) { GSettings *settings = G_SETTINGS (target); gboolean ignore_this; @@ -583,10 +592,7 @@ g_settings_finalize (GObject *object) static void g_settings_init (GSettings *settings) { - settings->priv = G_TYPE_INSTANCE_GET_PRIVATE (settings, - G_TYPE_SETTINGS, - GSettingsPrivate); - + settings->priv = g_settings_get_instance_private (settings); settings->priv->main_context = g_main_context_ref_thread_default (); } @@ -603,8 +609,6 @@ g_settings_class_init (GSettingsClass *class) object_class->constructed = g_settings_constructed; object_class->finalize = g_settings_finalize; - g_type_class_add_private (object_class, sizeof (GSettingsPrivate)); - /** * GSettings::changed: * @settings: the object on which the signal was emitted @@ -629,10 +633,8 @@ g_settings_class_init (GSettingsClass *class) * GSettings::change-event: * @settings: the object on which the signal was emitted * @keys: (array length=n_keys) (element-type GQuark) (allow-none): - * an array of #GQuarks for the changed keys, or %NULL + * an array of #GQuarks for the changed keys, or %NULL * @n_keys: the length of the @keys array, or 0 - * @returns: %TRUE to stop other handlers from being invoked for the - * event. FALSE to propagate the event further. * * The "change-event" signal is emitted once per change event that * affects this settings object. You should connect to this signal @@ -649,6 +651,9 @@ g_settings_class_init (GSettingsClass *class) * The default handler for this signal invokes the "changed" signal * for each affected key. If any other connected handler returns * %TRUE then this default functionality will be suppressed. + * + * Returns: %TRUE to stop other handlers from being invoked for the + * event. FALSE to propagate the event further. */ g_settings_signals[SIGNAL_CHANGE_EVENT] = g_signal_new ("change-event", G_TYPE_SETTINGS, @@ -682,8 +687,6 @@ g_settings_class_init (GSettingsClass *class) * GSettings::writable-change-event: * @settings: the object on which the signal was emitted * @key: the quark of the key, or 0 - * @returns: %TRUE to stop other handlers from being invoked for the - * event. FALSE to propagate the event further. * * The "writable-change-event" signal is emitted once per writability * change event that affects this settings object. You should connect @@ -703,6 +706,9 @@ g_settings_class_init (GSettingsClass *class) * example, a new mandatory setting is introduced). If any other * connected handler returns %TRUE then this default functionality * will be suppressed. + * + * Returns: %TRUE to stop other handlers from being invoked for the + * event. FALSE to propagate the event further. */ g_settings_signals[SIGNAL_WRITABLE_CHANGE_EVENT] = g_signal_new ("writable-change-event", G_TYPE_SETTINGS, @@ -826,7 +832,6 @@ g_settings_class_init (GSettingsClass *class) /** * g_settings_new: * @schema_id: the id of the schema - * @returns: a new #GSettings object * * Creates a new #GSettings object with the schema specified by * @schema_id. @@ -836,6 +841,8 @@ g_settings_class_init (GSettingsClass *class) * call to g_settings_new(). The new #GSettings will hold a reference * on the context. See g_main_context_push_thread_default(). * + * Returns: a new #GSettings object + * * Since: 2.26 */ GSettings * @@ -848,11 +855,25 @@ g_settings_new (const gchar *schema_id) NULL); } +static gboolean +path_is_valid (const gchar *path) +{ + if (!path) + return FALSE; + + if (path[0] != '/') + return FALSE; + + if (!g_str_has_suffix (path, "/")) + return FALSE; + + return strstr (path, "//") == NULL; +} + /** * g_settings_new_with_path: * @schema_id: the id of the schema * @path: the path to use - * @returns: a new #GSettings object * * Creates a new #GSettings object with the relocatable schema specified * by @schema_id and a given path. @@ -864,6 +885,12 @@ g_settings_new (const gchar *schema_id) * It is a programmer error to call this function for a schema that * has an explicitly specified path. * + * It is a programmer error if @path is not a valid path. A valid path + * begins and ends with '/' and does not contain two consecutive '/' + * characters. + * + * Returns: a new #GSettings object + * * Since: 2.26 */ GSettings * @@ -871,7 +898,7 @@ g_settings_new_with_path (const gchar *schema_id, const gchar *path) { g_return_val_if_fail (schema_id != NULL, NULL); - g_return_val_if_fail (path != NULL, NULL); + g_return_val_if_fail (path_is_valid (path), NULL); return g_object_new (G_TYPE_SETTINGS, "schema-id", schema_id, @@ -883,7 +910,6 @@ g_settings_new_with_path (const gchar *schema_id, * g_settings_new_with_backend: * @schema_id: the id of the schema * @backend: the #GSettingsBackend to use - * @returns: a new #GSettings object * * Creates a new #GSettings object with the schema specified by * @schema_id and a given #GSettingsBackend. @@ -894,6 +920,8 @@ g_settings_new_with_path (const gchar *schema_id, * the system to get a settings object that modifies the system default * settings instead of the settings for this user. * + * Returns: a new #GSettings object + * * Since: 2.26 */ GSettings * @@ -914,7 +942,6 @@ g_settings_new_with_backend (const gchar *schema_id, * @schema_id: the id of the schema * @backend: the #GSettingsBackend to use * @path: the path to use - * @returns: a new #GSettings object * * Creates a new #GSettings object with the schema specified by * @schema_id and a given #GSettingsBackend and path. @@ -922,6 +949,8 @@ g_settings_new_with_backend (const gchar *schema_id, * This is a mix of g_settings_new_with_backend() and * g_settings_new_with_path(). * + * Returns: a new #GSettings object + * * Since: 2.26 */ GSettings * @@ -931,7 +960,7 @@ g_settings_new_with_backend_and_path (const gchar *schema_id, { g_return_val_if_fail (schema_id != NULL, NULL); g_return_val_if_fail (G_IS_SETTINGS_BACKEND (backend), NULL); - g_return_val_if_fail (path != NULL, NULL); + g_return_val_if_fail (path_is_valid (path), NULL); return g_object_new (G_TYPE_SETTINGS, "schema-id", schema_id, @@ -943,9 +972,8 @@ g_settings_new_with_backend_and_path (const gchar *schema_id, /** * g_settings_new_full: * @schema: a #GSettingsSchema - * @backend: a #GSettingsBackend - * @path: the path to use - * @returns: a new #GSettings object + * @backend: (allow-none): a #GSettingsBackend + * @path: (allow-none): the path to use * * Creates a new #GSettings object with a given schema, backend and * path. @@ -964,6 +992,15 @@ g_settings_new_with_backend_and_path (const gchar *schema_id, * @schema, @backend and @path, and the main context is taken from the * thread-default (as per g_settings_new()). * + * If @backend is %NULL then the default backend is used. + * + * If @path is %NULL then the path from the schema is used. It is an + * error f @path is %NULL and the schema has no path of its own or if + * @path is non-%NULL and not equal to the path that the schema does + * have. + * + * Returns: a new #GSettings object + * * Since: 2.32 */ GSettings * @@ -971,6 +1008,10 @@ g_settings_new_full (GSettingsSchema *schema, GSettingsBackend *backend, const gchar *path) { + g_return_val_if_fail (schema != NULL, NULL); + g_return_val_if_fail (backend == NULL || G_IS_SETTINGS_BACKEND (backend), NULL); + g_return_val_if_fail (path == NULL || path_is_valid (path), NULL); + return g_object_new (G_TYPE_SETTINGS, "settings-schema", schema, "backend", backend, @@ -996,14 +1037,19 @@ g_settings_write_to_backend (GSettings *settings, static GVariant * g_settings_read_from_backend (GSettings *settings, - GSettingsSchemaKey *key) + GSettingsSchemaKey *key, + gboolean user_value_only, + gboolean default_value) { GVariant *value; GVariant *fixup; gchar *path; path = g_strconcat (settings->priv->path, key->name, NULL); - value = g_settings_backend_read (settings->priv->backend, path, key->type, FALSE); + if (user_value_only) + value = g_settings_backend_read_user_value (settings->priv->backend, path, key->type); + else + value = g_settings_backend_read (settings->priv->backend, path, key->type, default_value); g_free (path); if (value != NULL) @@ -1022,13 +1068,14 @@ g_settings_read_from_backend (GSettings *settings, * g_settings_get_value: * @settings: a #GSettings object * @key: the key to get the value for - * @returns: a new #GVariant * * Gets the value that is stored in @settings for @key. * * It is a programmer error to give a @key that isn't contained in the * schema for @settings. * + * Returns: a new #GVariant + * * Since: 2.26 */ GVariant * @@ -1042,7 +1089,107 @@ g_settings_get_value (GSettings *settings, g_return_val_if_fail (key != NULL, NULL); g_settings_schema_key_init (&skey, settings->priv->schema, key); - value = g_settings_read_from_backend (settings, &skey); + 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); + + g_settings_schema_key_clear (&skey); + + return value; +} + +/** + * g_settings_get_user_value: + * @settings: a #GSettings object + * @key: the key to get the user value for + * + * Checks the "user value" of a key, if there is one. + * + * The user value of a key is the last value that was set by the user. + * + * After calling g_settings_reset() this function should always return + * %NULL (assuming something is not wrong with the system + * configuration). + * + * It is possible that g_settings_get_value() will return a different + * value than this function. This can happen in the case that the user + * set a value for a key that was subsequently locked down by the system + * administrator -- this function will return the user's old value. + * + * This function may be useful for adding a "reset" option to a UI or + * for providing indication that a particular value has been changed. + * + * It is a programmer error to give a @key that isn't contained in the + * schema for @settings. + * + * Returns: (allow-none) (transfer full): the user's value, if set + * + * Since: 2.40 + **/ +GVariant * +g_settings_get_user_value (GSettings *settings, + const gchar *key) +{ + GSettingsSchemaKey skey; + GVariant *value; + + g_return_val_if_fail (G_IS_SETTINGS (settings), NULL); + g_return_val_if_fail (key != NULL, NULL); + + g_settings_schema_key_init (&skey, settings->priv->schema, key); + value = g_settings_read_from_backend (settings, &skey, TRUE, FALSE); + g_settings_schema_key_clear (&skey); + + return value; +} + +/** + * g_settings_get_default_value: + * @settings: a #GSettings object + * @key: the key to get the default value for + * + * Gets the "default value" of a key. + * + * This is the value that would be read if g_settings_reset() were to be + * called on the key. + * + * Note that this may be a different value than returned by + * g_settings_schema_key_get_default_value() if the system administrator + * has provided a default value. + * + * Comparing the return values of g_settings_get_default_value() and + * g_settings_get_value() is not sufficient for determining if a value + * has been set because the user may have explicitly set the value to + * something that happens to be equal to the default. The difference + * here is that if the default changes in the future, the user's key + * will still be set. + * + * This function may be useful for adding an indication to a UI of what + * the default value was before the user set it. + * + * It is a programmer error to give a @key that isn't contained in the + * schema for @settings. + * + * Returns: (allow-none) (transfer full): the default value + * + * Since: 2.40 + **/ +GVariant * +g_settings_get_default_value (GSettings *settings, + const gchar *key) +{ + GSettingsSchemaKey skey; + GVariant *value; + + g_return_val_if_fail (G_IS_SETTINGS (settings), NULL); + g_return_val_if_fail (key != NULL, NULL); + + g_settings_schema_key_init (&skey, settings->priv->schema, key); + value = g_settings_read_from_backend (settings, &skey, FALSE, TRUE); if (value == NULL) value = g_settings_schema_key_get_translated_default (&skey); @@ -1059,7 +1206,6 @@ g_settings_get_value (GSettings *settings, * g_settings_get_enum: * @settings: a #GSettings object * @key: the key to get the value for - * @returns: the enum value * * Gets the value that is stored in @settings for @key and converts it * to the enum value that it represents. @@ -1074,6 +1220,8 @@ g_settings_get_value (GSettings *settings, * value for the enumerated type then this function will return the * default value. * + * Returns: the enum value + * * Since: 2.26 **/ gint @@ -1091,13 +1239,13 @@ g_settings_get_enum (GSettings *settings, if (!skey.is_enum) { - g_critical ("g_settings_get_enum() called on key `%s' which is not " + g_critical ("g_settings_get_enum() called on key '%s' which is not " "associated with an enumerated type", skey.name); g_settings_schema_key_clear (&skey); return -1; } - value = g_settings_read_from_backend (settings, &skey); + value = g_settings_read_from_backend (settings, &skey, FALSE, FALSE); if (value == NULL) value = g_settings_schema_key_get_translated_default (&skey); @@ -1117,7 +1265,6 @@ g_settings_get_enum (GSettings *settings, * @settings: a #GSettings object * @key: a key, within @settings * @value: an enumerated value - * @returns: %TRUE, if the set succeeds * * Looks up the enumerated type nick for @value and writes it to @key, * within @settings. @@ -1129,6 +1276,8 @@ g_settings_get_enum (GSettings *settings, * After performing the write, accessing @key directly with * g_settings_get_string() will return the 'nick' associated with * @value. + * + * Returns: %TRUE, if the set succeeds **/ gboolean g_settings_set_enum (GSettings *settings, @@ -1146,15 +1295,15 @@ g_settings_set_enum (GSettings *settings, if (!skey.is_enum) { - g_critical ("g_settings_set_enum() called on key `%s' which is not " + g_critical ("g_settings_set_enum() called on key '%s' which is not " "associated with an enumerated type", skey.name); return FALSE; } if (!(variant = g_settings_schema_key_from_enum (&skey, value))) { - g_critical ("g_settings_set_enum(): invalid enum value %d for key `%s' " - "in schema `%s'. Doing nothing.", value, skey.name, + g_critical ("g_settings_set_enum(): invalid enum value %d for key '%s' " + "in schema '%s'. Doing nothing.", value, skey.name, g_settings_schema_get_id (skey.schema)); g_settings_schema_key_clear (&skey); return FALSE; @@ -1170,7 +1319,6 @@ g_settings_set_enum (GSettings *settings, * 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. @@ -1185,6 +1333,8 @@ g_settings_set_enum (GSettings *settings, * value for the flags type then this function will return the default * value. * + * Returns: the flags value + * * Since: 2.26 **/ guint @@ -1202,13 +1352,13 @@ g_settings_get_flags (GSettings *settings, if (!skey.is_flags) { - g_critical ("g_settings_get_flags() called on key `%s' which is not " + g_critical ("g_settings_get_flags() called on key '%s' which is not " "associated with a flags type", skey.name); g_settings_schema_key_clear (&skey); return -1; } - value = g_settings_read_from_backend (settings, &skey); + value = g_settings_read_from_backend (settings, &skey, FALSE, FALSE); if (value == NULL) value = g_settings_schema_key_get_translated_default (&skey); @@ -1228,7 +1378,6 @@ g_settings_get_flags (GSettings *settings, * @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, within @@ -1241,6 +1390,8 @@ g_settings_get_flags (GSettings *settings, * After performing the write, accessing @key directly with * g_settings_get_strv() will return an array of 'nicks'; one for each * bit in @value. + * + * Returns: %TRUE, if the set succeeds **/ gboolean g_settings_set_flags (GSettings *settings, @@ -1258,7 +1409,7 @@ g_settings_set_flags (GSettings *settings, if (!skey.is_flags) { - g_critical ("g_settings_set_flags() called on key `%s' which is not " + g_critical ("g_settings_set_flags() called on key '%s' which is not " "associated with a flags type", skey.name); return FALSE; } @@ -1266,7 +1417,7 @@ g_settings_set_flags (GSettings *settings, if (!(variant = g_settings_schema_key_from_flags (&skey, value))) { g_critical ("g_settings_set_flags(): invalid flags value 0x%08x " - "for key `%s' in schema `%s'. Doing nothing.", + "for key '%s' in schema '%s'. Doing nothing.", value, skey.name, g_settings_schema_get_id (skey.schema)); g_settings_schema_key_clear (&skey); return FALSE; @@ -1283,8 +1434,6 @@ g_settings_set_flags (GSettings *settings, * @settings: a #GSettings object * @key: the name of the key to set * @value: a #GVariant of the correct type - * @returns: %TRUE if setting the key succeeded, - * %FALSE if the key was not writable * * Sets @key in @settings to @value. * @@ -1294,6 +1443,9 @@ g_settings_set_flags (GSettings *settings, * * If @value is floating then this function consumes the reference. * + * Returns: %TRUE if setting the key succeeded, + * %FALSE if the key was not writable + * * Since: 2.26 **/ gboolean @@ -1302,6 +1454,7 @@ g_settings_set_value (GSettings *settings, GVariant *value) { GSettingsSchemaKey skey; + gboolean success; g_return_val_if_fail (G_IS_SETTINGS (settings), FALSE); g_return_val_if_fail (key != NULL, FALSE); @@ -1329,9 +1482,10 @@ g_settings_set_value (GSettings *settings, return FALSE; } + success = g_settings_write_to_backend (settings, &skey, value); g_settings_schema_key_clear (&skey); - return g_settings_write_to_backend (settings, &skey, value); + return success; } /** @@ -1363,6 +1517,13 @@ g_settings_get (GSettings *settings, value = g_settings_get_value (settings, key); + if (strchr (format, '&')) + { + g_critical ("%s: the format string may not contain '&' (key '%s' from schema '%s'). " + "This call will probably stop working with a future version of glib.", + G_STRFUNC, key, g_settings_schema_get_id (settings->priv->schema)); + } + va_start (ap, format); g_variant_get_va (value, format, NULL, &ap); va_end (ap); @@ -1376,8 +1537,6 @@ g_settings_get (GSettings *settings, * @key: the name of the key to set * @format: a #GVariant format string * @...: arguments as per @format - * @returns: %TRUE if setting the key succeeded, - * %FALSE if the key was not writable * * Sets @key in @settings to @value. * @@ -1388,6 +1547,9 @@ g_settings_get (GSettings *settings, * schema for @settings or for the #GVariantType of @format to mismatch * the type given in the schema. * + * Returns: %TRUE if setting the key succeeded, + * %FALSE if the key was not writable + * * Since: 2.26 */ gboolean @@ -1413,7 +1575,6 @@ g_settings_set (GSettings *settings, * @mapping: (scope call): the function to map the value in the * settings database to the value used by the application * @user_data: user data for @mapping - * @returns: (transfer full): the result, which may be %NULL * * Gets the value that is stored at @key in @settings, subject to * application-level validation/mapping. @@ -1423,7 +1584,7 @@ g_settings_set (GSettings *settings, * @mapping function performs that processing. If the function * indicates that the processing was unsuccessful (due to a parse error, * for example) then the mapping is tried again with another value. - + * * This allows a robust 'fall back to defaults' behaviour to be * implemented somewhat automatically. * @@ -1442,6 +1603,8 @@ g_settings_set (GSettings *settings, * to each invocation of @mapping. The final value of that #gpointer is * what is returned by this function. %NULL is valid; it is returned * just as any other value would be. + * + * Returns: (transfer full): the result, which may be %NULL **/ gpointer g_settings_get_mapped (GSettings *settings, @@ -1460,7 +1623,7 @@ g_settings_get_mapped (GSettings *settings, g_settings_schema_key_init (&skey, settings->priv->schema, key); - if ((value = g_settings_read_from_backend (settings, &skey))) + if ((value = g_settings_read_from_backend (settings, &skey, FALSE, FALSE))) { okay = mapping (value, &result, user_data); g_variant_unref (value); @@ -1479,7 +1642,7 @@ g_settings_get_mapped (GSettings *settings, if (!mapping (NULL, &result, user_data)) g_error ("The mapping function given to g_settings_get_mapped() for key " - "`%s' in schema `%s' returned FALSE when given a NULL value.", + "'%s' in schema '%s' returned FALSE when given a NULL value.", key, g_settings_schema_get_id (settings->priv->schema)); okay: @@ -1493,7 +1656,6 @@ g_settings_get_mapped (GSettings *settings, * g_settings_get_string: * @settings: a #GSettings object * @key: the key to get the value for - * @returns: a newly-allocated string * * Gets the value that is stored at @key in @settings. * @@ -1502,6 +1664,8 @@ g_settings_get_mapped (GSettings *settings, * It is a programmer error to give a @key that isn't specified as * having a string type in the schema for @settings. * + * Returns: a newly-allocated string + * * Since: 2.26 */ gchar * @@ -1523,8 +1687,6 @@ g_settings_get_string (GSettings *settings, * @settings: a #GSettings object * @key: the name of the key to set * @value: the value to set it to - * @returns: %TRUE if setting the key succeeded, - * %FALSE if the key was not writable * * Sets @key in @settings to @value. * @@ -1533,6 +1695,9 @@ g_settings_get_string (GSettings *settings, * It is a programmer error to give a @key that isn't specified as * having a string type in the schema for @settings. * + * Returns: %TRUE if setting the key succeeded, + * %FALSE if the key was not writable + * * Since: 2.26 */ gboolean @@ -1547,7 +1712,6 @@ g_settings_set_string (GSettings *settings, * g_settings_get_int: * @settings: a #GSettings object * @key: the key to get the value for - * @returns: an integer * * Gets the value that is stored at @key in @settings. * @@ -1556,6 +1720,8 @@ g_settings_set_string (GSettings *settings, * It is a programmer error to give a @key that isn't specified as * having a int32 type in the schema for @settings. * + * Returns: an integer + * * Since: 2.26 */ gint @@ -1577,8 +1743,6 @@ g_settings_get_int (GSettings *settings, * @settings: a #GSettings object * @key: the name of the key to set * @value: the value to set it to - * @returns: %TRUE if setting the key succeeded, - * %FALSE if the key was not writable * * Sets @key in @settings to @value. * @@ -1587,6 +1751,9 @@ g_settings_get_int (GSettings *settings, * It is a programmer error to give a @key that isn't specified as * having a int32 type in the schema for @settings. * + * Returns: %TRUE if setting the key succeeded, + * %FALSE if the key was not writable + * * Since: 2.26 */ gboolean @@ -1601,7 +1768,6 @@ g_settings_set_int (GSettings *settings, * g_settings_get_uint: * @settings: a #GSettings object * @key: the key to get the value for - * @returns: an unsigned integer * * Gets the value that is stored at @key in @settings. * @@ -1611,6 +1777,8 @@ g_settings_set_int (GSettings *settings, * It is a programmer error to give a @key that isn't specified as * having a uint32 type in the schema for @settings. * + * Returns: an unsigned integer + * * Since: 2.30 */ guint @@ -1632,8 +1800,6 @@ g_settings_get_uint (GSettings *settings, * @settings: a #GSettings object * @key: the name of the key to set * @value: the value to set it to - * @returns: %TRUE if setting the key succeeded, - * %FALSE if the key was not writable * * Sets @key in @settings to @value. * @@ -1643,6 +1809,9 @@ g_settings_get_uint (GSettings *settings, * It is a programmer error to give a @key that isn't specified as * having a uint32 type in the schema for @settings. * + * Returns: %TRUE if setting the key succeeded, + * %FALSE if the key was not writable + * * Since: 2.30 */ gboolean @@ -1657,7 +1826,6 @@ g_settings_set_uint (GSettings *settings, * g_settings_get_double: * @settings: a #GSettings object * @key: the key to get the value for - * @returns: a double * * Gets the value that is stored at @key in @settings. * @@ -1666,6 +1834,8 @@ g_settings_set_uint (GSettings *settings, * It is a programmer error to give a @key that isn't specified as * having a 'double' type in the schema for @settings. * + * Returns: a double + * * Since: 2.26 */ gdouble @@ -1687,8 +1857,6 @@ g_settings_get_double (GSettings *settings, * @settings: a #GSettings object * @key: the name of the key to set * @value: the value to set it to - * @returns: %TRUE if setting the key succeeded, - * %FALSE if the key was not writable * * Sets @key in @settings to @value. * @@ -1697,6 +1865,9 @@ g_settings_get_double (GSettings *settings, * It is a programmer error to give a @key that isn't specified as * having a 'double' type in the schema for @settings. * + * Returns: %TRUE if setting the key succeeded, + * %FALSE if the key was not writable + * * Since: 2.26 */ gboolean @@ -1711,7 +1882,6 @@ g_settings_set_double (GSettings *settings, * g_settings_get_boolean: * @settings: a #GSettings object * @key: the key to get the value for - * @returns: a boolean * * Gets the value that is stored at @key in @settings. * @@ -1720,6 +1890,8 @@ g_settings_set_double (GSettings *settings, * It is a programmer error to give a @key that isn't specified as * having a boolean type in the schema for @settings. * + * Returns: a boolean + * * Since: 2.26 */ gboolean @@ -1741,8 +1913,6 @@ g_settings_get_boolean (GSettings *settings, * @settings: a #GSettings object * @key: the name of the key to set * @value: the value to set it to - * @returns: %TRUE if setting the key succeeded, - * %FALSE if the key was not writable * * Sets @key in @settings to @value. * @@ -1751,6 +1921,9 @@ g_settings_get_boolean (GSettings *settings, * It is a programmer error to give a @key that isn't specified as * having a boolean type in the schema for @settings. * + * Returns: %TRUE if setting the key succeeded, + * %FALSE if the key was not writable + * * Since: 2.26 */ gboolean @@ -1765,15 +1938,16 @@ g_settings_set_boolean (GSettings *settings, * g_settings_get_strv: * @settings: a #GSettings object * @key: the key to get the value for - * @returns: (array zero-terminated=1) (transfer full): a - * newly-allocated, %NULL-terminated array of strings, the value that - * is stored at @key in @settings. * * A convenience variant of g_settings_get() for string arrays. * * It is a programmer error to give a @key that isn't specified as * having an array of strings type in the schema for @settings. * + * Returns: (array zero-terminated=1) (transfer full): a + * newly-allocated, %NULL-terminated array of strings, the value that + * is stored at @key in @settings. + * * Since: 2.26 */ gchar ** @@ -1795,8 +1969,6 @@ g_settings_get_strv (GSettings *settings, * @settings: a #GSettings object * @key: the name of the key to set * @value: (allow-none) (array zero-terminated=1): the value to set it to, or %NULL - * @returns: %TRUE if setting the key succeeded, - * %FALSE if the key was not writable * * Sets @key in @settings to @value. * @@ -1806,6 +1978,9 @@ g_settings_get_strv (GSettings *settings, * It is a programmer error to give a @key that isn't specified as * having an array of strings type in the schema for @settings. * + * Returns: %TRUE if setting the key succeeded, + * %FALSE if the key was not writable + * * Since: 2.26 */ gboolean @@ -1904,11 +2079,12 @@ g_settings_revert (GSettings *settings) /** * g_settings_get_has_unapplied: * @settings: a #GSettings object - * @returns: %TRUE if @settings has unapplied changes * * Returns whether the #GSettings object has any unapplied * changes. This can only be the case if it is in 'delayed-apply' mode. * + * Returns: %TRUE if @settings has unapplied changes + * * Since: 2.26 */ gboolean @@ -1969,10 +2145,11 @@ g_settings_sync (void) * g_settings_is_writable: * @settings: a #GSettings object * @name: the name of a key - * @returns: %TRUE if the key @name is writable * * Finds out if a key can be written or not * + * Returns: %TRUE if the key @name is writable + * * Since: 2.26 */ gboolean @@ -1994,15 +2171,16 @@ g_settings_is_writable (GSettings *settings, /** * g_settings_get_child: * @settings: a #GSettings object - * @name: the name of the 'child' schema - * @returns: (transfer full): a 'child' settings object + * @name: the name of the child schema * - * Creates a 'child' settings object which has a base path of - * base-path/@name, where - * base-path is the base path of @settings. + * Creates a child settings object which has a base path of + * `base-path/@name`, where `base-path` is the base path of + * @settings. * * The schema for the child settings object must have been declared - * in the schema of @settings using a child element. + * in the schema of @settings using a element. + * + * Returns: (transfer full): a 'child' settings object * * Since: 2.26 */ @@ -2026,6 +2204,7 @@ g_settings_get_child (GSettings *settings, child_path = g_strconcat (settings->priv->path, child_name, NULL); child = g_object_new (G_TYPE_SETTINGS, + "backend", settings->priv->backend, "schema-id", child_schema, "path", child_path, NULL); @@ -2038,7 +2217,6 @@ g_settings_get_child (GSettings *settings, /** * g_settings_list_keys: * @settings: a #GSettings object - * @returns: (transfer full) (element-type utf8): a list of the keys on @settings * * Introspects the list of keys on @settings. * @@ -2048,6 +2226,8 @@ g_settings_get_child (GSettings *settings, * * You should free the return value with g_strfreev() when you are done * with it. + * + * Returns: (transfer full) (element-type utf8): a list of the keys on @settings */ gchar ** g_settings_list_keys (GSettings *settings) @@ -2074,7 +2254,6 @@ g_settings_list_keys (GSettings *settings) /** * g_settings_list_children: * @settings: a #GSettings object - * @returns: (transfer full) (element-type utf8): a list of the children on @settings * * Gets the list of children on @settings. * @@ -2095,6 +2274,8 @@ g_settings_list_keys (GSettings *settings) * * You should free the return value with g_strfreev() when you are done * with it. + * + * Returns: (transfer full) (element-type utf8): a list of the children on @settings */ gchar ** g_settings_list_children (GSettings *settings) @@ -2128,82 +2309,25 @@ g_settings_list_children (GSettings *settings) * 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 (sv). 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 'type' 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 'enum' 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 'flags' 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 ['x', - * 'y'] then the valid values for the key would be - * [], ['x'], - * ['y'], ['x', 'y'] and - * ['y', 'x']. - * - * Finally, if the string is 'range' 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 + * + * Deprecated:2.40:Use g_settings_schema_key_get_range() instead. **/ GVariant * g_settings_get_range (GSettings *settings, const gchar *key) { GSettingsSchemaKey skey; - const gchar *type; GVariant *range; g_settings_schema_key_init (&skey, settings->priv->schema, key); - - if (skey.minimum) - { - range = g_variant_new ("(**)", skey.minimum, skey.maximum); - type = "range"; - } - else if (skey.strinfo) - { - range = strinfo_enumerate (skey.strinfo, skey.strinfo_length); - type = skey.is_flags ? "flags" : "enum"; - } - else - { - range = g_variant_new_array (skey.type, NULL, 0); - type = "type"; - } - + range = g_settings_schema_key_get_range (&skey); g_settings_schema_key_clear (&skey); - return g_variant_ref_sink (g_variant_new ("(sv)", type, range)); + return range; } /** @@ -2211,19 +2335,15 @@ g_settings_get_range (GSettings *settings, * @settings: a #GSettings * @key: the key to check * @value: the value to check - * @returns: %TRUE if @value is valid for @key * * Checks if the given @value is of the correct type and within the * permitted range for @key. * - * This API is not intended to be used by normal programs -- they should - * already know what is permitted by their own schemas. This API is - * meant to be used by programs such as editors or commandline tools. - * - * It is a programmer error to give a @key that isn't contained in the - * schema for @settings. + * Returns: %TRUE if @value is valid for @key * * Since: 2.28 + * + * Deprecated:2.40:Use g_settings_schema_key_range_check() instead. **/ gboolean g_settings_range_check (GSettings *settings, @@ -2234,8 +2354,7 @@ g_settings_range_check (GSettings *settings, gboolean good; g_settings_schema_key_init (&skey, settings->priv->schema, key); - good = g_settings_schema_key_type_check (&skey, value) && - g_settings_schema_key_range_check (&skey, value); + good = g_settings_schema_key_range_check (&skey, value); g_settings_schema_key_clear (&skey); return good; @@ -2324,7 +2443,7 @@ g_settings_binding_key_changed (GSettings *settings, g_value_init (&value, binding->property->value_type); - variant = g_settings_read_from_backend (binding->settings, &binding->key); + variant = g_settings_read_from_backend (binding->settings, &binding->key, FALSE, FALSE); if (variant && !binding->get_mapping (&value, variant, binding->user_data)) { /* silently ignore errors in the user's config database */ @@ -2339,7 +2458,7 @@ g_settings_binding_key_changed (GSettings *settings, !binding->get_mapping (&value, variant, binding->user_data)) { /* flag translation errors with a warning */ - g_warning ("Translated default `%s' for key `%s' in schema `%s' " + g_warning ("Translated default '%s' for key '%s' in schema '%s' " "was rejected by the binding mapping function", binding->key.unparsed, binding->key.name, g_settings_schema_get_id (binding->key.schema)); @@ -2352,7 +2471,7 @@ g_settings_binding_key_changed (GSettings *settings, { variant = g_variant_ref (binding->key.default_value); if (!binding->get_mapping (&value, variant, binding->user_data)) - g_error ("The schema default value for key `%s' in schema `%s' " + g_error ("The schema 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)); } @@ -2390,8 +2509,8 @@ g_settings_binding_property_changed (GObject *object, if (!g_settings_schema_key_type_check (&binding->key, variant)) { - g_critical ("binding mapping function for key `%s' returned " - "GVariant of type `%s' when type `%s' was requested", + g_critical ("binding mapping function for key '%s' returned " + "GVariant of type '%s' when type '%s' was requested", binding->key.name, g_variant_get_type_string (variant), g_variant_type_dup_string (binding->key.type)); return; @@ -2399,8 +2518,8 @@ g_settings_binding_property_changed (GObject *object, if (!g_settings_schema_key_range_check (&binding->key, variant)) { - g_critical ("GObject property `%s' on a `%s' object is out of " - "schema-specified range for key `%s' of `%s': %s", + g_critical ("GObject property '%s' on a '%s' object is out of " + "schema-specified range for key '%s' of '%s': %s", binding->property->name, g_type_name (binding->property->owner_type), binding->key.name, g_settings_schema_get_id (binding->key.schema), g_variant_print (variant, TRUE)); @@ -2561,14 +2680,14 @@ g_settings_bind_with_mapping (GSettings *settings, (binding->property->flags & G_PARAM_WRITABLE) == 0) { g_critical ("g_settings_bind: property '%s' on class '%s' is not " - "writable", property, G_OBJECT_TYPE_NAME (object)); + "writable", binding->property->name, G_OBJECT_TYPE_NAME (object)); return; } if ((flags & G_SETTINGS_BIND_SET) && (binding->property->flags & G_PARAM_READABLE) == 0) { g_critical ("g_settings_bind: property '%s' on class '%s' is not " - "readable", property, G_OBJECT_TYPE_NAME (object)); + "readable", binding->property->name, G_OBJECT_TYPE_NAME (object)); return; } @@ -2584,8 +2703,8 @@ g_settings_bind_with_mapping (GSettings *settings, if (binding->property->value_type != G_TYPE_BOOLEAN) { g_critical ("g_settings_bind: G_SETTINGS_BIND_INVERT_BOOLEAN " - "was specified, but property `%s' on type `%s' has " - "type `%s'", property, G_OBJECT_TYPE_NAME (object), + "was specified, but property '%s' on type '%s' has " + "type '%s'", binding->property->name, G_OBJECT_TYPE_NAME (object), g_type_name ((binding->property->value_type))); return; } @@ -2593,8 +2712,8 @@ g_settings_bind_with_mapping (GSettings *settings, if (!g_variant_type_equal (binding->key.type, G_VARIANT_TYPE_BOOLEAN)) { g_critical ("g_settings_bind: G_SETTINGS_BIND_INVERT_BOOLEAN " - "was specified, but key `%s' on schema `%s' has " - "type `%s'", key, g_settings_schema_get_id (settings->priv->schema), + "was specified, but key '%s' on schema '%s' has " + "type '%s'", key, g_settings_schema_get_id (settings->priv->schema), g_variant_type_dup_string (binding->key.type)); return; } @@ -2608,7 +2727,7 @@ g_settings_bind_with_mapping (GSettings *settings, { g_critical ("g_settings_bind: property '%s' on class '%s' has type " "'%s' which is not compatible with type '%s' of key '%s' " - "on schema '%s'", property, G_OBJECT_TYPE_NAME (object), + "on schema '%s'", binding->property->name, G_OBJECT_TYPE_NAME (object), g_type_name (binding->property->value_type), g_variant_type_dup_string (binding->key.type), key, g_settings_schema_get_id (settings->priv->schema)); @@ -2629,7 +2748,7 @@ g_settings_bind_with_mapping (GSettings *settings, if (flags & G_SETTINGS_BIND_SET) { - detailed_signal = g_strdup_printf ("notify::%s", property); + detailed_signal = g_strdup_printf ("notify::%s", binding->property->name); binding->property_handler_id = g_signal_connect (object, detailed_signal, G_CALLBACK (g_settings_binding_property_changed), @@ -2657,7 +2776,7 @@ g_settings_bind_with_mapping (GSettings *settings, g_settings_binding_key_changed (settings, binding->key.name, binding); } - binding_quark = g_settings_binding_quark (property); + binding_quark = g_settings_binding_quark (binding->property->name); g_object_set_qdata_full (object, binding_quark, binding, g_settings_binding_free); } @@ -2721,8 +2840,7 @@ g_settings_binding_writable_changed (GSettings *settings, * * When the @inverted argument is %TRUE, the binding inverts the * value as it passes from the setting to the object, i.e. @property - * will be set to %TRUE if the key is not - * writable. + * will be set to %TRUE if the key is not writable. * * Note that the lifecycle of the binding is tied to the object, * and that you can have only one binding per object property. @@ -2801,6 +2919,267 @@ g_settings_unbind (gpointer object, g_object_set_qdata (object, binding_quark, NULL); } +/* GAction {{{1 */ + +typedef struct +{ + GObject parent_instance; + + GSettingsSchemaKey key; + GSettings *settings; +} GSettingsAction; + +typedef GObjectClass GSettingsActionClass; + +static GType g_settings_action_get_type (void); +static void g_settings_action_iface_init (GActionInterface *iface); +G_DEFINE_TYPE_WITH_CODE (GSettingsAction, g_settings_action, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (G_TYPE_ACTION, g_settings_action_iface_init)) + +enum +{ + ACTION_PROP_0, + ACTION_PROP_NAME, + ACTION_PROP_PARAMETER_TYPE, + ACTION_PROP_ENABLED, + ACTION_PROP_STATE_TYPE, + ACTION_PROP_STATE +}; + +static const gchar * +g_settings_action_get_name (GAction *action) +{ + GSettingsAction *gsa = (GSettingsAction *) action; + + return gsa->key.name; +} + +static const GVariantType * +g_settings_action_get_parameter_type (GAction *action) +{ + GSettingsAction *gsa = (GSettingsAction *) action; + const GVariantType *type; + + type = g_variant_get_type (gsa->key.default_value); + if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN)) + type = NULL; + + return type; +} + +static gboolean +g_settings_action_get_enabled (GAction *action) +{ + GSettingsAction *gsa = (GSettingsAction *) action; + + return g_settings_is_writable (gsa->settings, gsa->key.name); +} + +static const GVariantType * +g_settings_action_get_state_type (GAction *action) +{ + GSettingsAction *gsa = (GSettingsAction *) action; + + return g_variant_get_type (gsa->key.default_value); +} + +static GVariant * +g_settings_action_get_state (GAction *action) +{ + GSettingsAction *gsa = (GSettingsAction *) action; + GVariant *value; + + value = g_settings_read_from_backend (gsa->settings, &gsa->key, FALSE, FALSE); + + if (value == NULL) + value = g_settings_schema_key_get_translated_default (&gsa->key); + + if (value == NULL) + value = g_variant_ref (gsa->key.default_value); + + return value; +} + +static GVariant * +g_settings_action_get_state_hint (GAction *action) +{ + GSettingsAction *gsa = (GSettingsAction *) action; + + /* no point in reimplementing this... */ + return g_settings_schema_key_get_range (&gsa->key); +} + +static void +g_settings_action_change_state (GAction *action, + GVariant *value) +{ + GSettingsAction *gsa = (GSettingsAction *) action; + + if (g_settings_schema_key_type_check (&gsa->key, value) && g_settings_schema_key_range_check (&gsa->key, value)) + g_settings_write_to_backend (gsa->settings, &gsa->key, value); +} + +static void +g_settings_action_activate (GAction *action, + GVariant *parameter) +{ + GSettingsAction *gsa = (GSettingsAction *) action; + + if (g_variant_is_of_type (gsa->key.default_value, G_VARIANT_TYPE_BOOLEAN)) + { + GVariant *old; + + if (parameter != NULL) + return; + + old = g_settings_action_get_state (action); + parameter = g_variant_new_boolean (!g_variant_get_boolean (old)); + g_variant_unref (old); + } + + g_action_change_state (action, parameter); +} + +static void +g_settings_action_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + GAction *action = G_ACTION (object); + + switch (prop_id) + { + case ACTION_PROP_NAME: + g_value_set_string (value, g_settings_action_get_name (action)); + break; + + case ACTION_PROP_PARAMETER_TYPE: + g_value_set_boxed (value, g_settings_action_get_parameter_type (action)); + break; + + case ACTION_PROP_ENABLED: + g_value_set_boolean (value, g_settings_action_get_enabled (action)); + break; + + case ACTION_PROP_STATE_TYPE: + g_value_set_boxed (value, g_settings_action_get_state_type (action)); + break; + + case ACTION_PROP_STATE: + g_value_set_variant (value, g_settings_action_get_state (action)); + break; + + default: + g_assert_not_reached (); + } +} + +static void +g_settings_action_finalize (GObject *object) +{ + GSettingsAction *gsa = (GSettingsAction *) object; + + g_signal_handlers_disconnect_by_data (gsa->settings, gsa); + g_object_unref (gsa->settings); + + G_OBJECT_CLASS (g_settings_action_parent_class) + ->finalize (object); +} + +static void +g_settings_action_init (GSettingsAction *gsa) +{ +} + +static void +g_settings_action_iface_init (GActionInterface *iface) +{ + iface->get_name = g_settings_action_get_name; + iface->get_parameter_type = g_settings_action_get_parameter_type; + iface->get_enabled = g_settings_action_get_enabled; + iface->get_state_type = g_settings_action_get_state_type; + iface->get_state = g_settings_action_get_state; + iface->get_state_hint = g_settings_action_get_state_hint; + iface->change_state = g_settings_action_change_state; + iface->activate = g_settings_action_activate; +} + +static void +g_settings_action_class_init (GSettingsActionClass *class) +{ + class->get_property = g_settings_action_get_property; + class->finalize = g_settings_action_finalize; + + g_object_class_override_property (class, ACTION_PROP_NAME, "name"); + g_object_class_override_property (class, ACTION_PROP_PARAMETER_TYPE, "parameter-type"); + g_object_class_override_property (class, ACTION_PROP_ENABLED, "enabled"); + g_object_class_override_property (class, ACTION_PROP_STATE_TYPE, "state-type"); + g_object_class_override_property (class, ACTION_PROP_STATE, "state"); +} + +static void +g_settings_action_changed (GSettings *settings, + const gchar *key, + gpointer user_data) +{ + g_object_notify (user_data, "state"); +} + +static void +g_settings_action_enabled_changed (GSettings *settings, + const gchar *key, + gpointer user_data) +{ + g_object_notify (user_data, "enabled"); +} + +/** + * g_settings_create_action: + * @settings: a #GSettings + * @key: the name of a key in @settings + * + * Creates a #GAction corresponding to a given #GSettings key. + * + * The action has the same name as the key. + * + * The value of the key becomes the state of the action and the action + * is enabled when the key is writable. Changing the state of the + * action results in the key being written to. Changes to the value or + * writability of the key cause appropriate change notifications to be + * emitted for the action. + * + * For boolean-valued keys, action activations take no parameter and + * result in the toggling of the value. For all other types, + * activations take the new value for the key (which must have the + * correct type). + * + * Returns: (transfer full): a new #GAction + * + * Since: 2.32 + **/ +GAction * +g_settings_create_action (GSettings *settings, + const gchar *key) +{ + GSettingsAction *gsa; + gchar *detailed_signal; + + g_return_val_if_fail (G_IS_SETTINGS (settings), NULL); + g_return_val_if_fail (key != NULL, NULL); + + gsa = g_object_new (g_settings_action_get_type (), NULL); + gsa->settings = g_object_ref (settings); + g_settings_schema_key_init (&gsa->key, settings->priv->schema, key); + + detailed_signal = g_strdup_printf ("changed::%s", key); + g_signal_connect (settings, detailed_signal, G_CALLBACK (g_settings_action_changed), gsa); + g_free (detailed_signal); + detailed_signal = g_strdup_printf ("writable-changed::%s", key); + g_signal_connect (settings, detailed_signal, G_CALLBACK (g_settings_action_enabled_changed), gsa); + g_free (detailed_signal); + + return G_ACTION (gsa); +} + /* Epilogue {{{1 */ /* vim:set foldmethod=marker: */