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