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