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