1 /*
2  * Copyright © 2009, 2010 Codethink Limited
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
16  *
17  * Author: Ryan Lortie <desrt@desrt.ca>
18  */
19 
20 /* Prelude {{{1 */
21 #include "config.h"
22 
23 #include <glib.h>
24 #include <glibintl.h>
25 
26 #include "gsettings.h"
27 
28 #include "gdelayedsettingsbackend.h"
29 #include "gsettingsbackendinternal.h"
30 #include "gsettings-mapping.h"
31 #include "gsettingsschema-internal.h"
32 #include "gaction.h"
33 #include "gmarshal-internal.h"
34 
35 #include "strinfo.c"
36 
37 /**
38  * SECTION:gsettings
39  * @short_description: High-level API for application settings
40  * @include: gio/gio.h
41  *
42  * The #GSettings class provides a convenient API for storing and retrieving
43  * application settings.
44  *
45  * Reads and writes can be considered to be non-blocking.  Reading
46  * settings with #GSettings is typically extremely fast: on
47  * approximately the same order of magnitude (but slower than) a
48  * #GHashTable lookup.  Writing settings is also extremely fast in terms
49  * of time to return to your application, but can be extremely expensive
50  * for other threads and other processes.  Many settings backends
51  * (including dconf) have lazy initialisation which means in the common
52  * case of the user using their computer without modifying any settings
53  * a lot of work can be avoided.  For dconf, the D-Bus service doesn't
54  * even need to be started in this case.  For this reason, you should
55  * only ever modify #GSettings keys in response to explicit user action.
56  * Particular care should be paid to ensure that modifications are not
57  * made during startup -- for example, when setting the initial value
58  * of preferences widgets.  The built-in g_settings_bind() functionality
59  * is careful not to write settings in response to notify signals as a
60  * result of modifications that it makes to widgets.
61  *
62  * When creating a GSettings instance, you have to specify a schema
63  * that describes the keys in your settings and their types and default
64  * values, as well as some other information.
65  *
66  * Normally, a schema has a fixed path that determines where the settings
67  * are stored in the conceptual global tree of settings. However, schemas
68  * can also be '[relocatable][gsettings-relocatable]', i.e. not equipped with
69  * a fixed path. This is
70  * useful e.g. when the schema describes an 'account', and you want to be
71  * able to store a arbitrary number of accounts.
72  *
73  * Paths must start with and end with a forward slash character ('/')
74  * and must not contain two sequential slash characters.  Paths should
75  * be chosen based on a domain name associated with the program or
76  * library to which the settings belong.  Examples of paths are
77  * "/org/gtk/settings/file-chooser/" and "/ca/desrt/dconf-editor/".
78  * Paths should not start with "/apps/", "/desktop/" or "/system/" as
79  * they often did in GConf.
80  *
81  * Unlike other configuration systems (like GConf), GSettings does not
82  * restrict keys to basic types like strings and numbers. GSettings stores
83  * values as #GVariant, and allows any #GVariantType for keys. Key names
84  * are restricted to lowercase characters, numbers and '-'. Furthermore,
85  * the names must begin with a lowercase character, must not end
86  * with a '-', and must not contain consecutive dashes.
87  *
88  * Similar to GConf, the default values in GSettings schemas can be
89  * localized, but the localized values are stored in gettext catalogs
90  * and looked up with the domain that is specified in the
91  * `gettext-domain` attribute of the <schemalist> or <schema>
92  * elements and the category that is specified in the `l10n` attribute of
93  * the <default> element. The string which is translated includes all text in
94  * the <default> element, including any surrounding quotation marks.
95  *
96  * The `l10n` attribute must be set to `messages` or `time`, and sets the
97  * [locale category for
98  * translation](https://www.gnu.org/software/gettext/manual/html_node/Aspects.html#index-locale-categories-1).
99  * The `messages` category should be used by default; use `time` for
100  * translatable date or time formats. A translation comment can be added as an
101  * XML comment immediately above the <default> element — it is recommended to
102  * add these comments to aid translators understand the meaning and
103  * implications of the default value. An optional translation `context`
104  * attribute can be set on the <default> element to disambiguate multiple
105  * defaults which use the same string.
106  *
107  * For example:
108  * |[
109  *  <!-- Translators: A list of words which are not allowed to be typed, in
110  *       GVariant serialization syntax.
111  *       See: https://developer.gnome.org/glib/stable/gvariant-text.html -->
112  *  <default l10n='messages' context='Banned words'>['bad', 'words']</default>
113  * ]|
114  *
115  * Translations of default values must remain syntactically valid serialized
116  * #GVariants (e.g. retaining any surrounding quotation marks) or runtime
117  * errors will occur.
118  *
119  * GSettings uses schemas in a compact binary form that is created
120  * by the [glib-compile-schemas][glib-compile-schemas]
121  * utility. The input is a schema description in an XML format.
122  *
123  * A DTD for the gschema XML format can be found here:
124  * [gschema.dtd](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/gschema.dtd)
125  *
126  * The [glib-compile-schemas][glib-compile-schemas] tool expects schema
127  * files to have the extension `.gschema.xml`.
128  *
129  * At runtime, schemas are identified by their id (as specified in the
130  * id attribute of the <schema> element). The convention for schema
131  * ids is to use a dotted name, similar in style to a D-Bus bus name,
132  * e.g. "org.gnome.SessionManager". In particular, if the settings are
133  * for a specific service that owns a D-Bus bus name, the D-Bus bus name
134  * and schema id should match. For schemas which deal with settings not
135  * associated with one named application, the id should not use
136  * StudlyCaps, e.g. "org.gnome.font-rendering".
137  *
138  * In addition to #GVariant types, keys can have types that have
139  * enumerated types. These can be described by a <choice>,
140  * <enum> or <flags> element, as seen in the
141  * [example][schema-enumerated]. The underlying type of such a key
142  * is string, but you can use g_settings_get_enum(), g_settings_set_enum(),
143  * g_settings_get_flags(), g_settings_set_flags() access the numeric values
144  * corresponding to the string value of enum and flags keys.
145  *
146  * An example for default value:
147  * |[
148  * <schemalist>
149  *   <schema id="org.gtk.Test" path="/org/gtk/Test/" gettext-domain="test">
150  *
151  *     <key name="greeting" type="s">
152  *       <default l10n="messages">"Hello, earthlings"</default>
153  *       <summary>A greeting</summary>
154  *       <description>
155  *         Greeting of the invading martians
156  *       </description>
157  *     </key>
158  *
159  *     <key name="box" type="(ii)">
160  *       <default>(20,30)</default>
161  *     </key>
162  *
163  *     <key name="empty-string" type="s">
164  *       <default>""</default>
165  *       <summary>Empty strings have to be provided in GVariant form</summary>
166  *     </key>
167  *
168  *   </schema>
169  * </schemalist>
170  * ]|
171  *
172  * An example for ranges, choices and enumerated types:
173  * |[
174  * <schemalist>
175  *
176  *   <enum id="org.gtk.Test.myenum">
177  *     <value nick="first" value="1"/>
178  *     <value nick="second" value="2"/>
179  *   </enum>
180  *
181  *   <flags id="org.gtk.Test.myflags">
182  *     <value nick="flag1" value="1"/>
183  *     <value nick="flag2" value="2"/>
184  *     <value nick="flag3" value="4"/>
185  *   </flags>
186  *
187  *   <schema id="org.gtk.Test">
188  *
189  *     <key name="key-with-range" type="i">
190  *       <range min="1" max="100"/>
191  *       <default>10</default>
192  *     </key>
193  *
194  *     <key name="key-with-choices" type="s">
195  *       <choices>
196  *         <choice value='Elisabeth'/>
197  *         <choice value='Annabeth'/>
198  *         <choice value='Joe'/>
199  *       </choices>
200  *       <aliases>
201  *         <alias value='Anna' target='Annabeth'/>
202  *         <alias value='Beth' target='Elisabeth'/>
203  *       </aliases>
204  *       <default>'Joe'</default>
205  *     </key>
206  *
207  *     <key name='enumerated-key' enum='org.gtk.Test.myenum'>
208  *       <default>'first'</default>
209  *     </key>
210  *
211  *     <key name='flags-key' flags='org.gtk.Test.myflags'>
212  *       <default>["flag1","flag2"]</default>
213  *     </key>
214  *   </schema>
215  * </schemalist>
216  * ]|
217  *
218  * ## Vendor overrides
219  *
220  * Default values are defined in the schemas that get installed by
221  * an application. Sometimes, it is necessary for a vendor or distributor
222  * to adjust these defaults. Since patching the XML source for the schema
223  * is inconvenient and error-prone,
224  * [glib-compile-schemas][glib-compile-schemas] reads so-called vendor
225  * override' files. These are keyfiles in the same directory as the XML
226  * schema sources which can override default values. The schema id serves
227  * as the group name in the key file, and the values are expected in
228  * serialized GVariant form, as in the following example:
229  * |[
230  *     [org.gtk.Example]
231  *     key1='string'
232  *     key2=1.5
233  * ]|
234  *
235  * glib-compile-schemas expects schema files to have the extension
236  * `.gschema.override`.
237  *
238  * ## Binding
239  *
240  * A very convenient feature of GSettings lets you bind #GObject properties
241  * directly to settings, using g_settings_bind(). Once a GObject property
242  * has been bound to a setting, changes on either side are automatically
243  * propagated to the other side. GSettings handles details like mapping
244  * between GObject and GVariant types, and preventing infinite cycles.
245  *
246  * This makes it very easy to hook up a preferences dialog to the
247  * underlying settings. To make this even more convenient, GSettings
248  * looks for a boolean property with the name "sensitivity" and
249  * automatically binds it to the writability of the bound setting.
250  * If this 'magic' gets in the way, it can be suppressed with the
251  * #G_SETTINGS_BIND_NO_SENSITIVITY flag.
252  *
253  * ## Relocatable schemas # {#gsettings-relocatable}
254  *
255  * A relocatable schema is one with no `path` attribute specified on its
256  * <schema> element. By using g_settings_new_with_path(), a #GSettings object
257  * can be instantiated for a relocatable schema, assigning a path to the
258  * instance. Paths passed to g_settings_new_with_path() will typically be
259  * constructed dynamically from a constant prefix plus some form of instance
260  * identifier; but they must still be valid GSettings paths. Paths could also
261  * be constant and used with a globally installed schema originating from a
262  * dependency library.
263  *
264  * For example, a relocatable schema could be used to store geometry information
265  * for different windows in an application. If the schema ID was
266  * `org.foo.MyApp.Window`, it could be instantiated for paths
267  * `/org/foo/MyApp/main/`, `/org/foo/MyApp/document-1/`,
268  * `/org/foo/MyApp/document-2/`, etc. If any of the paths are well-known
269  * they can be specified as <child> elements in the parent schema, e.g.:
270  * |[
271  * <schema id="org.foo.MyApp" path="/org/foo/MyApp/">
272  *   <child name="main" schema="org.foo.MyApp.Window"/>
273  * </schema>
274  * ]|
275  *
276  * ## Build system integration # {#gsettings-build-system}
277  *
278  * GSettings comes with autotools integration to simplify compiling and
279  * installing schemas. To add GSettings support to an application, add the
280  * following to your `configure.ac`:
281  * |[
282  * GLIB_GSETTINGS
283  * ]|
284  *
285  * In the appropriate `Makefile.am`, use the following snippet to compile and
286  * install the named schema:
287  * |[
288  * gsettings_SCHEMAS = org.foo.MyApp.gschema.xml
289  * EXTRA_DIST = $(gsettings_SCHEMAS)
290  *
291  * @GSETTINGS_RULES@
292  * ]|
293  *
294  * No changes are needed to the build system to mark a schema XML file for
295  * translation. Assuming it sets the `gettext-domain` attribute, a schema may
296  * be marked for translation by adding it to `POTFILES.in`, assuming gettext
297  * 0.19 is in use (the preferred method for translation):
298  * |[
299  * data/org.foo.MyApp.gschema.xml
300  * ]|
301  *
302  * Alternatively, if intltool 0.50.1 is in use:
303  * |[
304  * [type: gettext/gsettings]data/org.foo.MyApp.gschema.xml
305  * ]|
306  *
307  * GSettings will use gettext to look up translations for the <summary> and
308  * <description> elements, and also any <default> elements which have a `l10n`
309  * attribute set. Translations must not be included in the `.gschema.xml` file
310  * by the build system, for example by using intltool XML rules with a
311  * `.gschema.xml.in` template.
312  *
313  * If an enumerated type defined in a C header file is to be used in a GSettings
314  * schema, it can either be defined manually using an <enum> element in the
315  * schema XML, or it can be extracted automatically from the C header. This
316  * approach is preferred, as it ensures the two representations are always
317  * synchronised. To do so, add the following to the relevant `Makefile.am`:
318  * |[
319  * gsettings_ENUM_NAMESPACE = org.foo.MyApp
320  * gsettings_ENUM_FILES = my-app-enums.h my-app-misc.h
321  * ]|
322  *
323  * `gsettings_ENUM_NAMESPACE` specifies the schema namespace for the enum files,
324  * which are specified in `gsettings_ENUM_FILES`. This will generate a
325  * `org.foo.MyApp.enums.xml` file containing the extracted enums, which will be
326  * automatically included in the schema compilation, install and uninstall
327  * rules. It should not be committed to version control or included in
328  * `EXTRA_DIST`.
329  */
330 
331 /**
332  * GSettings:
333  *
334  * #GSettings is an opaque data structure and can only be accessed
335  * using the following functions.
336  **/
337 
338 struct _GSettingsPrivate
339 {
340   /* where the signals go... */
341   GMainContext *main_context;
342 
343   GSettingsBackend *backend;
344   GSettingsSchema *schema;
345   gchar *path;
346 };
347 
348 enum
349 {
350   PROP_0,
351   PROP_SCHEMA,
352   PROP_SCHEMA_ID,
353   PROP_BACKEND,
354   PROP_PATH,
355   PROP_HAS_UNAPPLIED,
356   PROP_DELAY_APPLY
357 };
358 
359 enum
360 {
361   SIGNAL_WRITABLE_CHANGE_EVENT,
362   SIGNAL_WRITABLE_CHANGED,
363   SIGNAL_CHANGE_EVENT,
364   SIGNAL_CHANGED,
365   N_SIGNALS
366 };
367 
368 static guint g_settings_signals[N_SIGNALS];
369 
G_DEFINE_TYPE_WITH_PRIVATE(GSettings,g_settings,G_TYPE_OBJECT)370 G_DEFINE_TYPE_WITH_PRIVATE (GSettings, g_settings, G_TYPE_OBJECT)
371 
372 /* Signals {{{1 */
373 static gboolean
374 g_settings_real_change_event (GSettings    *settings,
375                               const GQuark *keys,
376                               gint          n_keys)
377 {
378   gint i;
379 
380   if (keys == NULL)
381     keys = g_settings_schema_list (settings->priv->schema, &n_keys);
382 
383   for (i = 0; i < n_keys; i++)
384     {
385       const gchar *key = g_quark_to_string (keys[i]);
386 
387       if (g_str_has_suffix (key, "/"))
388         continue;
389 
390       g_signal_emit (settings, g_settings_signals[SIGNAL_CHANGED], keys[i], key);
391     }
392 
393   return FALSE;
394 }
395 
396 static gboolean
g_settings_real_writable_change_event(GSettings * settings,GQuark key)397 g_settings_real_writable_change_event (GSettings *settings,
398                                        GQuark     key)
399 {
400   const GQuark *keys = &key;
401   gint n_keys = 1;
402   gint i;
403 
404   if (key == 0)
405     keys = g_settings_schema_list (settings->priv->schema, &n_keys);
406 
407   for (i = 0; i < n_keys; i++)
408     {
409       const gchar *key = g_quark_to_string (keys[i]);
410 
411       if (g_str_has_suffix (key, "/"))
412         continue;
413 
414       g_signal_emit (settings, g_settings_signals[SIGNAL_WRITABLE_CHANGED], keys[i], key);
415     }
416 
417   return FALSE;
418 }
419 
420 static void
settings_backend_changed(GObject * target,GSettingsBackend * backend,const gchar * key,gpointer origin_tag)421 settings_backend_changed (GObject             *target,
422                           GSettingsBackend    *backend,
423                           const gchar         *key,
424                           gpointer             origin_tag)
425 {
426   GSettings *settings = G_SETTINGS (target);
427   gboolean ignore_this;
428   gint i;
429 
430   /* We used to assert here:
431    *
432    *   settings->priv->backend == backend
433    *
434    * but it could be the case that a notification is queued for delivery
435    * while someone calls g_settings_delay() (which changes the backend).
436    *
437    * Since the delay backend would just pass that straight through
438    * anyway, it doesn't make sense to try to detect this case.
439    * Therefore, we just accept it.
440    */
441 
442   for (i = 0; key[i] == settings->priv->path[i]; i++);
443 
444   if (settings->priv->path[i] == '\0' &&
445       g_settings_schema_has_key (settings->priv->schema, key + i))
446     {
447       GQuark quark;
448 
449       quark = g_quark_from_string (key + i);
450       g_signal_emit (settings, g_settings_signals[SIGNAL_CHANGE_EVENT],
451                      0, &quark, 1, &ignore_this);
452     }
453 }
454 
455 static void
settings_backend_path_changed(GObject * target,GSettingsBackend * backend,const gchar * path,gpointer origin_tag)456 settings_backend_path_changed (GObject          *target,
457                                GSettingsBackend *backend,
458                                const gchar      *path,
459                                gpointer          origin_tag)
460 {
461   GSettings *settings = G_SETTINGS (target);
462   gboolean ignore_this;
463 
464   if (g_str_has_prefix (settings->priv->path, path))
465     g_signal_emit (settings, g_settings_signals[SIGNAL_CHANGE_EVENT],
466                    0, NULL, 0, &ignore_this);
467 }
468 
469 static void
settings_backend_keys_changed(GObject * target,GSettingsBackend * backend,const gchar * path,gpointer origin_tag,const gchar * const * items)470 settings_backend_keys_changed (GObject             *target,
471                                GSettingsBackend    *backend,
472                                const gchar         *path,
473                                gpointer             origin_tag,
474                                const gchar * const *items)
475 {
476   GSettings *settings = G_SETTINGS (target);
477   gboolean ignore_this;
478   gint i;
479 
480   for (i = 0; settings->priv->path[i] &&
481               settings->priv->path[i] == path[i]; i++);
482 
483   if (path[i] == '\0')
484     {
485       GQuark quarks[256];
486       gint j, l = 0;
487 
488       for (j = 0; items[j]; j++)
489          {
490            const gchar *item = items[j];
491            gint k;
492 
493            for (k = 0; item[k] == settings->priv->path[i + k]; k++);
494 
495            if (settings->priv->path[i + k] == '\0' &&
496                g_settings_schema_has_key (settings->priv->schema, item + k))
497              quarks[l++] = g_quark_from_string (item + k);
498 
499            /* "256 quarks ought to be enough for anybody!"
500             * If this bites you, I'm sorry.  Please file a bug.
501             */
502            g_assert (l < 256);
503          }
504 
505       if (l > 0)
506         g_signal_emit (settings, g_settings_signals[SIGNAL_CHANGE_EVENT],
507                        0, quarks, l, &ignore_this);
508     }
509 }
510 
511 static void
settings_backend_writable_changed(GObject * target,GSettingsBackend * backend,const gchar * key)512 settings_backend_writable_changed (GObject          *target,
513                                    GSettingsBackend *backend,
514                                    const gchar      *key)
515 {
516   GSettings *settings = G_SETTINGS (target);
517   gboolean ignore_this;
518   gint i;
519 
520   for (i = 0; key[i] == settings->priv->path[i]; i++);
521 
522   if (settings->priv->path[i] == '\0' &&
523       g_settings_schema_has_key (settings->priv->schema, key + i))
524     g_signal_emit (settings, g_settings_signals[SIGNAL_WRITABLE_CHANGE_EVENT],
525                    0, g_quark_from_string (key + i), &ignore_this);
526 }
527 
528 static void
settings_backend_path_writable_changed(GObject * target,GSettingsBackend * backend,const gchar * path)529 settings_backend_path_writable_changed (GObject          *target,
530                                         GSettingsBackend *backend,
531                                         const gchar      *path)
532 {
533   GSettings *settings = G_SETTINGS (target);
534   gboolean ignore_this;
535 
536   if (g_str_has_prefix (settings->priv->path, path))
537     g_signal_emit (settings, g_settings_signals[SIGNAL_WRITABLE_CHANGE_EVENT],
538                    0, (GQuark) 0, &ignore_this);
539 }
540 
541 /* Properties, Construction, Destruction {{{1 */
542 static void
g_settings_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)543 g_settings_set_property (GObject      *object,
544                          guint         prop_id,
545                          const GValue *value,
546                          GParamSpec   *pspec)
547 {
548   GSettings *settings = G_SETTINGS (object);
549 
550   switch (prop_id)
551     {
552     case PROP_SCHEMA:
553       {
554         GSettingsSchema *schema;
555 
556         schema = g_value_dup_boxed (value);
557 
558         /* we receive a set_property() call for "settings-schema" even
559          * if it was not specified (ie: with NULL value).  ->schema
560          * could already be set at this point (ie: via "schema-id").
561          * check for NULL to avoid clobbering the existing value.
562          */
563         if (schema != NULL)
564           {
565             g_assert (settings->priv->schema == NULL);
566             settings->priv->schema = schema;
567           }
568       }
569       break;
570 
571     case PROP_SCHEMA_ID:
572       {
573         const gchar *schema_id;
574 
575         schema_id = g_value_get_string (value);
576 
577         /* we receive a set_property() call for both "schema" and
578          * "schema-id", even if they are not set.  Hopefully only one of
579          * them is non-NULL.
580          */
581         if (schema_id != NULL)
582           {
583             GSettingsSchemaSource *default_source;
584 
585             g_assert (settings->priv->schema == NULL);
586             default_source = g_settings_schema_source_get_default ();
587 
588             if (default_source == NULL)
589               g_error ("No GSettings schemas are installed on the system");
590 
591             settings->priv->schema = g_settings_schema_source_lookup (default_source, schema_id, TRUE);
592 
593             if (settings->priv->schema == NULL)
594               g_error ("Settings schema '%s' is not installed", schema_id);
595           }
596       }
597       break;
598 
599     case PROP_PATH:
600       settings->priv->path = g_value_dup_string (value);
601       break;
602 
603     case PROP_BACKEND:
604       settings->priv->backend = g_value_dup_object (value);
605       break;
606 
607     default:
608       g_assert_not_reached ();
609     }
610 }
611 
612 static void
g_settings_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)613 g_settings_get_property (GObject    *object,
614                          guint       prop_id,
615                          GValue     *value,
616                          GParamSpec *pspec)
617 {
618   GSettings *settings = G_SETTINGS (object);
619 
620   switch (prop_id)
621     {
622     case PROP_SCHEMA:
623       g_value_set_boxed (value, settings->priv->schema);
624       break;
625 
626      case PROP_SCHEMA_ID:
627       g_value_set_string (value, g_settings_schema_get_id (settings->priv->schema));
628       break;
629 
630      case PROP_BACKEND:
631       g_value_set_object (value, settings->priv->backend);
632       break;
633 
634      case PROP_PATH:
635       g_value_set_string (value, settings->priv->path);
636       break;
637 
638      case PROP_HAS_UNAPPLIED:
639       g_value_set_boolean (value, g_settings_get_has_unapplied (settings));
640       break;
641 
642      case PROP_DELAY_APPLY:
643       g_value_set_boolean (value, G_IS_DELAYED_SETTINGS_BACKEND (settings->priv->backend));
644       break;
645 
646      default:
647       g_assert_not_reached ();
648     }
649 }
650 
651 static const GSettingsListenerVTable listener_vtable = {
652   settings_backend_changed,
653   settings_backend_path_changed,
654   settings_backend_keys_changed,
655   settings_backend_writable_changed,
656   settings_backend_path_writable_changed
657 };
658 
659 static void
g_settings_constructed(GObject * object)660 g_settings_constructed (GObject *object)
661 {
662   GSettings *settings = G_SETTINGS (object);
663   const gchar *schema_path;
664 
665   schema_path = g_settings_schema_get_path (settings->priv->schema);
666 
667   if (settings->priv->path && schema_path && strcmp (settings->priv->path, schema_path) != 0)
668     g_error ("settings object created with schema '%s' and path '%s', but path '%s' is specified by schema",
669              g_settings_schema_get_id (settings->priv->schema), settings->priv->path, schema_path);
670 
671   if (settings->priv->path == NULL)
672     {
673       if (schema_path == NULL)
674         g_error ("attempting to create schema '%s' without a path",
675                  g_settings_schema_get_id (settings->priv->schema));
676 
677       settings->priv->path = g_strdup (schema_path);
678     }
679 
680   if (settings->priv->backend == NULL)
681     settings->priv->backend = g_settings_backend_get_default ();
682 
683   g_settings_backend_watch (settings->priv->backend,
684                             &listener_vtable, G_OBJECT (settings),
685                             settings->priv->main_context);
686   g_settings_backend_subscribe (settings->priv->backend,
687                                 settings->priv->path);
688 }
689 
690 static void
g_settings_finalize(GObject * object)691 g_settings_finalize (GObject *object)
692 {
693   GSettings *settings = G_SETTINGS (object);
694 
695   g_settings_backend_unsubscribe (settings->priv->backend,
696                                   settings->priv->path);
697   g_main_context_unref (settings->priv->main_context);
698   g_object_unref (settings->priv->backend);
699   g_settings_schema_unref (settings->priv->schema);
700   g_free (settings->priv->path);
701 
702   G_OBJECT_CLASS (g_settings_parent_class)->finalize (object);
703 }
704 
705 static void
g_settings_init(GSettings * settings)706 g_settings_init (GSettings *settings)
707 {
708   settings->priv = g_settings_get_instance_private (settings);
709   settings->priv->main_context = g_main_context_ref_thread_default ();
710 }
711 
712 static void
g_settings_class_init(GSettingsClass * class)713 g_settings_class_init (GSettingsClass *class)
714 {
715   GObjectClass *object_class = G_OBJECT_CLASS (class);
716 
717   class->writable_change_event = g_settings_real_writable_change_event;
718   class->change_event = g_settings_real_change_event;
719 
720   object_class->set_property = g_settings_set_property;
721   object_class->get_property = g_settings_get_property;
722   object_class->constructed = g_settings_constructed;
723   object_class->finalize = g_settings_finalize;
724 
725   /**
726    * GSettings::changed:
727    * @settings: the object on which the signal was emitted
728    * @key: the name of the key that changed
729    *
730    * The "changed" signal is emitted when a key has potentially changed.
731    * You should call one of the g_settings_get() calls to check the new
732    * value.
733    *
734    * This signal supports detailed connections.  You can connect to the
735    * detailed signal "changed::x" in order to only receive callbacks
736    * when key "x" changes.
737    *
738    * Note that @settings only emits this signal if you have read @key at
739    * least once while a signal handler was already connected for @key.
740    */
741   g_settings_signals[SIGNAL_CHANGED] =
742     g_signal_new (I_("changed"), G_TYPE_SETTINGS,
743                   G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
744                   G_STRUCT_OFFSET (GSettingsClass, changed),
745                   NULL, NULL, NULL, G_TYPE_NONE,
746                   1, G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE);
747 
748   /**
749    * GSettings::change-event:
750    * @settings: the object on which the signal was emitted
751    * @keys: (array length=n_keys) (element-type GQuark) (nullable):
752    *        an array of #GQuarks for the changed keys, or %NULL
753    * @n_keys: the length of the @keys array, or 0
754    *
755    * The "change-event" signal is emitted once per change event that
756    * affects this settings object.  You should connect to this signal
757    * only if you are interested in viewing groups of changes before they
758    * are split out into multiple emissions of the "changed" signal.
759    * For most use cases it is more appropriate to use the "changed" signal.
760    *
761    * In the event that the change event applies to one or more specified
762    * keys, @keys will be an array of #GQuark of length @n_keys.  In the
763    * event that the change event applies to the #GSettings object as a
764    * whole (ie: potentially every key has been changed) then @keys will
765    * be %NULL and @n_keys will be 0.
766    *
767    * The default handler for this signal invokes the "changed" signal
768    * for each affected key.  If any other connected handler returns
769    * %TRUE then this default functionality will be suppressed.
770    *
771    * Returns: %TRUE to stop other handlers from being invoked for the
772    *          event. FALSE to propagate the event further.
773    */
774   g_settings_signals[SIGNAL_CHANGE_EVENT] =
775     g_signal_new (I_("change-event"), G_TYPE_SETTINGS,
776                   G_SIGNAL_RUN_LAST,
777                   G_STRUCT_OFFSET (GSettingsClass, change_event),
778                   g_signal_accumulator_true_handled, NULL,
779                   _g_cclosure_marshal_BOOLEAN__POINTER_INT,
780                   G_TYPE_BOOLEAN, 2, G_TYPE_POINTER, G_TYPE_INT);
781   g_signal_set_va_marshaller (g_settings_signals[SIGNAL_CHANGE_EVENT],
782                               G_TYPE_FROM_CLASS (class),
783                               _g_cclosure_marshal_BOOLEAN__POINTER_INTv);
784 
785   /**
786    * GSettings::writable-changed:
787    * @settings: the object on which the signal was emitted
788    * @key: the key
789    *
790    * The "writable-changed" signal is emitted when the writability of a
791    * key has potentially changed.  You should call
792    * g_settings_is_writable() in order to determine the new status.
793    *
794    * This signal supports detailed connections.  You can connect to the
795    * detailed signal "writable-changed::x" in order to only receive
796    * callbacks when the writability of "x" changes.
797    */
798   g_settings_signals[SIGNAL_WRITABLE_CHANGED] =
799     g_signal_new (I_("writable-changed"), G_TYPE_SETTINGS,
800                   G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
801                   G_STRUCT_OFFSET (GSettingsClass, writable_changed),
802                   NULL, NULL, NULL, G_TYPE_NONE,
803                   1, G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE);
804 
805   /**
806    * GSettings::writable-change-event:
807    * @settings: the object on which the signal was emitted
808    * @key: the quark of the key, or 0
809    *
810    * The "writable-change-event" signal is emitted once per writability
811    * change event that affects this settings object.  You should connect
812    * to this signal if you are interested in viewing groups of changes
813    * before they are split out into multiple emissions of the
814    * "writable-changed" signal.  For most use cases it is more
815    * appropriate to use the "writable-changed" signal.
816    *
817    * In the event that the writability change applies only to a single
818    * key, @key will be set to the #GQuark for that key.  In the event
819    * that the writability change affects the entire settings object,
820    * @key will be 0.
821    *
822    * The default handler for this signal invokes the "writable-changed"
823    * and "changed" signals for each affected key.  This is done because
824    * changes in writability might also imply changes in value (if for
825    * example, a new mandatory setting is introduced).  If any other
826    * connected handler returns %TRUE then this default functionality
827    * will be suppressed.
828    *
829    * Returns: %TRUE to stop other handlers from being invoked for the
830    *          event. FALSE to propagate the event further.
831    */
832   g_settings_signals[SIGNAL_WRITABLE_CHANGE_EVENT] =
833     g_signal_new (I_("writable-change-event"), G_TYPE_SETTINGS,
834                   G_SIGNAL_RUN_LAST,
835                   G_STRUCT_OFFSET (GSettingsClass, writable_change_event),
836                   g_signal_accumulator_true_handled, NULL,
837                   _g_cclosure_marshal_BOOLEAN__UINT,
838                   G_TYPE_BOOLEAN, 1, G_TYPE_UINT);
839   g_signal_set_va_marshaller (g_settings_signals[SIGNAL_WRITABLE_CHANGE_EVENT],
840                               G_TYPE_FROM_CLASS (class),
841                               _g_cclosure_marshal_BOOLEAN__UINTv);
842 
843   /**
844    * GSettings:backend:
845    *
846    * The name of the context that the settings are stored in.
847    */
848   g_object_class_install_property (object_class, PROP_BACKEND,
849     g_param_spec_object ("backend",
850                          P_("GSettingsBackend"),
851                          P_("The GSettingsBackend for this settings object"),
852                          G_TYPE_SETTINGS_BACKEND, G_PARAM_CONSTRUCT_ONLY |
853                          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
854 
855   /**
856    * GSettings:settings-schema:
857    *
858    * The #GSettingsSchema describing the types of keys for this
859    * #GSettings object.
860    *
861    * Ideally, this property would be called 'schema'.  #GSettingsSchema
862    * has only existed since version 2.32, however, and before then the
863    * 'schema' property was used to refer to the ID of the schema rather
864    * than the schema itself.  Take care.
865    */
866   g_object_class_install_property (object_class, PROP_SCHEMA,
867     g_param_spec_boxed ("settings-schema",
868                         P_("schema"),
869                         P_("The GSettingsSchema for this settings object"),
870                         G_TYPE_SETTINGS_SCHEMA,
871                         G_PARAM_CONSTRUCT_ONLY |
872                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
873 
874   /**
875    * GSettings:schema:
876    *
877    * The name of the schema that describes the types of keys
878    * for this #GSettings object.
879    *
880    * The type of this property is *not* #GSettingsSchema.
881    * #GSettingsSchema has only existed since version 2.32 and
882    * unfortunately this name was used in previous versions to refer to
883    * the schema ID rather than the schema itself.  Take care to use the
884    * 'settings-schema' property if you wish to pass in a
885    * #GSettingsSchema.
886    *
887    * Deprecated:2.32:Use the 'schema-id' property instead.  In a future
888    * version, this property may instead refer to a #GSettingsSchema.
889    */
890   g_object_class_install_property (object_class, PROP_SCHEMA_ID,
891     g_param_spec_string ("schema",
892                          P_("Schema name"),
893                          P_("The name of the schema for this settings object"),
894                          NULL,
895                          G_PARAM_CONSTRUCT_ONLY |
896                          G_PARAM_DEPRECATED | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
897 
898   /**
899    * GSettings:schema-id:
900    *
901    * The name of the schema that describes the types of keys
902    * for this #GSettings object.
903    */
904   g_object_class_install_property (object_class, PROP_SCHEMA_ID,
905     g_param_spec_string ("schema-id",
906                          P_("Schema name"),
907                          P_("The name of the schema for this settings object"),
908                          NULL,
909                          G_PARAM_CONSTRUCT_ONLY |
910                          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
911 
912    /**
913     * GSettings:path:
914     *
915     * The path within the backend where the settings are stored.
916     */
917    g_object_class_install_property (object_class, PROP_PATH,
918      g_param_spec_string ("path",
919                           P_("Base path"),
920                           P_("The path within the backend where the settings are"),
921                           NULL,
922                           G_PARAM_CONSTRUCT_ONLY |
923                           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
924 
925    /**
926     * GSettings:has-unapplied:
927     *
928     * If this property is %TRUE, the #GSettings object has outstanding
929     * changes that will be applied when g_settings_apply() is called.
930     */
931    g_object_class_install_property (object_class, PROP_HAS_UNAPPLIED,
932      g_param_spec_boolean ("has-unapplied",
933                            P_("Has unapplied changes"),
934                            P_("TRUE if there are outstanding changes to apply()"),
935                            FALSE,
936                            G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
937 
938    /**
939     * GSettings:delay-apply:
940     *
941     * Whether the #GSettings object is in 'delay-apply' mode. See
942     * g_settings_delay() for details.
943     *
944     * Since: 2.28
945     */
946    g_object_class_install_property (object_class, PROP_DELAY_APPLY,
947      g_param_spec_boolean ("delay-apply",
948                            P_("Delay-apply mode"),
949                            P_("Whether this settings object is in “delay-apply” mode"),
950                            FALSE,
951                            G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
952 }
953 
954 /* Construction (new, new_with_path, etc.) {{{1 */
955 /**
956  * g_settings_new:
957  * @schema_id: the id of the schema
958  *
959  * Creates a new #GSettings object with the schema specified by
960  * @schema_id.
961  *
962  * It is an error for the schema to not exist: schemas are an
963  * essential part of a program, as they provide type information.
964  * If schemas need to be dynamically loaded (for example, from an
965  * optional runtime dependency), g_settings_schema_source_lookup()
966  * can be used to test for their existence before loading them.
967  *
968  * Signals on the newly created #GSettings object will be dispatched
969  * via the thread-default #GMainContext in effect at the time of the
970  * call to g_settings_new().  The new #GSettings will hold a reference
971  * on the context.  See g_main_context_push_thread_default().
972  *
973  * Returns: a new #GSettings object
974  *
975  * Since: 2.26
976  */
977 GSettings *
g_settings_new(const gchar * schema_id)978 g_settings_new (const gchar *schema_id)
979 {
980   g_return_val_if_fail (schema_id != NULL, NULL);
981 
982   return g_object_new (G_TYPE_SETTINGS,
983                        "schema-id", schema_id,
984                        NULL);
985 }
986 
987 static gboolean
path_is_valid(const gchar * path)988 path_is_valid (const gchar *path)
989 {
990   if (!path)
991     return FALSE;
992 
993   if (path[0] != '/')
994     return FALSE;
995 
996   if (!g_str_has_suffix (path, "/"))
997     return FALSE;
998 
999   return strstr (path, "//") == NULL;
1000 }
1001 
1002 /**
1003  * g_settings_new_with_path:
1004  * @schema_id: the id of the schema
1005  * @path: the path to use
1006  *
1007  * Creates a new #GSettings object with the relocatable schema specified
1008  * by @schema_id and a given path.
1009  *
1010  * You only need to do this if you want to directly create a settings
1011  * object with a schema that doesn't have a specified path of its own.
1012  * That's quite rare.
1013  *
1014  * It is a programmer error to call this function for a schema that
1015  * has an explicitly specified path.
1016  *
1017  * It is a programmer error if @path is not a valid path.  A valid path
1018  * begins and ends with '/' and does not contain two consecutive '/'
1019  * characters.
1020  *
1021  * Returns: a new #GSettings object
1022  *
1023  * Since: 2.26
1024  */
1025 GSettings *
g_settings_new_with_path(const gchar * schema_id,const gchar * path)1026 g_settings_new_with_path (const gchar *schema_id,
1027                           const gchar *path)
1028 {
1029   g_return_val_if_fail (schema_id != NULL, NULL);
1030   g_return_val_if_fail (path_is_valid (path), NULL);
1031 
1032   return g_object_new (G_TYPE_SETTINGS,
1033                        "schema-id", schema_id,
1034                        "path", path,
1035                        NULL);
1036 }
1037 
1038 /**
1039  * g_settings_new_with_backend:
1040  * @schema_id: the id of the schema
1041  * @backend: the #GSettingsBackend to use
1042  *
1043  * Creates a new #GSettings object with the schema specified by
1044  * @schema_id and a given #GSettingsBackend.
1045  *
1046  * Creating a #GSettings object with a different backend allows accessing
1047  * settings from a database other than the usual one. For example, it may make
1048  * sense to pass a backend corresponding to the "defaults" settings database on
1049  * the system to get a settings object that modifies the system default
1050  * settings instead of the settings for this user.
1051  *
1052  * Returns: a new #GSettings object
1053  *
1054  * Since: 2.26
1055  */
1056 GSettings *
g_settings_new_with_backend(const gchar * schema_id,GSettingsBackend * backend)1057 g_settings_new_with_backend (const gchar      *schema_id,
1058                              GSettingsBackend *backend)
1059 {
1060   g_return_val_if_fail (schema_id != NULL, NULL);
1061   g_return_val_if_fail (G_IS_SETTINGS_BACKEND (backend), NULL);
1062 
1063   return g_object_new (G_TYPE_SETTINGS,
1064                        "schema-id", schema_id,
1065                        "backend", backend,
1066                        NULL);
1067 }
1068 
1069 /**
1070  * g_settings_new_with_backend_and_path:
1071  * @schema_id: the id of the schema
1072  * @backend: the #GSettingsBackend to use
1073  * @path: the path to use
1074  *
1075  * Creates a new #GSettings object with the schema specified by
1076  * @schema_id and a given #GSettingsBackend and path.
1077  *
1078  * This is a mix of g_settings_new_with_backend() and
1079  * g_settings_new_with_path().
1080  *
1081  * Returns: a new #GSettings object
1082  *
1083  * Since: 2.26
1084  */
1085 GSettings *
g_settings_new_with_backend_and_path(const gchar * schema_id,GSettingsBackend * backend,const gchar * path)1086 g_settings_new_with_backend_and_path (const gchar      *schema_id,
1087                                       GSettingsBackend *backend,
1088                                       const gchar      *path)
1089 {
1090   g_return_val_if_fail (schema_id != NULL, NULL);
1091   g_return_val_if_fail (G_IS_SETTINGS_BACKEND (backend), NULL);
1092   g_return_val_if_fail (path_is_valid (path), NULL);
1093 
1094   return g_object_new (G_TYPE_SETTINGS,
1095                        "schema-id", schema_id,
1096                        "backend", backend,
1097                        "path", path,
1098                        NULL);
1099 }
1100 
1101 /**
1102  * g_settings_new_full:
1103  * @schema: a #GSettingsSchema
1104  * @backend: (nullable): a #GSettingsBackend
1105  * @path: (nullable): the path to use
1106  *
1107  * Creates a new #GSettings object with a given schema, backend and
1108  * path.
1109  *
1110  * It should be extremely rare that you ever want to use this function.
1111  * It is made available for advanced use-cases (such as plugin systems
1112  * that want to provide access to schemas loaded from custom locations,
1113  * etc).
1114  *
1115  * At the most basic level, a #GSettings object is a pure composition of
1116  * 4 things: a #GSettingsSchema, a #GSettingsBackend, a path within that
1117  * backend, and a #GMainContext to which signals are dispatched.
1118  *
1119  * This constructor therefore gives you full control over constructing
1120  * #GSettings instances.  The first 3 parameters are given directly as
1121  * @schema, @backend and @path, and the main context is taken from the
1122  * thread-default (as per g_settings_new()).
1123  *
1124  * If @backend is %NULL then the default backend is used.
1125  *
1126  * If @path is %NULL then the path from the schema is used.  It is an
1127  * error if @path is %NULL and the schema has no path of its own or if
1128  * @path is non-%NULL and not equal to the path that the schema does
1129  * have.
1130  *
1131  * Returns: a new #GSettings object
1132  *
1133  * Since: 2.32
1134  */
1135 GSettings *
g_settings_new_full(GSettingsSchema * schema,GSettingsBackend * backend,const gchar * path)1136 g_settings_new_full (GSettingsSchema  *schema,
1137                      GSettingsBackend *backend,
1138                      const gchar      *path)
1139 {
1140   g_return_val_if_fail (schema != NULL, NULL);
1141   g_return_val_if_fail (backend == NULL || G_IS_SETTINGS_BACKEND (backend), NULL);
1142   g_return_val_if_fail (path == NULL || path_is_valid (path), NULL);
1143 
1144   return g_object_new (G_TYPE_SETTINGS,
1145                        "settings-schema", schema,
1146                        "backend", backend,
1147                        "path", path,
1148                        NULL);
1149 }
1150 
1151 /* Internal read/write utilities {{{1 */
1152 
1153 /* @value will be sunk */
1154 static gboolean
g_settings_write_to_backend(GSettings * settings,GSettingsSchemaKey * key,GVariant * value)1155 g_settings_write_to_backend (GSettings          *settings,
1156                              GSettingsSchemaKey *key,
1157                              GVariant           *value)
1158 {
1159   gboolean success;
1160   gchar *path;
1161 
1162   path = g_strconcat (settings->priv->path, key->name, NULL);
1163   success = g_settings_backend_write (settings->priv->backend, path, value, NULL);
1164   g_free (path);
1165 
1166   return success;
1167 }
1168 
1169 static GVariant *
g_settings_read_from_backend(GSettings * settings,GSettingsSchemaKey * key,gboolean user_value_only,gboolean default_value)1170 g_settings_read_from_backend (GSettings          *settings,
1171                               GSettingsSchemaKey *key,
1172                               gboolean            user_value_only,
1173                               gboolean            default_value)
1174 {
1175   GVariant *value;
1176   GVariant *fixup;
1177   gchar *path;
1178 
1179   path = g_strconcat (settings->priv->path, key->name, NULL);
1180   if (user_value_only)
1181     value = g_settings_backend_read_user_value (settings->priv->backend, path, key->type);
1182   else
1183     value = g_settings_backend_read (settings->priv->backend, path, key->type, default_value);
1184   g_free (path);
1185 
1186   if (value != NULL)
1187     {
1188       fixup = g_settings_schema_key_range_fixup (key, value);
1189       g_variant_unref (value);
1190     }
1191   else
1192     fixup = NULL;
1193 
1194   return fixup;
1195 }
1196 
1197 /* Public Get/Set API {{{1 (get, get_value, set, set_value, get_mapped) */
1198 /**
1199  * g_settings_get_value:
1200  * @settings: a #GSettings object
1201  * @key: the key to get the value for
1202  *
1203  * Gets the value that is stored in @settings for @key.
1204  *
1205  * It is a programmer error to give a @key that isn't contained in the
1206  * schema for @settings.
1207  *
1208  * Returns: a new #GVariant
1209  *
1210  * Since: 2.26
1211  */
1212 GVariant *
g_settings_get_value(GSettings * settings,const gchar * key)1213 g_settings_get_value (GSettings   *settings,
1214                       const gchar *key)
1215 {
1216   GSettingsSchemaKey skey;
1217   GVariant *value;
1218 
1219   g_return_val_if_fail (G_IS_SETTINGS (settings), NULL);
1220   g_return_val_if_fail (key != NULL, NULL);
1221 
1222   g_settings_schema_key_init (&skey, settings->priv->schema, key);
1223   value = g_settings_read_from_backend (settings, &skey, FALSE, FALSE);
1224 
1225   if (value == NULL)
1226     value = g_settings_schema_key_get_default_value (&skey);
1227 
1228   g_settings_schema_key_clear (&skey);
1229 
1230   return value;
1231 }
1232 
1233 /**
1234  * g_settings_get_user_value:
1235  * @settings: a #GSettings object
1236  * @key: the key to get the user value for
1237  *
1238  * Checks the "user value" of a key, if there is one.
1239  *
1240  * The user value of a key is the last value that was set by the user.
1241  *
1242  * After calling g_settings_reset() this function should always return
1243  * %NULL (assuming something is not wrong with the system
1244  * configuration).
1245  *
1246  * It is possible that g_settings_get_value() will return a different
1247  * value than this function.  This can happen in the case that the user
1248  * set a value for a key that was subsequently locked down by the system
1249  * administrator -- this function will return the user's old value.
1250  *
1251  * This function may be useful for adding a "reset" option to a UI or
1252  * for providing indication that a particular value has been changed.
1253  *
1254  * It is a programmer error to give a @key that isn't contained in the
1255  * schema for @settings.
1256  *
1257  * Returns: (nullable) (transfer full): the user's value, if set
1258  *
1259  * Since: 2.40
1260  **/
1261 GVariant *
g_settings_get_user_value(GSettings * settings,const gchar * key)1262 g_settings_get_user_value (GSettings   *settings,
1263                            const gchar *key)
1264 {
1265   GSettingsSchemaKey skey;
1266   GVariant *value;
1267 
1268   g_return_val_if_fail (G_IS_SETTINGS (settings), NULL);
1269   g_return_val_if_fail (key != NULL, NULL);
1270 
1271   g_settings_schema_key_init (&skey, settings->priv->schema, key);
1272   value = g_settings_read_from_backend (settings, &skey, TRUE, FALSE);
1273   g_settings_schema_key_clear (&skey);
1274 
1275   return value;
1276 }
1277 
1278 /**
1279  * g_settings_get_default_value:
1280  * @settings: a #GSettings object
1281  * @key: the key to get the default value for
1282  *
1283  * Gets the "default value" of a key.
1284  *
1285  * This is the value that would be read if g_settings_reset() were to be
1286  * called on the key.
1287  *
1288  * Note that this may be a different value than returned by
1289  * g_settings_schema_key_get_default_value() if the system administrator
1290  * has provided a default value.
1291  *
1292  * Comparing the return values of g_settings_get_default_value() and
1293  * g_settings_get_value() is not sufficient for determining if a value
1294  * has been set because the user may have explicitly set the value to
1295  * something that happens to be equal to the default.  The difference
1296  * here is that if the default changes in the future, the user's key
1297  * will still be set.
1298  *
1299  * This function may be useful for adding an indication to a UI of what
1300  * the default value was before the user set it.
1301  *
1302  * It is a programmer error to give a @key that isn't contained in the
1303  * schema for @settings.
1304  *
1305  * Returns: (nullable) (transfer full): the default value
1306  *
1307  * Since: 2.40
1308  **/
1309 GVariant *
g_settings_get_default_value(GSettings * settings,const gchar * key)1310 g_settings_get_default_value (GSettings   *settings,
1311                               const gchar *key)
1312 {
1313   GSettingsSchemaKey skey;
1314   GVariant *value;
1315 
1316   g_return_val_if_fail (G_IS_SETTINGS (settings), NULL);
1317   g_return_val_if_fail (key != NULL, NULL);
1318 
1319   g_settings_schema_key_init (&skey, settings->priv->schema, key);
1320   value = g_settings_read_from_backend (settings, &skey, FALSE, TRUE);
1321 
1322   if (value == NULL)
1323     value = g_settings_schema_key_get_default_value (&skey);
1324 
1325   g_settings_schema_key_clear (&skey);
1326 
1327   return value;
1328 }
1329 
1330 /**
1331  * g_settings_get_enum:
1332  * @settings: a #GSettings object
1333  * @key: the key to get the value for
1334  *
1335  * Gets the value that is stored in @settings for @key and converts it
1336  * to the enum value that it represents.
1337  *
1338  * In order to use this function the type of the value must be a string
1339  * and it must be marked in the schema file as an enumerated type.
1340  *
1341  * It is a programmer error to give a @key that isn't contained in the
1342  * schema for @settings or is not marked as an enumerated type.
1343  *
1344  * If the value stored in the configuration database is not a valid
1345  * value for the enumerated type then this function will return the
1346  * default value.
1347  *
1348  * Returns: the enum value
1349  *
1350  * Since: 2.26
1351  **/
1352 gint
g_settings_get_enum(GSettings * settings,const gchar * key)1353 g_settings_get_enum (GSettings   *settings,
1354                      const gchar *key)
1355 {
1356   GSettingsSchemaKey skey;
1357   GVariant *value;
1358   gint result;
1359 
1360   g_return_val_if_fail (G_IS_SETTINGS (settings), -1);
1361   g_return_val_if_fail (key != NULL, -1);
1362 
1363   g_settings_schema_key_init (&skey, settings->priv->schema, key);
1364 
1365   if (!skey.is_enum)
1366     {
1367       g_critical ("g_settings_get_enum() called on key '%s' which is not "
1368                   "associated with an enumerated type", skey.name);
1369       g_settings_schema_key_clear (&skey);
1370       return -1;
1371     }
1372 
1373   value = g_settings_read_from_backend (settings, &skey, FALSE, FALSE);
1374 
1375   if (value == NULL)
1376     value = g_settings_schema_key_get_default_value (&skey);
1377 
1378   result = g_settings_schema_key_to_enum (&skey, value);
1379   g_settings_schema_key_clear (&skey);
1380   g_variant_unref (value);
1381 
1382   return result;
1383 }
1384 
1385 /**
1386  * g_settings_set_enum:
1387  * @settings: a #GSettings object
1388  * @key: a key, within @settings
1389  * @value: an enumerated value
1390  *
1391  * Looks up the enumerated type nick for @value and writes it to @key,
1392  * within @settings.
1393  *
1394  * It is a programmer error to give a @key that isn't contained in the
1395  * schema for @settings or is not marked as an enumerated type, or for
1396  * @value not to be a valid value for the named type.
1397  *
1398  * After performing the write, accessing @key directly with
1399  * g_settings_get_string() will return the 'nick' associated with
1400  * @value.
1401  *
1402  * Returns: %TRUE, if the set succeeds
1403  **/
1404 gboolean
g_settings_set_enum(GSettings * settings,const gchar * key,gint value)1405 g_settings_set_enum (GSettings   *settings,
1406                      const gchar *key,
1407                      gint         value)
1408 {
1409   GSettingsSchemaKey skey;
1410   GVariant *variant;
1411   gboolean success;
1412 
1413   g_return_val_if_fail (G_IS_SETTINGS (settings), FALSE);
1414   g_return_val_if_fail (key != NULL, FALSE);
1415 
1416   g_settings_schema_key_init (&skey, settings->priv->schema, key);
1417 
1418   if (!skey.is_enum)
1419     {
1420       g_critical ("g_settings_set_enum() called on key '%s' which is not "
1421                   "associated with an enumerated type", skey.name);
1422       return FALSE;
1423     }
1424 
1425   if (!(variant = g_settings_schema_key_from_enum (&skey, value)))
1426     {
1427       g_critical ("g_settings_set_enum(): invalid enum value %d for key '%s' "
1428                   "in schema '%s'.  Doing nothing.", value, skey.name,
1429                   g_settings_schema_get_id (skey.schema));
1430       g_settings_schema_key_clear (&skey);
1431       return FALSE;
1432     }
1433 
1434   success = g_settings_write_to_backend (settings, &skey, g_steal_pointer (&variant));
1435   g_settings_schema_key_clear (&skey);
1436 
1437   return success;
1438 }
1439 
1440 /**
1441  * g_settings_get_flags:
1442  * @settings: a #GSettings object
1443  * @key: the key to get the value for
1444  *
1445  * Gets the value that is stored in @settings for @key and converts it
1446  * to the flags value that it represents.
1447  *
1448  * In order to use this function the type of the value must be an array
1449  * of strings and it must be marked in the schema file as a flags type.
1450  *
1451  * It is a programmer error to give a @key that isn't contained in the
1452  * schema for @settings or is not marked as a flags type.
1453  *
1454  * If the value stored in the configuration database is not a valid
1455  * value for the flags type then this function will return the default
1456  * value.
1457  *
1458  * Returns: the flags value
1459  *
1460  * Since: 2.26
1461  **/
1462 guint
g_settings_get_flags(GSettings * settings,const gchar * key)1463 g_settings_get_flags (GSettings   *settings,
1464                       const gchar *key)
1465 {
1466   GSettingsSchemaKey skey;
1467   GVariant *value;
1468   guint result;
1469 
1470   g_return_val_if_fail (G_IS_SETTINGS (settings), -1);
1471   g_return_val_if_fail (key != NULL, -1);
1472 
1473   g_settings_schema_key_init (&skey, settings->priv->schema, key);
1474 
1475   if (!skey.is_flags)
1476     {
1477       g_critical ("g_settings_get_flags() called on key '%s' which is not "
1478                   "associated with a flags type", skey.name);
1479       g_settings_schema_key_clear (&skey);
1480       return -1;
1481     }
1482 
1483   value = g_settings_read_from_backend (settings, &skey, FALSE, FALSE);
1484 
1485   if (value == NULL)
1486     value = g_settings_schema_key_get_default_value (&skey);
1487 
1488   result = g_settings_schema_key_to_flags (&skey, value);
1489   g_settings_schema_key_clear (&skey);
1490   g_variant_unref (value);
1491 
1492   return result;
1493 }
1494 
1495 /**
1496  * g_settings_set_flags:
1497  * @settings: a #GSettings object
1498  * @key: a key, within @settings
1499  * @value: a flags value
1500  *
1501  * Looks up the flags type nicks for the bits specified by @value, puts
1502  * them in an array of strings and writes the array to @key, within
1503  * @settings.
1504  *
1505  * It is a programmer error to give a @key that isn't contained in the
1506  * schema for @settings or is not marked as a flags type, or for @value
1507  * to contain any bits that are not value for the named type.
1508  *
1509  * After performing the write, accessing @key directly with
1510  * g_settings_get_strv() will return an array of 'nicks'; one for each
1511  * bit in @value.
1512  *
1513  * Returns: %TRUE, if the set succeeds
1514  **/
1515 gboolean
g_settings_set_flags(GSettings * settings,const gchar * key,guint value)1516 g_settings_set_flags (GSettings   *settings,
1517                       const gchar *key,
1518                       guint        value)
1519 {
1520   GSettingsSchemaKey skey;
1521   GVariant *variant;
1522   gboolean success;
1523 
1524   g_return_val_if_fail (G_IS_SETTINGS (settings), FALSE);
1525   g_return_val_if_fail (key != NULL, FALSE);
1526 
1527   g_settings_schema_key_init (&skey, settings->priv->schema, key);
1528 
1529   if (!skey.is_flags)
1530     {
1531       g_critical ("g_settings_set_flags() called on key '%s' which is not "
1532                   "associated with a flags type", skey.name);
1533       return FALSE;
1534     }
1535 
1536   if (!(variant = g_settings_schema_key_from_flags (&skey, value)))
1537     {
1538       g_critical ("g_settings_set_flags(): invalid flags value 0x%08x "
1539                   "for key '%s' in schema '%s'.  Doing nothing.",
1540                   value, skey.name, g_settings_schema_get_id (skey.schema));
1541       g_settings_schema_key_clear (&skey);
1542       return FALSE;
1543     }
1544 
1545   success = g_settings_write_to_backend (settings, &skey, g_steal_pointer (&variant));
1546   g_settings_schema_key_clear (&skey);
1547 
1548   return success;
1549 }
1550 
1551 /**
1552  * g_settings_set_value:
1553  * @settings: a #GSettings object
1554  * @key: the name of the key to set
1555  * @value: a #GVariant of the correct type
1556  *
1557  * Sets @key in @settings to @value.
1558  *
1559  * It is a programmer error to give a @key that isn't contained in the
1560  * schema for @settings or for @value to have the incorrect type, per
1561  * the schema.
1562  *
1563  * If @value is floating then this function consumes the reference.
1564  *
1565  * Returns: %TRUE if setting the key succeeded,
1566  *     %FALSE if the key was not writable
1567  *
1568  * Since: 2.26
1569  **/
1570 gboolean
g_settings_set_value(GSettings * settings,const gchar * key,GVariant * value)1571 g_settings_set_value (GSettings   *settings,
1572                       const gchar *key,
1573                       GVariant    *value)
1574 {
1575   GSettingsSchemaKey skey;
1576   gboolean success;
1577 
1578   g_return_val_if_fail (G_IS_SETTINGS (settings), FALSE);
1579   g_return_val_if_fail (key != NULL, FALSE);
1580 
1581   g_variant_ref_sink (value);
1582   g_settings_schema_key_init (&skey, settings->priv->schema, key);
1583 
1584   if (!g_settings_schema_key_type_check (&skey, value))
1585     {
1586       g_critical ("g_settings_set_value: key '%s' in '%s' expects type '%s', but a GVariant of type '%s' was given",
1587                   key,
1588                   g_settings_schema_get_id (settings->priv->schema),
1589                   g_variant_type_peek_string (skey.type),
1590                   g_variant_get_type_string (value));
1591       success = FALSE;
1592     }
1593   else if (!g_settings_schema_key_range_check (&skey, value))
1594     {
1595       g_warning ("g_settings_set_value: value for key '%s' in schema '%s' "
1596                  "is outside of valid range",
1597                  key,
1598                  g_settings_schema_get_id (settings->priv->schema));
1599       success = FALSE;
1600     }
1601   else
1602     {
1603       success = g_settings_write_to_backend (settings, &skey, value);
1604     }
1605 
1606   g_settings_schema_key_clear (&skey);
1607   g_variant_unref (value);
1608 
1609   return success;
1610 }
1611 
1612 /**
1613  * g_settings_get:
1614  * @settings: a #GSettings object
1615  * @key: the key to get the value for
1616  * @format: a #GVariant format string
1617  * @...: arguments as per @format
1618  *
1619  * Gets the value that is stored at @key in @settings.
1620  *
1621  * A convenience function that combines g_settings_get_value() with
1622  * g_variant_get().
1623  *
1624  * It is a programmer error to give a @key that isn't contained in the
1625  * schema for @settings or for the #GVariantType of @format to mismatch
1626  * the type given in the schema.
1627  *
1628  * Since: 2.26
1629  */
1630 void
g_settings_get(GSettings * settings,const gchar * key,const gchar * format,...)1631 g_settings_get (GSettings   *settings,
1632                 const gchar *key,
1633                 const gchar *format,
1634                 ...)
1635 {
1636   GVariant *value;
1637   va_list ap;
1638 
1639   value = g_settings_get_value (settings, key);
1640 
1641   if (strchr (format, '&'))
1642     {
1643       g_critical ("%s: the format string may not contain '&' (key '%s' from schema '%s'). "
1644                   "This call will probably stop working with a future version of glib.",
1645                   G_STRFUNC, key, g_settings_schema_get_id (settings->priv->schema));
1646     }
1647 
1648   va_start (ap, format);
1649   g_variant_get_va (value, format, NULL, &ap);
1650   va_end (ap);
1651 
1652   g_variant_unref (value);
1653 }
1654 
1655 /**
1656  * g_settings_set:
1657  * @settings: a #GSettings object
1658  * @key: the name of the key to set
1659  * @format: a #GVariant format string
1660  * @...: arguments as per @format
1661  *
1662  * Sets @key in @settings to @value.
1663  *
1664  * A convenience function that combines g_settings_set_value() with
1665  * g_variant_new().
1666  *
1667  * It is a programmer error to give a @key that isn't contained in the
1668  * schema for @settings or for the #GVariantType of @format to mismatch
1669  * the type given in the schema.
1670  *
1671  * Returns: %TRUE if setting the key succeeded,
1672  *     %FALSE if the key was not writable
1673  *
1674  * Since: 2.26
1675  */
1676 gboolean
g_settings_set(GSettings * settings,const gchar * key,const gchar * format,...)1677 g_settings_set (GSettings   *settings,
1678                 const gchar *key,
1679                 const gchar *format,
1680                 ...)
1681 {
1682   GVariant *value;
1683   va_list ap;
1684 
1685   va_start (ap, format);
1686   value = g_variant_new_va (format, NULL, &ap);
1687   va_end (ap);
1688 
1689   return g_settings_set_value (settings, key, g_steal_pointer (&value));
1690 }
1691 
1692 /**
1693  * g_settings_get_mapped:
1694  * @settings: a #GSettings object
1695  * @key: the key to get the value for
1696  * @mapping: (scope call): the function to map the value in the
1697  *           settings database to the value used by the application
1698  * @user_data: user data for @mapping
1699  *
1700  * Gets the value that is stored at @key in @settings, subject to
1701  * application-level validation/mapping.
1702  *
1703  * You should use this function when the application needs to perform
1704  * some processing on the value of the key (for example, parsing).  The
1705  * @mapping function performs that processing.  If the function
1706  * indicates that the processing was unsuccessful (due to a parse error,
1707  * for example) then the mapping is tried again with another value.
1708  *
1709  * This allows a robust 'fall back to defaults' behaviour to be
1710  * implemented somewhat automatically.
1711  *
1712  * The first value that is tried is the user's setting for the key.  If
1713  * the mapping function fails to map this value, other values may be
1714  * tried in an unspecified order (system or site defaults, translated
1715  * schema default values, untranslated schema default values, etc).
1716  *
1717  * If the mapping function fails for all possible values, one additional
1718  * attempt is made: the mapping function is called with a %NULL value.
1719  * If the mapping function still indicates failure at this point then
1720  * the application will be aborted.
1721  *
1722  * The result parameter for the @mapping function is pointed to a
1723  * #gpointer which is initially set to %NULL.  The same pointer is given
1724  * to each invocation of @mapping.  The final value of that #gpointer is
1725  * what is returned by this function.  %NULL is valid; it is returned
1726  * just as any other value would be.
1727  *
1728  * Returns: (transfer full): the result, which may be %NULL
1729  **/
1730 gpointer
g_settings_get_mapped(GSettings * settings,const gchar * key,GSettingsGetMapping mapping,gpointer user_data)1731 g_settings_get_mapped (GSettings           *settings,
1732                        const gchar         *key,
1733                        GSettingsGetMapping  mapping,
1734                        gpointer             user_data)
1735 {
1736   gpointer result = NULL;
1737   GSettingsSchemaKey skey;
1738   GVariant *value;
1739   gboolean okay;
1740 
1741   g_return_val_if_fail (G_IS_SETTINGS (settings), NULL);
1742   g_return_val_if_fail (key != NULL, NULL);
1743   g_return_val_if_fail (mapping != NULL, NULL);
1744 
1745   g_settings_schema_key_init (&skey, settings->priv->schema, key);
1746 
1747   if ((value = g_settings_read_from_backend (settings, &skey, FALSE, FALSE)))
1748     {
1749       okay = mapping (value, &result, user_data);
1750       g_variant_unref (value);
1751       if (okay) goto okay;
1752     }
1753 
1754   if ((value = g_settings_schema_key_get_translated_default (&skey)))
1755     {
1756       okay = mapping (value, &result, user_data);
1757       g_variant_unref (value);
1758       if (okay) goto okay;
1759     }
1760 
1761   if ((value = g_settings_schema_key_get_per_desktop_default (&skey)))
1762     {
1763       okay = mapping (value, &result, user_data);
1764       g_variant_unref (value);
1765       if (okay) goto okay;
1766     }
1767 
1768   if (mapping (skey.default_value, &result, user_data))
1769     goto okay;
1770 
1771   if (!mapping (NULL, &result, user_data))
1772     g_error ("The mapping function given to g_settings_get_mapped() for key "
1773              "'%s' in schema '%s' returned FALSE when given a NULL value.",
1774              key, g_settings_schema_get_id (settings->priv->schema));
1775 
1776  okay:
1777   g_settings_schema_key_clear (&skey);
1778 
1779   return result;
1780 }
1781 
1782 /* Convenience API (get, set_string, int, double, boolean, strv) {{{1 */
1783 /**
1784  * g_settings_get_string:
1785  * @settings: a #GSettings object
1786  * @key: the key to get the value for
1787  *
1788  * Gets the value that is stored at @key in @settings.
1789  *
1790  * A convenience variant of g_settings_get() for strings.
1791  *
1792  * It is a programmer error to give a @key that isn't specified as
1793  * having a string type in the schema for @settings.
1794  *
1795  * Returns: a newly-allocated string
1796  *
1797  * Since: 2.26
1798  */
1799 gchar *
g_settings_get_string(GSettings * settings,const gchar * key)1800 g_settings_get_string (GSettings   *settings,
1801                        const gchar *key)
1802 {
1803   GVariant *value;
1804   gchar *result;
1805 
1806   value = g_settings_get_value (settings, key);
1807   result = g_variant_dup_string (value, NULL);
1808   g_variant_unref (value);
1809 
1810   return result;
1811 }
1812 
1813 /**
1814  * g_settings_set_string:
1815  * @settings: a #GSettings object
1816  * @key: the name of the key to set
1817  * @value: the value to set it to
1818  *
1819  * Sets @key in @settings to @value.
1820  *
1821  * A convenience variant of g_settings_set() for strings.
1822  *
1823  * It is a programmer error to give a @key that isn't specified as
1824  * having a string type in the schema for @settings.
1825  *
1826  * Returns: %TRUE if setting the key succeeded,
1827  *     %FALSE if the key was not writable
1828  *
1829  * Since: 2.26
1830  */
1831 gboolean
g_settings_set_string(GSettings * settings,const gchar * key,const gchar * value)1832 g_settings_set_string (GSettings   *settings,
1833                        const gchar *key,
1834                        const gchar *value)
1835 {
1836   return g_settings_set_value (settings, key, g_variant_new_string (value));
1837 }
1838 
1839 /**
1840  * g_settings_get_int:
1841  * @settings: a #GSettings object
1842  * @key: the key to get the value for
1843  *
1844  * Gets the value that is stored at @key in @settings.
1845  *
1846  * A convenience variant of g_settings_get() for 32-bit integers.
1847  *
1848  * It is a programmer error to give a @key that isn't specified as
1849  * having a int32 type in the schema for @settings.
1850  *
1851  * Returns: an integer
1852  *
1853  * Since: 2.26
1854  */
1855 gint
g_settings_get_int(GSettings * settings,const gchar * key)1856 g_settings_get_int (GSettings   *settings,
1857                     const gchar *key)
1858 {
1859   GVariant *value;
1860   gint result;
1861 
1862   value = g_settings_get_value (settings, key);
1863   result = g_variant_get_int32 (value);
1864   g_variant_unref (value);
1865 
1866   return result;
1867 }
1868 
1869 /**
1870  * g_settings_set_int:
1871  * @settings: a #GSettings object
1872  * @key: the name of the key to set
1873  * @value: the value to set it to
1874  *
1875  * Sets @key in @settings to @value.
1876  *
1877  * A convenience variant of g_settings_set() for 32-bit integers.
1878  *
1879  * It is a programmer error to give a @key that isn't specified as
1880  * having a int32 type in the schema for @settings.
1881  *
1882  * Returns: %TRUE if setting the key succeeded,
1883  *     %FALSE if the key was not writable
1884  *
1885  * Since: 2.26
1886  */
1887 gboolean
g_settings_set_int(GSettings * settings,const gchar * key,gint value)1888 g_settings_set_int (GSettings   *settings,
1889                     const gchar *key,
1890                     gint         value)
1891 {
1892   return g_settings_set_value (settings, key, g_variant_new_int32 (value));
1893 }
1894 
1895 /**
1896  * g_settings_get_int64:
1897  * @settings: a #GSettings object
1898  * @key: the key to get the value for
1899  *
1900  * Gets the value that is stored at @key in @settings.
1901  *
1902  * A convenience variant of g_settings_get() for 64-bit integers.
1903  *
1904  * It is a programmer error to give a @key that isn't specified as
1905  * having a int64 type in the schema for @settings.
1906  *
1907  * Returns: a 64-bit integer
1908  *
1909  * Since: 2.50
1910  */
1911 gint64
g_settings_get_int64(GSettings * settings,const gchar * key)1912 g_settings_get_int64 (GSettings   *settings,
1913                       const gchar *key)
1914 {
1915   GVariant *value;
1916   gint64 result;
1917 
1918   value = g_settings_get_value (settings, key);
1919   result = g_variant_get_int64 (value);
1920   g_variant_unref (value);
1921 
1922   return result;
1923 }
1924 
1925 /**
1926  * g_settings_set_int64:
1927  * @settings: a #GSettings object
1928  * @key: the name of the key to set
1929  * @value: the value to set it to
1930  *
1931  * Sets @key in @settings to @value.
1932  *
1933  * A convenience variant of g_settings_set() for 64-bit integers.
1934  *
1935  * It is a programmer error to give a @key that isn't specified as
1936  * having a int64 type in the schema for @settings.
1937  *
1938  * Returns: %TRUE if setting the key succeeded,
1939  *     %FALSE if the key was not writable
1940  *
1941  * Since: 2.50
1942  */
1943 gboolean
g_settings_set_int64(GSettings * settings,const gchar * key,gint64 value)1944 g_settings_set_int64 (GSettings   *settings,
1945                       const gchar *key,
1946                       gint64       value)
1947 {
1948   return g_settings_set_value (settings, key, g_variant_new_int64 (value));
1949 }
1950 
1951 /**
1952  * g_settings_get_uint:
1953  * @settings: a #GSettings object
1954  * @key: the key to get the value for
1955  *
1956  * Gets the value that is stored at @key in @settings.
1957  *
1958  * A convenience variant of g_settings_get() for 32-bit unsigned
1959  * integers.
1960  *
1961  * It is a programmer error to give a @key that isn't specified as
1962  * having a uint32 type in the schema for @settings.
1963  *
1964  * Returns: an unsigned integer
1965  *
1966  * Since: 2.30
1967  */
1968 guint
g_settings_get_uint(GSettings * settings,const gchar * key)1969 g_settings_get_uint (GSettings   *settings,
1970                      const gchar *key)
1971 {
1972   GVariant *value;
1973   guint result;
1974 
1975   value = g_settings_get_value (settings, key);
1976   result = g_variant_get_uint32 (value);
1977   g_variant_unref (value);
1978 
1979   return result;
1980 }
1981 
1982 /**
1983  * g_settings_set_uint:
1984  * @settings: a #GSettings object
1985  * @key: the name of the key to set
1986  * @value: the value to set it to
1987  *
1988  * Sets @key in @settings to @value.
1989  *
1990  * A convenience variant of g_settings_set() for 32-bit unsigned
1991  * integers.
1992  *
1993  * It is a programmer error to give a @key that isn't specified as
1994  * having a uint32 type in the schema for @settings.
1995  *
1996  * Returns: %TRUE if setting the key succeeded,
1997  *     %FALSE if the key was not writable
1998  *
1999  * Since: 2.30
2000  */
2001 gboolean
g_settings_set_uint(GSettings * settings,const gchar * key,guint value)2002 g_settings_set_uint (GSettings   *settings,
2003                      const gchar *key,
2004                      guint        value)
2005 {
2006   return g_settings_set_value (settings, key, g_variant_new_uint32 (value));
2007 }
2008 
2009 /**
2010  * g_settings_get_uint64:
2011  * @settings: a #GSettings object
2012  * @key: the key to get the value for
2013  *
2014  * Gets the value that is stored at @key in @settings.
2015  *
2016  * A convenience variant of g_settings_get() for 64-bit unsigned
2017  * integers.
2018  *
2019  * It is a programmer error to give a @key that isn't specified as
2020  * having a uint64 type in the schema for @settings.
2021  *
2022  * Returns: a 64-bit unsigned integer
2023  *
2024  * Since: 2.50
2025  */
2026 guint64
g_settings_get_uint64(GSettings * settings,const gchar * key)2027 g_settings_get_uint64 (GSettings   *settings,
2028                        const gchar *key)
2029 {
2030   GVariant *value;
2031   guint64 result;
2032 
2033   value = g_settings_get_value (settings, key);
2034   result = g_variant_get_uint64 (value);
2035   g_variant_unref (value);
2036 
2037   return result;
2038 }
2039 
2040 /**
2041  * g_settings_set_uint64:
2042  * @settings: a #GSettings object
2043  * @key: the name of the key to set
2044  * @value: the value to set it to
2045  *
2046  * Sets @key in @settings to @value.
2047  *
2048  * A convenience variant of g_settings_set() for 64-bit unsigned
2049  * integers.
2050  *
2051  * It is a programmer error to give a @key that isn't specified as
2052  * having a uint64 type in the schema for @settings.
2053  *
2054  * Returns: %TRUE if setting the key succeeded,
2055  *     %FALSE if the key was not writable
2056  *
2057  * Since: 2.50
2058  */
2059 gboolean
g_settings_set_uint64(GSettings * settings,const gchar * key,guint64 value)2060 g_settings_set_uint64 (GSettings   *settings,
2061                        const gchar *key,
2062                        guint64      value)
2063 {
2064   return g_settings_set_value (settings, key, g_variant_new_uint64 (value));
2065 }
2066 
2067 /**
2068  * g_settings_get_double:
2069  * @settings: a #GSettings object
2070  * @key: the key to get the value for
2071  *
2072  * Gets the value that is stored at @key in @settings.
2073  *
2074  * A convenience variant of g_settings_get() for doubles.
2075  *
2076  * It is a programmer error to give a @key that isn't specified as
2077  * having a 'double' type in the schema for @settings.
2078  *
2079  * Returns: a double
2080  *
2081  * Since: 2.26
2082  */
2083 gdouble
g_settings_get_double(GSettings * settings,const gchar * key)2084 g_settings_get_double (GSettings   *settings,
2085                        const gchar *key)
2086 {
2087   GVariant *value;
2088   gdouble result;
2089 
2090   value = g_settings_get_value (settings, key);
2091   result = g_variant_get_double (value);
2092   g_variant_unref (value);
2093 
2094   return result;
2095 }
2096 
2097 /**
2098  * g_settings_set_double:
2099  * @settings: a #GSettings object
2100  * @key: the name of the key to set
2101  * @value: the value to set it to
2102  *
2103  * Sets @key in @settings to @value.
2104  *
2105  * A convenience variant of g_settings_set() for doubles.
2106  *
2107  * It is a programmer error to give a @key that isn't specified as
2108  * having a 'double' type in the schema for @settings.
2109  *
2110  * Returns: %TRUE if setting the key succeeded,
2111  *     %FALSE if the key was not writable
2112  *
2113  * Since: 2.26
2114  */
2115 gboolean
g_settings_set_double(GSettings * settings,const gchar * key,gdouble value)2116 g_settings_set_double (GSettings   *settings,
2117                        const gchar *key,
2118                        gdouble      value)
2119 {
2120   return g_settings_set_value (settings, key, g_variant_new_double (value));
2121 }
2122 
2123 /**
2124  * g_settings_get_boolean:
2125  * @settings: a #GSettings object
2126  * @key: the key to get the value for
2127  *
2128  * Gets the value that is stored at @key in @settings.
2129  *
2130  * A convenience variant of g_settings_get() for booleans.
2131  *
2132  * It is a programmer error to give a @key that isn't specified as
2133  * having a boolean type in the schema for @settings.
2134  *
2135  * Returns: a boolean
2136  *
2137  * Since: 2.26
2138  */
2139 gboolean
g_settings_get_boolean(GSettings * settings,const gchar * key)2140 g_settings_get_boolean (GSettings  *settings,
2141                        const gchar *key)
2142 {
2143   GVariant *value;
2144   gboolean result;
2145 
2146   value = g_settings_get_value (settings, key);
2147   result = g_variant_get_boolean (value);
2148   g_variant_unref (value);
2149 
2150   return result;
2151 }
2152 
2153 /**
2154  * g_settings_set_boolean:
2155  * @settings: a #GSettings object
2156  * @key: the name of the key to set
2157  * @value: the value to set it to
2158  *
2159  * Sets @key in @settings to @value.
2160  *
2161  * A convenience variant of g_settings_set() for booleans.
2162  *
2163  * It is a programmer error to give a @key that isn't specified as
2164  * having a boolean type in the schema for @settings.
2165  *
2166  * Returns: %TRUE if setting the key succeeded,
2167  *     %FALSE if the key was not writable
2168  *
2169  * Since: 2.26
2170  */
2171 gboolean
g_settings_set_boolean(GSettings * settings,const gchar * key,gboolean value)2172 g_settings_set_boolean (GSettings  *settings,
2173                        const gchar *key,
2174                        gboolean     value)
2175 {
2176   return g_settings_set_value (settings, key, g_variant_new_boolean (value));
2177 }
2178 
2179 /**
2180  * g_settings_get_strv:
2181  * @settings: a #GSettings object
2182  * @key: the key to get the value for
2183  *
2184  * A convenience variant of g_settings_get() for string arrays.
2185  *
2186  * It is a programmer error to give a @key that isn't specified as
2187  * having an array of strings type in the schema for @settings.
2188  *
2189  * Returns: (array zero-terminated=1) (transfer full): a
2190  * newly-allocated, %NULL-terminated array of strings, the value that
2191  * is stored at @key in @settings.
2192  *
2193  * Since: 2.26
2194  */
2195 gchar **
g_settings_get_strv(GSettings * settings,const gchar * key)2196 g_settings_get_strv (GSettings   *settings,
2197                      const gchar *key)
2198 {
2199   GVariant *value;
2200   gchar **result;
2201 
2202   value = g_settings_get_value (settings, key);
2203   result = g_variant_dup_strv (value, NULL);
2204   g_variant_unref (value);
2205 
2206   return result;
2207 }
2208 
2209 /**
2210  * g_settings_set_strv:
2211  * @settings: a #GSettings object
2212  * @key: the name of the key to set
2213  * @value: (nullable) (array zero-terminated=1): the value to set it to, or %NULL
2214  *
2215  * Sets @key in @settings to @value.
2216  *
2217  * A convenience variant of g_settings_set() for string arrays.  If
2218  * @value is %NULL, then @key is set to be the empty array.
2219  *
2220  * It is a programmer error to give a @key that isn't specified as
2221  * having an array of strings type in the schema for @settings.
2222  *
2223  * Returns: %TRUE if setting the key succeeded,
2224  *     %FALSE if the key was not writable
2225  *
2226  * Since: 2.26
2227  */
2228 gboolean
g_settings_set_strv(GSettings * settings,const gchar * key,const gchar * const * value)2229 g_settings_set_strv (GSettings           *settings,
2230                      const gchar         *key,
2231                      const gchar * const *value)
2232 {
2233   GVariant *array;
2234 
2235   if (value != NULL)
2236     array = g_variant_new_strv (value, -1);
2237   else
2238     array = g_variant_new_strv (NULL, 0);
2239 
2240   return g_settings_set_value (settings, key, array);
2241 }
2242 
2243 /* Delayed apply (delay, apply, revert, get_has_unapplied) {{{1 */
2244 /**
2245  * g_settings_delay:
2246  * @settings: a #GSettings object
2247  *
2248  * Changes the #GSettings object into 'delay-apply' mode. In this
2249  * mode, changes to @settings are not immediately propagated to the
2250  * backend, but kept locally until g_settings_apply() is called.
2251  *
2252  * Since: 2.26
2253  */
2254 void
g_settings_delay(GSettings * settings)2255 g_settings_delay (GSettings *settings)
2256 {
2257   GDelayedSettingsBackend *delayed = NULL;
2258 
2259   g_return_if_fail (G_IS_SETTINGS (settings));
2260 
2261   if (G_IS_DELAYED_SETTINGS_BACKEND (settings->priv->backend))
2262     return;
2263 
2264   delayed = g_delayed_settings_backend_new (settings->priv->backend,
2265                                             settings,
2266                                             settings->priv->main_context);
2267   g_settings_backend_unwatch (settings->priv->backend, G_OBJECT (settings));
2268   g_object_unref (settings->priv->backend);
2269 
2270   settings->priv->backend = G_SETTINGS_BACKEND (delayed);
2271   g_settings_backend_watch (settings->priv->backend,
2272                             &listener_vtable, G_OBJECT (settings),
2273                             settings->priv->main_context);
2274 
2275   g_object_notify (G_OBJECT (settings), "delay-apply");
2276 }
2277 
2278 /**
2279  * g_settings_apply:
2280  * @settings: a #GSettings instance
2281  *
2282  * Applies any changes that have been made to the settings.  This
2283  * function does nothing unless @settings is in 'delay-apply' mode;
2284  * see g_settings_delay().  In the normal case settings are always
2285  * applied immediately.
2286  **/
2287 void
g_settings_apply(GSettings * settings)2288 g_settings_apply (GSettings *settings)
2289 {
2290   if (G_IS_DELAYED_SETTINGS_BACKEND (settings->priv->backend))
2291     {
2292       GDelayedSettingsBackend *delayed;
2293 
2294       delayed = G_DELAYED_SETTINGS_BACKEND (settings->priv->backend);
2295       g_delayed_settings_backend_apply (delayed);
2296     }
2297 }
2298 
2299 /**
2300  * g_settings_revert:
2301  * @settings: a #GSettings instance
2302  *
2303  * Reverts all non-applied changes to the settings.  This function
2304  * does nothing unless @settings is in 'delay-apply' mode; see
2305  * g_settings_delay().  In the normal case settings are always applied
2306  * immediately.
2307  *
2308  * Change notifications will be emitted for affected keys.
2309  **/
2310 void
g_settings_revert(GSettings * settings)2311 g_settings_revert (GSettings *settings)
2312 {
2313   if (G_IS_DELAYED_SETTINGS_BACKEND (settings->priv->backend))
2314     {
2315       GDelayedSettingsBackend *delayed;
2316 
2317       delayed = G_DELAYED_SETTINGS_BACKEND (settings->priv->backend);
2318       g_delayed_settings_backend_revert (delayed);
2319     }
2320 }
2321 
2322 /**
2323  * g_settings_get_has_unapplied:
2324  * @settings: a #GSettings object
2325  *
2326  * Returns whether the #GSettings object has any unapplied
2327  * changes.  This can only be the case if it is in 'delayed-apply' mode.
2328  *
2329  * Returns: %TRUE if @settings has unapplied changes
2330  *
2331  * Since: 2.26
2332  */
2333 gboolean
g_settings_get_has_unapplied(GSettings * settings)2334 g_settings_get_has_unapplied (GSettings *settings)
2335 {
2336   g_return_val_if_fail (G_IS_SETTINGS (settings), FALSE);
2337 
2338   return G_IS_DELAYED_SETTINGS_BACKEND (settings->priv->backend) &&
2339          g_delayed_settings_backend_get_has_unapplied (
2340            G_DELAYED_SETTINGS_BACKEND (settings->priv->backend));
2341 }
2342 
2343 /* Extra API (reset, sync, get_child, is_writable, list_*, ranges) {{{1 */
2344 /**
2345  * g_settings_reset:
2346  * @settings: a #GSettings object
2347  * @key: the name of a key
2348  *
2349  * Resets @key to its default value.
2350  *
2351  * This call resets the key, as much as possible, to its default value.
2352  * That might be the value specified in the schema or the one set by the
2353  * administrator.
2354  **/
2355 void
g_settings_reset(GSettings * settings,const gchar * key)2356 g_settings_reset (GSettings *settings,
2357                   const gchar *key)
2358 {
2359   gchar *path;
2360 
2361   g_return_if_fail (G_IS_SETTINGS (settings));
2362   g_return_if_fail (key != NULL);
2363 
2364   path = g_strconcat (settings->priv->path, key, NULL);
2365   g_settings_backend_reset (settings->priv->backend, path, NULL);
2366   g_free (path);
2367 }
2368 
2369 /**
2370  * g_settings_sync:
2371  *
2372  * Ensures that all pending operations are complete for the default backend.
2373  *
2374  * Writes made to a #GSettings are handled asynchronously.  For this
2375  * reason, it is very unlikely that the changes have it to disk by the
2376  * time g_settings_set() returns.
2377  *
2378  * This call will block until all of the writes have made it to the
2379  * backend.  Since the mainloop is not running, no change notifications
2380  * will be dispatched during this call (but some may be queued by the
2381  * time the call is done).
2382  **/
2383 void
g_settings_sync(void)2384 g_settings_sync (void)
2385 {
2386   g_settings_backend_sync_default ();
2387 }
2388 
2389 /**
2390  * g_settings_is_writable:
2391  * @settings: a #GSettings object
2392  * @name: the name of a key
2393  *
2394  * Finds out if a key can be written or not
2395  *
2396  * Returns: %TRUE if the key @name is writable
2397  *
2398  * Since: 2.26
2399  */
2400 gboolean
g_settings_is_writable(GSettings * settings,const gchar * name)2401 g_settings_is_writable (GSettings   *settings,
2402                         const gchar *name)
2403 {
2404   gboolean writable;
2405   gchar *path;
2406 
2407   g_return_val_if_fail (G_IS_SETTINGS (settings), FALSE);
2408 
2409   path = g_strconcat (settings->priv->path, name, NULL);
2410   writable = g_settings_backend_get_writable (settings->priv->backend, path);
2411   g_free (path);
2412 
2413   return writable;
2414 }
2415 
2416 /**
2417  * g_settings_get_child:
2418  * @settings: a #GSettings object
2419  * @name: the name of the child schema
2420  *
2421  * Creates a child settings object which has a base path of
2422  * `base-path/@name`, where `base-path` is the base path of
2423  * @settings.
2424  *
2425  * The schema for the child settings object must have been declared
2426  * in the schema of @settings using a `<child>` element.
2427  *
2428  * The created child settings object will inherit the #GSettings:delay-apply
2429  * mode from @settings.
2430  *
2431  * Returns: (not nullable) (transfer full): a 'child' settings object
2432  *
2433  * Since: 2.26
2434  */
2435 GSettings *
g_settings_get_child(GSettings * settings,const gchar * name)2436 g_settings_get_child (GSettings   *settings,
2437                       const gchar *name)
2438 {
2439   GSettingsSchema *child_schema;
2440   gchar *child_path;
2441   GSettings *child;
2442 
2443   g_return_val_if_fail (G_IS_SETTINGS (settings), NULL);
2444 
2445   child_schema = g_settings_schema_get_child_schema (settings->priv->schema,
2446                                                      name);
2447   if (child_schema == NULL)
2448     g_error ("Schema '%s' has no child '%s' or child schema not found",
2449              g_settings_schema_get_id (settings->priv->schema), name);
2450 
2451   child_path = g_strconcat (settings->priv->path, name, "/", NULL);
2452   child = g_settings_new_full (child_schema,
2453                                settings->priv->backend,
2454                                child_path);
2455   g_settings_schema_unref (child_schema);
2456   g_free (child_path);
2457 
2458   return child;
2459 }
2460 
2461 /**
2462  * g_settings_list_keys:
2463  * @settings: a #GSettings object
2464  *
2465  * Introspects the list of keys on @settings.
2466  *
2467  * You should probably not be calling this function from "normal" code
2468  * (since you should already know what keys are in your schema).  This
2469  * function is intended for introspection reasons.
2470  *
2471  * You should free the return value with g_strfreev() when you are done
2472  * with it.
2473  *
2474  * Returns: (transfer full) (element-type utf8): a list of the keys on
2475  *    @settings, in no defined order
2476  * Deprecated: 2.46: Use g_settings_schema_list_keys() instead.
2477  */
2478 gchar **
g_settings_list_keys(GSettings * settings)2479 g_settings_list_keys (GSettings *settings)
2480 {
2481   return g_settings_schema_list_keys (settings->priv->schema);
2482 }
2483 
2484 /**
2485  * g_settings_list_children:
2486  * @settings: a #GSettings object
2487  *
2488  * Gets the list of children on @settings.
2489  *
2490  * The list is exactly the list of strings for which it is not an error
2491  * to call g_settings_get_child().
2492  *
2493  * There is little reason to call this function from "normal" code, since
2494  * you should already know what children are in your schema. This function
2495  * may still be useful there for introspection reasons, however.
2496  *
2497  * You should free the return value with g_strfreev() when you are done
2498  * with it.
2499  *
2500  * Returns: (transfer full) (element-type utf8): a list of the children on
2501  *    @settings, in no defined order
2502  */
2503 gchar **
g_settings_list_children(GSettings * settings)2504 g_settings_list_children (GSettings *settings)
2505 {
2506   return g_settings_schema_list_children (settings->priv->schema);
2507 }
2508 
2509 /**
2510  * g_settings_get_range:
2511  * @settings: a #GSettings
2512  * @key: the key to query the range of
2513  *
2514  * Queries the range of a key.
2515  *
2516  * Since: 2.28
2517  *
2518  * Deprecated:2.40:Use g_settings_schema_key_get_range() instead.
2519  **/
2520 GVariant *
g_settings_get_range(GSettings * settings,const gchar * key)2521 g_settings_get_range (GSettings   *settings,
2522                       const gchar *key)
2523 {
2524   GSettingsSchemaKey skey;
2525   GVariant *range;
2526 
2527   g_settings_schema_key_init (&skey, settings->priv->schema, key);
2528   range = g_settings_schema_key_get_range (&skey);
2529   g_settings_schema_key_clear (&skey);
2530 
2531   return range;
2532 }
2533 
2534 /**
2535  * g_settings_range_check:
2536  * @settings: a #GSettings
2537  * @key: the key to check
2538  * @value: the value to check
2539  *
2540  * Checks if the given @value is of the correct type and within the
2541  * permitted range for @key.
2542  *
2543  * Returns: %TRUE if @value is valid for @key
2544  *
2545  * Since: 2.28
2546  *
2547  * Deprecated:2.40:Use g_settings_schema_key_range_check() instead.
2548  **/
2549 gboolean
g_settings_range_check(GSettings * settings,const gchar * key,GVariant * value)2550 g_settings_range_check (GSettings   *settings,
2551                         const gchar *key,
2552                         GVariant    *value)
2553 {
2554   GSettingsSchemaKey skey;
2555   gboolean good;
2556 
2557   g_settings_schema_key_init (&skey, settings->priv->schema, key);
2558   good = g_settings_schema_key_range_check (&skey, value);
2559   g_settings_schema_key_clear (&skey);
2560 
2561   return good;
2562 }
2563 
2564 /* Binding {{{1 */
2565 typedef struct
2566 {
2567   GSettingsSchemaKey key;
2568   GSettings *settings;
2569   GObject *object;
2570 
2571   GSettingsBindGetMapping get_mapping;
2572   GSettingsBindSetMapping set_mapping;
2573   gpointer user_data;
2574   GDestroyNotify destroy;
2575 
2576   guint writable_handler_id;
2577   guint property_handler_id;
2578   const GParamSpec *property;
2579   guint key_handler_id;
2580 
2581   /* prevent recursion */
2582   gboolean running;
2583 } GSettingsBinding;
2584 
2585 static void
g_settings_binding_free(gpointer data)2586 g_settings_binding_free (gpointer data)
2587 {
2588   GSettingsBinding *binding = data;
2589 
2590   g_assert (!binding->running);
2591 
2592   if (binding->writable_handler_id)
2593     g_signal_handler_disconnect (binding->settings,
2594                                  binding->writable_handler_id);
2595 
2596   if (binding->key_handler_id)
2597     g_signal_handler_disconnect (binding->settings,
2598                                  binding->key_handler_id);
2599 
2600   if (g_signal_handler_is_connected (binding->object,
2601                                      binding->property_handler_id))
2602   g_signal_handler_disconnect (binding->object,
2603                                binding->property_handler_id);
2604 
2605   g_settings_schema_key_clear (&binding->key);
2606 
2607   if (binding->destroy)
2608     binding->destroy (binding->user_data);
2609 
2610   g_object_unref (binding->settings);
2611 
2612   g_slice_free (GSettingsBinding, binding);
2613 }
2614 
2615 static GQuark
g_settings_binding_quark(const char * property)2616 g_settings_binding_quark (const char *property)
2617 {
2618   GQuark quark;
2619   gchar *tmp;
2620 
2621   tmp = g_strdup_printf ("gsettingsbinding-%s", property);
2622   quark = g_quark_from_string (tmp);
2623   g_free (tmp);
2624 
2625   return quark;
2626 }
2627 
2628 static void
g_settings_binding_key_changed(GSettings * settings,const gchar * key,gpointer user_data)2629 g_settings_binding_key_changed (GSettings   *settings,
2630                                 const gchar *key,
2631                                 gpointer     user_data)
2632 {
2633   GSettingsBinding *binding = user_data;
2634   GValue value = G_VALUE_INIT;
2635   GVariant *variant;
2636 
2637   g_assert (settings == binding->settings);
2638   g_assert (key == binding->key.name);
2639 
2640   if (binding->running)
2641     return;
2642 
2643   binding->running = TRUE;
2644 
2645   g_value_init (&value, binding->property->value_type);
2646 
2647   variant = g_settings_read_from_backend (binding->settings, &binding->key, FALSE, FALSE);
2648   if (variant && !binding->get_mapping (&value, variant, binding->user_data))
2649     {
2650       /* silently ignore errors in the user's config database */
2651       g_variant_unref (variant);
2652       variant = NULL;
2653     }
2654 
2655   if (variant == NULL)
2656     {
2657       variant = g_settings_schema_key_get_translated_default (&binding->key);
2658       if (variant &&
2659           !binding->get_mapping (&value, variant, binding->user_data))
2660         {
2661           /* flag translation errors with a warning */
2662           g_warning ("Translated default '%s' for key '%s' in schema '%s' "
2663                      "was rejected by the binding mapping function",
2664                      binding->key.unparsed, binding->key.name,
2665                      g_settings_schema_get_id (binding->key.schema));
2666           g_variant_unref (variant);
2667           variant = NULL;
2668         }
2669     }
2670 
2671   if (variant == NULL)
2672     {
2673       variant = g_settings_schema_key_get_per_desktop_default (&binding->key);
2674       if (variant &&
2675           !binding->get_mapping (&value, variant, binding->user_data))
2676         {
2677           g_error ("Per-desktop default value for key '%s' in schema '%s' "
2678                    "was rejected by the binding mapping function.",
2679                    binding->key.name, g_settings_schema_get_id (binding->key.schema));
2680           g_variant_unref (variant);
2681           variant = NULL;
2682         }
2683     }
2684 
2685   if (variant == NULL)
2686     {
2687       variant = g_variant_ref (binding->key.default_value);
2688       if (!binding->get_mapping (&value, variant, binding->user_data))
2689         g_error ("The schema default value for key '%s' in schema '%s' "
2690                  "was rejected by the binding mapping function.",
2691                  binding->key.name, g_settings_schema_get_id (binding->key.schema));
2692     }
2693 
2694   g_object_set_property (binding->object, binding->property->name, &value);
2695   g_variant_unref (variant);
2696   g_value_unset (&value);
2697 
2698   binding->running = FALSE;
2699 }
2700 
2701 static void
g_settings_binding_property_changed(GObject * object,const GParamSpec * pspec,gpointer user_data)2702 g_settings_binding_property_changed (GObject          *object,
2703                                      const GParamSpec *pspec,
2704                                      gpointer          user_data)
2705 {
2706   GSettingsBinding *binding = user_data;
2707   GValue value = G_VALUE_INIT;
2708   GVariant *variant;
2709   gboolean valid = TRUE;
2710 
2711   g_assert (object == binding->object);
2712   g_assert (pspec == binding->property);
2713 
2714   if (binding->running)
2715     return;
2716 
2717   binding->running = TRUE;
2718 
2719   g_value_init (&value, pspec->value_type);
2720   g_object_get_property (object, pspec->name, &value);
2721   if ((variant = binding->set_mapping (&value, binding->key.type,
2722                                        binding->user_data)))
2723     {
2724       g_variant_take_ref (variant);
2725 
2726       if (!g_settings_schema_key_type_check (&binding->key, variant))
2727         {
2728           gchar *type_str;
2729           type_str = g_variant_type_dup_string (binding->key.type);
2730           g_critical ("binding mapping function for key '%s' returned "
2731                       "GVariant of type '%s' when type '%s' was requested",
2732                       binding->key.name, g_variant_get_type_string (variant),
2733                       type_str);
2734           g_free (type_str);
2735           valid = FALSE;
2736         }
2737 
2738       if (valid && !g_settings_schema_key_range_check (&binding->key, variant))
2739         {
2740           gchar *variant_str;
2741           variant_str = g_variant_print (variant, TRUE);
2742           g_critical ("GObject property '%s' on a '%s' object is out of "
2743                       "schema-specified range for key '%s' of '%s': %s",
2744                       binding->property->name, g_type_name (binding->property->owner_type),
2745                       binding->key.name, g_settings_schema_get_id (binding->key.schema),
2746                       variant_str);
2747           g_free (variant_str);
2748           valid = FALSE;
2749         }
2750 
2751       if (valid)
2752         {
2753           g_settings_write_to_backend (binding->settings, &binding->key, variant);
2754         }
2755       g_variant_unref (variant);
2756     }
2757   g_value_unset (&value);
2758 
2759   binding->running = FALSE;
2760 }
2761 
2762 static gboolean
g_settings_bind_invert_boolean_get_mapping(GValue * value,GVariant * variant,gpointer user_data)2763 g_settings_bind_invert_boolean_get_mapping (GValue   *value,
2764                                             GVariant *variant,
2765                                             gpointer  user_data)
2766 {
2767   g_value_set_boolean (value, !g_variant_get_boolean (variant));
2768   return TRUE;
2769 }
2770 
2771 static GVariant *
g_settings_bind_invert_boolean_set_mapping(const GValue * value,const GVariantType * expected_type,gpointer user_data)2772 g_settings_bind_invert_boolean_set_mapping (const GValue       *value,
2773                                             const GVariantType *expected_type,
2774                                             gpointer            user_data)
2775 {
2776   return g_variant_new_boolean (!g_value_get_boolean (value));
2777 }
2778 
2779 /**
2780  * g_settings_bind:
2781  * @settings: a #GSettings object
2782  * @key: the key to bind
2783  * @object: (type GObject.Object): a #GObject
2784  * @property: the name of the property to bind
2785  * @flags: flags for the binding
2786  *
2787  * Create a binding between the @key in the @settings object
2788  * and the property @property of @object.
2789  *
2790  * The binding uses the default GIO mapping functions to map
2791  * between the settings and property values. These functions
2792  * handle booleans, numeric types and string types in a
2793  * straightforward way. Use g_settings_bind_with_mapping() if
2794  * you need a custom mapping, or map between types that are not
2795  * supported by the default mapping functions.
2796  *
2797  * Unless the @flags include %G_SETTINGS_BIND_NO_SENSITIVITY, this
2798  * function also establishes a binding between the writability of
2799  * @key and the "sensitive" property of @object (if @object has
2800  * a boolean property by that name). See g_settings_bind_writable()
2801  * for more details about writable bindings.
2802  *
2803  * Note that the lifecycle of the binding is tied to @object,
2804  * and that you can have only one binding per object property.
2805  * If you bind the same property twice on the same object, the second
2806  * binding overrides the first one.
2807  *
2808  * Since: 2.26
2809  */
2810 void
g_settings_bind(GSettings * settings,const gchar * key,gpointer object,const gchar * property,GSettingsBindFlags flags)2811 g_settings_bind (GSettings          *settings,
2812                  const gchar        *key,
2813                  gpointer            object,
2814                  const gchar        *property,
2815                  GSettingsBindFlags  flags)
2816 {
2817   GSettingsBindGetMapping get_mapping = NULL;
2818   GSettingsBindSetMapping set_mapping = NULL;
2819 
2820   if (flags & G_SETTINGS_BIND_INVERT_BOOLEAN)
2821     {
2822       get_mapping = g_settings_bind_invert_boolean_get_mapping;
2823       set_mapping = g_settings_bind_invert_boolean_set_mapping;
2824 
2825       /* can't pass this flag to g_settings_bind_with_mapping() */
2826       flags &= ~G_SETTINGS_BIND_INVERT_BOOLEAN;
2827     }
2828 
2829   g_settings_bind_with_mapping (settings, key, object, property, flags,
2830                                 get_mapping, set_mapping, NULL, NULL);
2831 }
2832 
2833 /**
2834  * g_settings_bind_with_mapping: (skip)
2835  * @settings: a #GSettings object
2836  * @key: the key to bind
2837  * @object: (type GObject.Object): a #GObject
2838  * @property: the name of the property to bind
2839  * @flags: flags for the binding
2840  * @get_mapping: a function that gets called to convert values
2841  *     from @settings to @object, or %NULL to use the default GIO mapping
2842  * @set_mapping: a function that gets called to convert values
2843  *     from @object to @settings, or %NULL to use the default GIO mapping
2844  * @user_data: data that gets passed to @get_mapping and @set_mapping
2845  * @destroy: #GDestroyNotify function for @user_data
2846  *
2847  * Create a binding between the @key in the @settings object
2848  * and the property @property of @object.
2849  *
2850  * The binding uses the provided mapping functions to map between
2851  * settings and property values.
2852  *
2853  * Note that the lifecycle of the binding is tied to @object,
2854  * and that you can have only one binding per object property.
2855  * If you bind the same property twice on the same object, the second
2856  * binding overrides the first one.
2857  *
2858  * Since: 2.26
2859  */
2860 void
g_settings_bind_with_mapping(GSettings * settings,const gchar * key,gpointer object,const gchar * property,GSettingsBindFlags flags,GSettingsBindGetMapping get_mapping,GSettingsBindSetMapping set_mapping,gpointer user_data,GDestroyNotify destroy)2861 g_settings_bind_with_mapping (GSettings               *settings,
2862                               const gchar             *key,
2863                               gpointer                 object,
2864                               const gchar             *property,
2865                               GSettingsBindFlags       flags,
2866                               GSettingsBindGetMapping  get_mapping,
2867                               GSettingsBindSetMapping  set_mapping,
2868                               gpointer                 user_data,
2869                               GDestroyNotify           destroy)
2870 {
2871   GSettingsBinding *binding;
2872   GObjectClass *objectclass;
2873   gchar *detailed_signal;
2874   GQuark binding_quark;
2875 
2876   g_return_if_fail (G_IS_SETTINGS (settings));
2877   g_return_if_fail (key != NULL);
2878   g_return_if_fail (G_IS_OBJECT (object));
2879   g_return_if_fail (property != NULL);
2880   g_return_if_fail (~flags & G_SETTINGS_BIND_INVERT_BOOLEAN);
2881 
2882   objectclass = G_OBJECT_GET_CLASS (object);
2883 
2884   binding = g_slice_new0 (GSettingsBinding);
2885   g_settings_schema_key_init (&binding->key, settings->priv->schema, key);
2886   binding->settings = g_object_ref (settings);
2887   binding->object = object;
2888   binding->property = g_object_class_find_property (objectclass, property);
2889   binding->user_data = user_data;
2890   binding->destroy = destroy;
2891   binding->get_mapping = get_mapping ? get_mapping : g_settings_get_mapping;
2892   binding->set_mapping = set_mapping ? set_mapping : g_settings_set_mapping;
2893 
2894   if (!(flags & (G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET)))
2895     flags |= G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET;
2896 
2897   if (binding->property == NULL)
2898     {
2899       g_critical ("g_settings_bind: no property '%s' on class '%s'",
2900                   property, G_OBJECT_TYPE_NAME (object));
2901       return;
2902     }
2903 
2904   if ((flags & G_SETTINGS_BIND_GET) &&
2905       (binding->property->flags & G_PARAM_WRITABLE) == 0)
2906     {
2907       g_critical ("g_settings_bind: property '%s' on class '%s' is not "
2908                   "writable", binding->property->name, G_OBJECT_TYPE_NAME (object));
2909       return;
2910     }
2911   if ((flags & G_SETTINGS_BIND_SET) &&
2912       (binding->property->flags & G_PARAM_READABLE) == 0)
2913     {
2914       g_critical ("g_settings_bind: property '%s' on class '%s' is not "
2915                   "readable", binding->property->name, G_OBJECT_TYPE_NAME (object));
2916       return;
2917     }
2918 
2919   if (get_mapping == g_settings_bind_invert_boolean_get_mapping)
2920     {
2921       /* g_settings_bind_invert_boolean_get_mapping() is a private
2922        * function, so if we are here it means that g_settings_bind() was
2923        * called with G_SETTINGS_BIND_INVERT_BOOLEAN.
2924        *
2925        * Ensure that both sides are boolean.
2926        */
2927 
2928       if (binding->property->value_type != G_TYPE_BOOLEAN)
2929         {
2930           g_critical ("g_settings_bind: G_SETTINGS_BIND_INVERT_BOOLEAN "
2931                       "was specified, but property '%s' on type '%s' has "
2932                       "type '%s'", binding->property->name, G_OBJECT_TYPE_NAME (object),
2933                       g_type_name ((binding->property->value_type)));
2934           return;
2935         }
2936 
2937       if (!g_variant_type_equal (binding->key.type, G_VARIANT_TYPE_BOOLEAN))
2938         {
2939           gchar *type_string = g_variant_type_dup_string (binding->key.type);
2940           g_critical ("g_settings_bind: G_SETTINGS_BIND_INVERT_BOOLEAN "
2941                       "was specified, but key '%s' on schema '%s' has "
2942                       "type '%s'", key, g_settings_schema_get_id (settings->priv->schema),
2943                       type_string);
2944           g_free (type_string);
2945           return;
2946         }
2947 
2948     }
2949 
2950   else if (((get_mapping == NULL && (flags & G_SETTINGS_BIND_GET)) ||
2951             (set_mapping == NULL && (flags & G_SETTINGS_BIND_SET))) &&
2952            !g_settings_mapping_is_compatible (binding->property->value_type,
2953                                               binding->key.type))
2954     {
2955       gchar *type_string = g_variant_type_dup_string (binding->key.type);
2956       g_critical ("g_settings_bind: property '%s' on class '%s' has type "
2957                   "'%s' which is not compatible with type '%s' of key '%s' "
2958                   "on schema '%s'", binding->property->name, G_OBJECT_TYPE_NAME (object),
2959                   g_type_name (binding->property->value_type),
2960                   type_string, key,
2961                   g_settings_schema_get_id (settings->priv->schema));
2962       g_free (type_string);
2963       return;
2964     }
2965 
2966   if ((flags & G_SETTINGS_BIND_SET) &&
2967       (~flags & G_SETTINGS_BIND_NO_SENSITIVITY))
2968     {
2969       GParamSpec *sensitive;
2970 
2971       sensitive = g_object_class_find_property (objectclass, "sensitive");
2972 
2973       if (sensitive && sensitive->value_type == G_TYPE_BOOLEAN &&
2974           (sensitive->flags & G_PARAM_WRITABLE))
2975         g_settings_bind_writable (settings, binding->key.name, object, "sensitive", FALSE);
2976     }
2977 
2978   if (flags & G_SETTINGS_BIND_SET)
2979     {
2980       detailed_signal = g_strdup_printf ("notify::%s", binding->property->name);
2981       binding->property_handler_id =
2982         g_signal_connect (object, detailed_signal,
2983                           G_CALLBACK (g_settings_binding_property_changed),
2984                           binding);
2985       g_free (detailed_signal);
2986 
2987       if (~flags & G_SETTINGS_BIND_GET)
2988         g_settings_binding_property_changed (object,
2989                                              binding->property,
2990                                              binding);
2991     }
2992 
2993   if (flags & G_SETTINGS_BIND_GET)
2994     {
2995       if (~flags & G_SETTINGS_BIND_GET_NO_CHANGES)
2996         {
2997           detailed_signal = g_strdup_printf ("changed::%s", key);
2998           binding->key_handler_id =
2999             g_signal_connect (settings, detailed_signal,
3000                               G_CALLBACK (g_settings_binding_key_changed),
3001                               binding);
3002           g_free (detailed_signal);
3003         }
3004 
3005       g_settings_binding_key_changed (settings, binding->key.name, binding);
3006     }
3007 
3008   binding_quark = g_settings_binding_quark (binding->property->name);
3009   g_object_set_qdata_full (object, binding_quark,
3010                            binding, g_settings_binding_free);
3011 }
3012 
3013 /* Writability binding {{{1 */
3014 typedef struct
3015 {
3016   GSettings *settings;
3017   gpointer object;
3018   const gchar *key;
3019   const gchar *property;
3020   gboolean inverted;
3021   gulong handler_id;
3022 } GSettingsWritableBinding;
3023 
3024 static void
g_settings_writable_binding_free(gpointer data)3025 g_settings_writable_binding_free (gpointer data)
3026 {
3027   GSettingsWritableBinding *binding = data;
3028 
3029   g_signal_handler_disconnect (binding->settings, binding->handler_id);
3030   g_object_unref (binding->settings);
3031   g_slice_free (GSettingsWritableBinding, binding);
3032 }
3033 
3034 static void
g_settings_binding_writable_changed(GSettings * settings,const gchar * key,gpointer user_data)3035 g_settings_binding_writable_changed (GSettings   *settings,
3036                                      const gchar *key,
3037                                      gpointer     user_data)
3038 {
3039   GSettingsWritableBinding *binding = user_data;
3040   gboolean writable;
3041 
3042   g_assert (settings == binding->settings);
3043   g_assert (key == binding->key);
3044 
3045   writable = g_settings_is_writable (settings, key);
3046 
3047   if (binding->inverted)
3048     writable = !writable;
3049 
3050   g_object_set (binding->object, binding->property, writable, NULL);
3051 }
3052 
3053 /**
3054  * g_settings_bind_writable:
3055  * @settings: a #GSettings object
3056  * @key: the key to bind
3057  * @object: (type GObject.Object):a #GObject
3058  * @property: the name of a boolean property to bind
3059  * @inverted: whether to 'invert' the value
3060  *
3061  * Create a binding between the writability of @key in the
3062  * @settings object and the property @property of @object.
3063  * The property must be boolean; "sensitive" or "visible"
3064  * properties of widgets are the most likely candidates.
3065  *
3066  * Writable bindings are always uni-directional; changes of the
3067  * writability of the setting will be propagated to the object
3068  * property, not the other way.
3069  *
3070  * When the @inverted argument is %TRUE, the binding inverts the
3071  * value as it passes from the setting to the object, i.e. @property
3072  * will be set to %TRUE if the key is not writable.
3073  *
3074  * Note that the lifecycle of the binding is tied to @object,
3075  * and that you can have only one binding per object property.
3076  * If you bind the same property twice on the same object, the second
3077  * binding overrides the first one.
3078  *
3079  * Since: 2.26
3080  */
3081 void
g_settings_bind_writable(GSettings * settings,const gchar * key,gpointer object,const gchar * property,gboolean inverted)3082 g_settings_bind_writable (GSettings   *settings,
3083                           const gchar *key,
3084                           gpointer     object,
3085                           const gchar *property,
3086                           gboolean     inverted)
3087 {
3088   GSettingsWritableBinding *binding;
3089   gchar *detailed_signal;
3090   GParamSpec *pspec;
3091 
3092   g_return_if_fail (G_IS_SETTINGS (settings));
3093 
3094   pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), property);
3095   if (pspec == NULL)
3096     {
3097       g_critical ("g_settings_bind_writable: no property '%s' on class '%s'",
3098                   property, G_OBJECT_TYPE_NAME (object));
3099       return;
3100     }
3101   if ((pspec->flags & G_PARAM_WRITABLE) == 0)
3102     {
3103       g_critical ("g_settings_bind_writable: property '%s' on class '%s' is not writable",
3104                   property, G_OBJECT_TYPE_NAME (object));
3105       return;
3106     }
3107 
3108   binding = g_slice_new (GSettingsWritableBinding);
3109   binding->settings = g_object_ref (settings);
3110   binding->object = object;
3111   binding->key = g_intern_string (key);
3112   binding->property = g_intern_string (property);
3113   binding->inverted = inverted;
3114 
3115   detailed_signal = g_strdup_printf ("writable-changed::%s", key);
3116   binding->handler_id =
3117     g_signal_connect (settings, detailed_signal,
3118                       G_CALLBACK (g_settings_binding_writable_changed),
3119                       binding);
3120   g_free (detailed_signal);
3121 
3122   g_object_set_qdata_full (object, g_settings_binding_quark (property),
3123                            binding, g_settings_writable_binding_free);
3124 
3125   g_settings_binding_writable_changed (settings, binding->key, binding);
3126 }
3127 
3128 /**
3129  * g_settings_unbind:
3130  * @object: (type GObject.Object): the object
3131  * @property: the property whose binding is removed
3132  *
3133  * Removes an existing binding for @property on @object.
3134  *
3135  * Note that bindings are automatically removed when the
3136  * object is finalized, so it is rarely necessary to call this
3137  * function.
3138  *
3139  * Since: 2.26
3140  */
3141 void
g_settings_unbind(gpointer object,const gchar * property)3142 g_settings_unbind (gpointer     object,
3143                    const gchar *property)
3144 {
3145   GQuark binding_quark;
3146 
3147   binding_quark = g_settings_binding_quark (property);
3148   g_object_set_qdata (object, binding_quark, NULL);
3149 }
3150 
3151 /* GAction {{{1 */
3152 
3153 typedef struct
3154 {
3155   GObject parent_instance;
3156 
3157   GSettingsSchemaKey key;
3158   GSettings *settings;
3159 } GSettingsAction;
3160 
3161 typedef GObjectClass GSettingsActionClass;
3162 
3163 static GType g_settings_action_get_type (void);
3164 static void g_settings_action_iface_init (GActionInterface *iface);
3165 G_DEFINE_TYPE_WITH_CODE (GSettingsAction, g_settings_action, G_TYPE_OBJECT,
3166                          G_IMPLEMENT_INTERFACE (G_TYPE_ACTION, g_settings_action_iface_init))
3167 
3168 enum
3169 {
3170   ACTION_PROP_0,
3171   ACTION_PROP_NAME,
3172   ACTION_PROP_PARAMETER_TYPE,
3173   ACTION_PROP_ENABLED,
3174   ACTION_PROP_STATE_TYPE,
3175   ACTION_PROP_STATE
3176 };
3177 
3178 static const gchar *
g_settings_action_get_name(GAction * action)3179 g_settings_action_get_name (GAction *action)
3180 {
3181   GSettingsAction *gsa = (GSettingsAction *) action;
3182 
3183   return gsa->key.name;
3184 }
3185 
3186 static const GVariantType *
g_settings_action_get_parameter_type(GAction * action)3187 g_settings_action_get_parameter_type (GAction *action)
3188 {
3189   GSettingsAction *gsa = (GSettingsAction *) action;
3190   const GVariantType *type;
3191 
3192   type = g_variant_get_type (gsa->key.default_value);
3193   if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN))
3194     type = NULL;
3195 
3196   return type;
3197 }
3198 
3199 static gboolean
g_settings_action_get_enabled(GAction * action)3200 g_settings_action_get_enabled (GAction *action)
3201 {
3202   GSettingsAction *gsa = (GSettingsAction *) action;
3203 
3204   return g_settings_is_writable (gsa->settings, gsa->key.name);
3205 }
3206 
3207 static const GVariantType *
g_settings_action_get_state_type(GAction * action)3208 g_settings_action_get_state_type (GAction *action)
3209 {
3210   GSettingsAction *gsa = (GSettingsAction *) action;
3211 
3212   return g_variant_get_type (gsa->key.default_value);
3213 }
3214 
3215 static GVariant *
g_settings_action_get_state(GAction * action)3216 g_settings_action_get_state (GAction *action)
3217 {
3218   GSettingsAction *gsa = (GSettingsAction *) action;
3219   GVariant *value;
3220 
3221   value = g_settings_read_from_backend (gsa->settings, &gsa->key, FALSE, FALSE);
3222 
3223   if (value == NULL)
3224     value = g_settings_schema_key_get_translated_default (&gsa->key);
3225 
3226   if (value == NULL)
3227     value = g_variant_ref (gsa->key.default_value);
3228 
3229   return value;
3230 }
3231 
3232 static GVariant *
g_settings_action_get_state_hint(GAction * action)3233 g_settings_action_get_state_hint (GAction *action)
3234 {
3235   GSettingsAction *gsa = (GSettingsAction *) action;
3236 
3237   /* no point in reimplementing this... */
3238   return g_settings_schema_key_get_range (&gsa->key);
3239 }
3240 
3241 static void
g_settings_action_change_state(GAction * action,GVariant * value)3242 g_settings_action_change_state (GAction  *action,
3243                                 GVariant *value)
3244 {
3245   GSettingsAction *gsa = (GSettingsAction *) action;
3246 
3247   if (g_settings_schema_key_type_check (&gsa->key, value) && g_settings_schema_key_range_check (&gsa->key, value))
3248     g_settings_write_to_backend (gsa->settings, &gsa->key, value);
3249 }
3250 
3251 static void
g_settings_action_activate(GAction * action,GVariant * parameter)3252 g_settings_action_activate (GAction  *action,
3253                             GVariant *parameter)
3254 {
3255   GSettingsAction *gsa = (GSettingsAction *) action;
3256 
3257   if (g_variant_is_of_type (gsa->key.default_value, G_VARIANT_TYPE_BOOLEAN))
3258     {
3259       GVariant *old;
3260 
3261       if (parameter != NULL)
3262         return;
3263 
3264       old = g_settings_action_get_state (action);
3265       parameter = g_variant_new_boolean (!g_variant_get_boolean (old));
3266       g_variant_unref (old);
3267     }
3268 
3269   g_action_change_state (action, parameter);
3270 }
3271 
3272 static void
g_settings_action_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)3273 g_settings_action_get_property (GObject *object, guint prop_id,
3274                                 GValue *value, GParamSpec *pspec)
3275 {
3276   GAction *action = G_ACTION (object);
3277 
3278   switch (prop_id)
3279     {
3280     case ACTION_PROP_NAME:
3281       g_value_set_string (value, g_settings_action_get_name (action));
3282       break;
3283 
3284     case ACTION_PROP_PARAMETER_TYPE:
3285       g_value_set_boxed (value, g_settings_action_get_parameter_type (action));
3286       break;
3287 
3288     case ACTION_PROP_ENABLED:
3289       g_value_set_boolean (value, g_settings_action_get_enabled (action));
3290       break;
3291 
3292     case ACTION_PROP_STATE_TYPE:
3293       g_value_set_boxed (value, g_settings_action_get_state_type (action));
3294       break;
3295 
3296     case ACTION_PROP_STATE:
3297       g_value_take_variant (value, g_settings_action_get_state (action));
3298       break;
3299 
3300     default:
3301       g_assert_not_reached ();
3302     }
3303 }
3304 
3305 static void
g_settings_action_finalize(GObject * object)3306 g_settings_action_finalize (GObject *object)
3307 {
3308   GSettingsAction *gsa = (GSettingsAction *) object;
3309 
3310   g_signal_handlers_disconnect_by_data (gsa->settings, gsa);
3311   g_object_unref (gsa->settings);
3312   g_settings_schema_key_clear (&gsa->key);
3313 
3314   G_OBJECT_CLASS (g_settings_action_parent_class)
3315     ->finalize (object);
3316 }
3317 
3318 static void
g_settings_action_init(GSettingsAction * gsa)3319 g_settings_action_init (GSettingsAction *gsa)
3320 {
3321 }
3322 
3323 static void
g_settings_action_iface_init(GActionInterface * iface)3324 g_settings_action_iface_init (GActionInterface *iface)
3325 {
3326   iface->get_name = g_settings_action_get_name;
3327   iface->get_parameter_type = g_settings_action_get_parameter_type;
3328   iface->get_enabled = g_settings_action_get_enabled;
3329   iface->get_state_type = g_settings_action_get_state_type;
3330   iface->get_state = g_settings_action_get_state;
3331   iface->get_state_hint = g_settings_action_get_state_hint;
3332   iface->change_state = g_settings_action_change_state;
3333   iface->activate = g_settings_action_activate;
3334 }
3335 
3336 static void
g_settings_action_class_init(GSettingsActionClass * class)3337 g_settings_action_class_init (GSettingsActionClass *class)
3338 {
3339   class->get_property = g_settings_action_get_property;
3340   class->finalize = g_settings_action_finalize;
3341 
3342   g_object_class_override_property (class, ACTION_PROP_NAME, "name");
3343   g_object_class_override_property (class, ACTION_PROP_PARAMETER_TYPE, "parameter-type");
3344   g_object_class_override_property (class, ACTION_PROP_ENABLED, "enabled");
3345   g_object_class_override_property (class, ACTION_PROP_STATE_TYPE, "state-type");
3346   g_object_class_override_property (class, ACTION_PROP_STATE, "state");
3347 }
3348 
3349 static void
g_settings_action_changed(GSettings * settings,const gchar * key,gpointer user_data)3350 g_settings_action_changed (GSettings   *settings,
3351                            const gchar *key,
3352                            gpointer     user_data)
3353 {
3354   g_object_notify (user_data, "state");
3355 }
3356 
3357 static void
g_settings_action_enabled_changed(GSettings * settings,const gchar * key,gpointer user_data)3358 g_settings_action_enabled_changed (GSettings   *settings,
3359                                    const gchar *key,
3360                                    gpointer     user_data)
3361 {
3362   g_object_notify (user_data, "enabled");
3363 }
3364 
3365 /**
3366  * g_settings_create_action:
3367  * @settings: a #GSettings
3368  * @key: the name of a key in @settings
3369  *
3370  * Creates a #GAction corresponding to a given #GSettings key.
3371  *
3372  * The action has the same name as the key.
3373  *
3374  * The value of the key becomes the state of the action and the action
3375  * is enabled when the key is writable.  Changing the state of the
3376  * action results in the key being written to.  Changes to the value or
3377  * writability of the key cause appropriate change notifications to be
3378  * emitted for the action.
3379  *
3380  * For boolean-valued keys, action activations take no parameter and
3381  * result in the toggling of the value.  For all other types,
3382  * activations take the new value for the key (which must have the
3383  * correct type).
3384  *
3385  * Returns: (transfer full): a new #GAction
3386  *
3387  * Since: 2.32
3388  **/
3389 GAction *
g_settings_create_action(GSettings * settings,const gchar * key)3390 g_settings_create_action (GSettings   *settings,
3391                           const gchar *key)
3392 {
3393   GSettingsAction *gsa;
3394   gchar *detailed_signal;
3395 
3396   g_return_val_if_fail (G_IS_SETTINGS (settings), NULL);
3397   g_return_val_if_fail (key != NULL, NULL);
3398 
3399   gsa = g_object_new (g_settings_action_get_type (), NULL);
3400   gsa->settings = g_object_ref (settings);
3401   g_settings_schema_key_init (&gsa->key, settings->priv->schema, key);
3402 
3403   detailed_signal = g_strdup_printf ("changed::%s", key);
3404   g_signal_connect (settings, detailed_signal, G_CALLBACK (g_settings_action_changed), gsa);
3405   g_free (detailed_signal);
3406   detailed_signal = g_strdup_printf ("writable-changed::%s", key);
3407   g_signal_connect (settings, detailed_signal, G_CALLBACK (g_settings_action_enabled_changed), gsa);
3408   g_free (detailed_signal);
3409 
3410   return G_ACTION (gsa);
3411 }
3412 
3413 /* Epilogue {{{1 */
3414 
3415 /* vim:set foldmethod=marker: */
3416