mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-04 18:26:19 +01:00
parent
4411023462
commit
221ba4e211
@ -271,7 +271,6 @@
|
|||||||
<title>Migrating to GIO</title>
|
<title>Migrating to GIO</title>
|
||||||
<xi:include href="xml/migrating-posix.xml"/>
|
<xi:include href="xml/migrating-posix.xml"/>
|
||||||
<xi:include href="xml/migrating-gnome-vfs.xml"/>
|
<xi:include href="xml/migrating-gnome-vfs.xml"/>
|
||||||
<xi:include href="xml/migrating-gconf.xml"/>
|
|
||||||
<xi:include href="xml/migrating-gdbus.xml"/>
|
<xi:include href="xml/migrating-gdbus.xml"/>
|
||||||
</part>
|
</part>
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ show_class_hierarchy = true
|
|||||||
urlmap_file = "urlmap.js"
|
urlmap_file = "urlmap.js"
|
||||||
# The same order will be used when generating the index
|
# The same order will be used when generating the index
|
||||||
content_files = [
|
content_files = [
|
||||||
|
"migrating-gconf.md",
|
||||||
]
|
]
|
||||||
content_images = [
|
content_images = [
|
||||||
"menu-example.png",
|
"menu-example.png",
|
||||||
|
@ -164,7 +164,6 @@ if get_option('gtk_doc')
|
|||||||
'overview.xml',
|
'overview.xml',
|
||||||
'migrating-posix.xml',
|
'migrating-posix.xml',
|
||||||
'migrating-gnome-vfs.xml',
|
'migrating-gnome-vfs.xml',
|
||||||
'migrating-gconf.xml',
|
|
||||||
'migrating-gdbus.xml',
|
'migrating-gdbus.xml',
|
||||||
'gio-querymodules.xml',
|
'gio-querymodules.xml',
|
||||||
'glib-compile-schemas.xml',
|
'glib-compile-schemas.xml',
|
||||||
@ -201,7 +200,6 @@ if get_option('gtk_doc')
|
|||||||
'overview.xml',
|
'overview.xml',
|
||||||
'migrating-posix.xml',
|
'migrating-posix.xml',
|
||||||
'migrating-gnome-vfs.xml',
|
'migrating-gnome-vfs.xml',
|
||||||
'migrating-gconf.xml',
|
|
||||||
'migrating-gdbus.xml',
|
'migrating-gdbus.xml',
|
||||||
'gdbus-codegen.xml',
|
'gdbus-codegen.xml',
|
||||||
],
|
],
|
||||||
@ -237,6 +235,7 @@ endif
|
|||||||
|
|
||||||
# gi-docgen version
|
# gi-docgen version
|
||||||
expand_content_files = [
|
expand_content_files = [
|
||||||
|
'migrating-gconf.md',
|
||||||
]
|
]
|
||||||
|
|
||||||
gio_gir = meson.current_source_dir() / 'Gio-2.0.gir'
|
gio_gir = meson.current_source_dir() / 'Gio-2.0.gir'
|
||||||
|
466
docs/reference/gio/migrating-gconf.md
Normal file
466
docs/reference/gio/migrating-gconf.md
Normal file
@ -0,0 +1,466 @@
|
|||||||
|
Title: Migrating from GConf to GSettings
|
||||||
|
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
SPDX-FileCopyrightText: 2010, 2012 Matthias Clasen
|
||||||
|
SPDX-FileCopyrightText: 2010 Allison Lortie
|
||||||
|
SPDX-FileCopyrightText: 2011 Ray Strode
|
||||||
|
|
||||||
|
# Migrating from GConf to GSettings
|
||||||
|
|
||||||
|
## Before you start
|
||||||
|
|
||||||
|
Converting individual applications and their settings from GConf to
|
||||||
|
GSettings can be done at will. But desktop-wide settings like font or theme
|
||||||
|
settings often have consumers in multiple modules. Therefore, some
|
||||||
|
consideration has to go into making sure that all users of a setting are
|
||||||
|
converted to GSettings at the same time or that the program responsible for
|
||||||
|
configuring that setting continues to update the value in both places.
|
||||||
|
|
||||||
|
It is always a good idea to have a look at how others have handled similar
|
||||||
|
problems before.
|
||||||
|
|
||||||
|
## Conceptual differences
|
||||||
|
|
||||||
|
Conceptually, GConf and GSettings are fairly similar. Both have a concept of
|
||||||
|
pluggable backends. Both keep information about keys and their types in
|
||||||
|
schemas. Both have a concept of mandatory values, which lets you implement
|
||||||
|
lock-down.
|
||||||
|
|
||||||
|
There are some differences in the approach to schemas. GConf installs the
|
||||||
|
schemas into the database and has API to handle schema information
|
||||||
|
(`gconf_client_get_default_from_schema()`, `gconf_value_get_schema()`, etc).
|
||||||
|
GSettings on the other hand assumes that an application knows its own
|
||||||
|
schemas, and does not provide API to handle schema information at runtime.
|
||||||
|
GSettings is also more strict about requiring a schema whenever you want to
|
||||||
|
read or write a key. To deal with more free-form information that would
|
||||||
|
appear in schema-less entries in GConf, GSettings allows for schemas to be
|
||||||
|
'relocatable'.
|
||||||
|
|
||||||
|
One difference in the way applications interact with their settings is that
|
||||||
|
with GConf you interact with a tree of settings (ie the keys you pass to
|
||||||
|
functions when reading or writing values are actually paths with the actual
|
||||||
|
name of the key as the last element. With GSettings, you create a GSettings
|
||||||
|
object which has an implicit prefix that determines where the settings get
|
||||||
|
stored in the global tree of settings, but the keys you pass when reading or
|
||||||
|
writing values are just the key names, not the full path.
|
||||||
|
|
||||||
|
## GConfClient (and GConfBridge) API conversion
|
||||||
|
|
||||||
|
Most people use GConf via the high-level `GConfClient` API. The
|
||||||
|
corresponding API is the [class@Gio.Settings] object. While not every
|
||||||
|
`GConfClient` function has a direct GSettings equivalent, many do:
|
||||||
|
|
||||||
|
| GConfClient | GSettings |
|
||||||
|
|-------------|-----------|
|
||||||
|
| `gconf_client_get_default()` | no direct equivalent, instead you call [`ctor@Gio.Settings.new`] for the schemas you use |
|
||||||
|
| `gconf_client_set()` | [`method@Gio.Settings.set`] |
|
||||||
|
| `gconf_client_get()` | `g_settings_get()` |
|
||||||
|
| `gconf_client_get_bool()` | `g_settings_get_boolean()` |
|
||||||
|
| `gconf_client_set_bool()` | `g_settings_set_boolean()` |
|
||||||
|
| `gconf_client_get_int()` | `g_settings_get_int()` |
|
||||||
|
| `gconf_client_set_int()` | `g_settings_set_int()` |
|
||||||
|
| `gconf_client_get_float()` | `g_settings_get_double()` |
|
||||||
|
| `gconf_client_set_float()` | `g_settings_set_double()` |
|
||||||
|
| `gconf_client_get_string()` | `g_settings_get_string()` |
|
||||||
|
| `gconf_client_set_string()` | `g_settings_set_string()` |
|
||||||
|
| `gconf_client_get_list()` | for string lists, see `g_settings_get_strv()`, else see `g_settings_get_value()` and GVariant API |
|
||||||
|
| `gconf_client_set_list()` | for string lists, see `g_settings_set_strv()`, else see `g_settings_set_value()` and GVariant API |
|
||||||
|
| `gconf_entry_get_is_writable()` | `g_settings_is_writable()` |
|
||||||
|
| `gconf_client_notify_add()` | not required, the “changed” signal is emitted automatically |
|
||||||
|
| `gconf_client_add_dir()` | not required, each GSettings instance automatically watches all keys in its path |
|
||||||
|
| `GConfChangeSet` | `g_settings_delay()`, `g_settings_apply()` |
|
||||||
|
| `gconf_client_get_default_from_schema()` | no equivalent, applications are expected to know their schema |
|
||||||
|
| `gconf_client_all_entries()` | no equivalent, applications are expected to know their schema, and GSettings does not allow schema-less entries |
|
||||||
|
| `gconf_client_get_without_default()` | no equivalent |
|
||||||
|
| `gconf_bridge_bind_property()` | `g_settings_bind()` |
|
||||||
|
| `gconf_bridge_bind_property_full()` | `g_settings_bind_with_mapping()` |
|
||||||
|
|
||||||
|
GConfBridge was a third-party library that used GConf to bind an object
|
||||||
|
property to a particular configuration key. GSettings offers this service
|
||||||
|
itself.
|
||||||
|
|
||||||
|
There is a pattern that is sometimes used for GConf, where a setting can
|
||||||
|
have explicit 'value A', explicit 'value B' or 'use the system default'.
|
||||||
|
With GConf, 'use the system default' is sometimes implemented by unsetting
|
||||||
|
the user value. This is not possible in GSettings, since it does not have
|
||||||
|
API to determine if a value is the default and does not let you unset
|
||||||
|
values. The recommended way (and much clearer) way in which this can be
|
||||||
|
implemented in GSettings is to have a separate 'use-system-default' boolean
|
||||||
|
setting.
|
||||||
|
|
||||||
|
## Change notification
|
||||||
|
|
||||||
|
GConf requires you to call `gconf_client_add_dir()` and
|
||||||
|
`gconf_client_notify_add()` to get change notification. With GSettings, this
|
||||||
|
is not necessary; signals get emitted automatically for every change.
|
||||||
|
|
||||||
|
The [signal@Gio.Settings::changed] signal is emitted for each changed key.
|
||||||
|
There is also a [`signal@Gio.Settings::change-event`] signal that you can
|
||||||
|
handle if you need to see groups of keys that get changed at the same time.
|
||||||
|
|
||||||
|
GSettings also notifies you about changes in writability of keys, with the
|
||||||
|
[signal@Gio.Settings::writable-changed] signal (and the
|
||||||
|
[signal@Gio.Settings::writable-change-event] signal).
|
||||||
|
|
||||||
|
## Change sets
|
||||||
|
|
||||||
|
GConf has a concept of a set of changes which can be applied or reverted at
|
||||||
|
once: `GConfChangeSet` (GConf doesn't actually apply changes atomically,
|
||||||
|
which is one of its shortcomings).
|
||||||
|
|
||||||
|
Instead of a separate object to represent a change set, GSettings has a
|
||||||
|
'delayed-apply' mode, which can be turned on for a [class@Gio.Settings]
|
||||||
|
object by calling [method@Gio.Settings.delay]. In this mode, changes done to
|
||||||
|
the GSettings object are not applied - they are still visible when calling
|
||||||
|
[method@Gio.Settings.get] on the same object, but not to other GSettings
|
||||||
|
instances or even other processes.
|
||||||
|
|
||||||
|
To apply the pending changes all at once (GSettings does atomicity here),
|
||||||
|
call [method@Gio.Settings.apply]. To revert the pending changes, call
|
||||||
|
[method@Gio.Settings.revert] or just drop the reference to the GSettings
|
||||||
|
object.
|
||||||
|
|
||||||
|
## Schema conversion
|
||||||
|
|
||||||
|
If you are porting your application from GConf, most likely you already have
|
||||||
|
a GConf schema. GConf comes with a commandline tool
|
||||||
|
`gsettings-schema-convert` that can help with the task of converting a GConf
|
||||||
|
schema into an equivalent GSettings schema. The tool is not perfect and may
|
||||||
|
need assistance in some cases.
|
||||||
|
|
||||||
|
### An example for using gsettings-schema-convert
|
||||||
|
|
||||||
|
Running `gsettings-schema-convert --gconf --xml --schema-id
|
||||||
|
"org.gnome.font-rendering" --output org.gnome.font-rendering.gschema.xml
|
||||||
|
destop_gnome_font_rendering.schemas` on the following
|
||||||
|
`desktop_gnome_font_rendering.schemas` file:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<gconfschemafile>
|
||||||
|
<schemalist>
|
||||||
|
<schema>
|
||||||
|
<key>/schemas/desktop/gnome/font_rendering/dpi</key>
|
||||||
|
<applyto>/desktop/gnome/font_rendering/dpi</applyto>
|
||||||
|
<owner>gnome</owner>
|
||||||
|
<type>int</type>
|
||||||
|
<default>96</default>
|
||||||
|
<locale name="C">
|
||||||
|
<short>DPI</short>
|
||||||
|
<long>The resolution used for converting font sizes to pixel sizes, in dots per inch.</long>
|
||||||
|
</locale>
|
||||||
|
</schema>
|
||||||
|
</schemalist>
|
||||||
|
</gconfschemafile>
|
||||||
|
```
|
||||||
|
|
||||||
|
produces an `org.gnome.font-rendering.gschema.xml` file with the following content:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<schemalist>
|
||||||
|
<schema id="org.gnome.font-rendering" path="/desktop/gnome/font_rendering/">
|
||||||
|
<key name="dpi" type="i">
|
||||||
|
<default>96</default>
|
||||||
|
<summary>DPI</summary>
|
||||||
|
<description>The resolution used for converting font sizes to pixel sizes, in dots per inch.</description>
|
||||||
|
</key>
|
||||||
|
</schema>
|
||||||
|
</schemalist>
|
||||||
|
```
|
||||||
|
|
||||||
|
GSettings schemas are identified at runtime by their id (as specified in the
|
||||||
|
XML source file). It is recommended to use a dotted name as schema id,
|
||||||
|
similar in style to a D-Bus bus name, e.g. "org.gnome.SessionManager". In
|
||||||
|
cases where the settings are general and not specific to one application,
|
||||||
|
the id should not use StudlyCaps, e.g. "org.gnome.font-rendering". The
|
||||||
|
filename used for the XML schema source is immaterial, but schema compiler
|
||||||
|
expects the files to have the extension `.gschema.xml`. It is recommended to
|
||||||
|
simply use the schema id as the filename, followed by this extension, e.g.
|
||||||
|
`org.gnome.SessionManager.gschema.xml`.
|
||||||
|
|
||||||
|
The XML source file for your GSettings schema needs to get installed into
|
||||||
|
`$datadir/glib-2.0/schemas`, and needs to be compiled into a binary form. At
|
||||||
|
runtime, GSettings looks for compiled schemas in the `glib-2.0/schemas`
|
||||||
|
subdirectories of all `XDG_DATA_DIRS` directories, so if you install your
|
||||||
|
schema in a different location, you need to set the `XDG_DATA_DIRS`
|
||||||
|
environment variable appropriately.
|
||||||
|
|
||||||
|
Schemas are compiled into binary form by the `glib-compile-schemas` utility.
|
||||||
|
GIO provides a `glib_compile_schemas` variable in its pkg-config file
|
||||||
|
pointing to the schema compiler binary.
|
||||||
|
|
||||||
|
### Using schemas with Meson
|
||||||
|
|
||||||
|
You should use `install_data()` to install the `.gschema.xml` file in the
|
||||||
|
correct directory, e.g.
|
||||||
|
|
||||||
|
```
|
||||||
|
install_data('my.app.gschema.xml', install_dir: get_option('datadir') / 'glib-2.0/schemas')
|
||||||
|
```
|
||||||
|
|
||||||
|
Schema compilation is done at installation time; if you are using Meson 0.57 or newer, you can use the `gnome.post_install()` function from the GNOME module:
|
||||||
|
|
||||||
|
```
|
||||||
|
gnome.post_install(glib_compile_schemas: true)
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively, you can use `meson.add_install_script()` and the following
|
||||||
|
Python script:
|
||||||
|
|
||||||
|
```py
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# build-aux/compile-schemas.py
|
||||||
|
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
install_prefix = os.environ['MESON_INSTALL_PREFIX']
|
||||||
|
schemadir = os.path.join(install_prefix, 'share', 'glib-2.0', 'schemas')
|
||||||
|
|
||||||
|
if not os.environ.get('DESTDIR'):
|
||||||
|
print('Compiling gsettings schemas...')
|
||||||
|
subprocess.call(['glib-compile-schemas', schemadir])
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
meson.add_install_script('build-aux/compile-schemas.py')
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using schemas with Autotools
|
||||||
|
|
||||||
|
GLib provides m4 macros for hiding the various complexities and reduce the
|
||||||
|
chances of getting things wrong.
|
||||||
|
|
||||||
|
To handle schemas in your Autotools build, start by adding this to your
|
||||||
|
`configure.ac`:
|
||||||
|
|
||||||
|
```
|
||||||
|
GLIB_GSETTINGS
|
||||||
|
```
|
||||||
|
|
||||||
|
Then add this fragment to your `Makefile.am`:
|
||||||
|
|
||||||
|
```
|
||||||
|
# gsettings_SCHEMAS is a list of all the schemas you want to install
|
||||||
|
gsettings_SCHEMAS = my.app.gschema.xml
|
||||||
|
|
||||||
|
# include the appropriate makefile rules for schema handling
|
||||||
|
@GSETTINGS_RULES@
|
||||||
|
```
|
||||||
|
|
||||||
|
This is not sufficient on its own. You need to mention what the source of
|
||||||
|
the `my.app.gschema.xml` file is. If the schema file is distributed directly
|
||||||
|
with your project's tarball then a mention in `EXTRA_DIST` is appropriate. If
|
||||||
|
the schema file is generated from another source then you will need the
|
||||||
|
appropriate rule for that, plus probably an item in `EXTRA_DIST` for the
|
||||||
|
source files used by that rule.
|
||||||
|
|
||||||
|
One possible pitfall in doing schema conversion is that the default values
|
||||||
|
in GSettings schemas are parsed by the GVariant parser. This means that
|
||||||
|
strings need to include quotes in the XML. Also note that the types are now
|
||||||
|
specified as GVariant type strings.
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<type>string</type>
|
||||||
|
<default>rgb</default>
|
||||||
|
```
|
||||||
|
|
||||||
|
becomes
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<key name="rgba-order" type="s">
|
||||||
|
<default>'rgb'</default> <!-- note quotes -->
|
||||||
|
</key>
|
||||||
|
```
|
||||||
|
|
||||||
|
Another possible complication is that GConf specifies full paths for each
|
||||||
|
key, while a GSettings schema has a 'path' attribute that contains the
|
||||||
|
prefix for all the keys in the schema, and individual keys just have a
|
||||||
|
simple name. So
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<key>/schemas/desktop/gnome/font_rendering/antialiasing</key>
|
||||||
|
```
|
||||||
|
|
||||||
|
becomes
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<schema id="org.gnome.font" path="/desktop/gnome/font_rendering/">
|
||||||
|
<key name="antialiasing" type="s">
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Default values can be localized in both GConf and GSettings schemas, but
|
||||||
|
GSettings uses gettext for the localization. You can specify the gettext
|
||||||
|
domain to use in the gettext-domain attribute. Therefore, when converting
|
||||||
|
localized defaults in GConf,
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<key>/schemas/apps/my_app/font_size</key>
|
||||||
|
<locale name="C">
|
||||||
|
<default>18</default>
|
||||||
|
</locale>
|
||||||
|
<locale name="be">
|
||||||
|
<default>24</default>
|
||||||
|
</locale>
|
||||||
|
</key>
|
||||||
|
```
|
||||||
|
|
||||||
|
becomes
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<schema id="..." gettext-domain="your-domain">
|
||||||
|
...
|
||||||
|
<key name="font-size" type="i">
|
||||||
|
<default l10n="messages" context="font_size">18</default>
|
||||||
|
</key>
|
||||||
|
```
|
||||||
|
|
||||||
|
GSettings uses gettext for translation of default values. The string that is
|
||||||
|
translated is exactly the string that appears inside of the `<default>`
|
||||||
|
element. This includes the quotation marks that appear around strings.
|
||||||
|
Default values must be marked with the l10n attribute in the `<default>` tag,
|
||||||
|
which should be set as equal to 'messages' or 'time' depending on the
|
||||||
|
desired category. An optional translation context can also be specified with
|
||||||
|
the context attribute, as in the example. This is usually recommended, since
|
||||||
|
the string "18" is not particularly easy to translate without context. The
|
||||||
|
translated version of the default value should be stored in the specified
|
||||||
|
gettext-domain. Care must be taken during translation to ensure that all
|
||||||
|
translated values remain syntactically valid; mistakes here will cause
|
||||||
|
runtime errors.
|
||||||
|
|
||||||
|
GSettings schemas have optional `<summary>` and `<description>` elements for
|
||||||
|
each key which correspond to the `<short>` and `<long>` elements in the
|
||||||
|
GConf schema and can be used in the same way by a GUI editor, so you should
|
||||||
|
use the same conventions for them: The summary is just a short label with no
|
||||||
|
punctuation, the description can be one or more complete sentences. If
|
||||||
|
multiple paragraphs are desired for the description, the paragraphs should
|
||||||
|
be separated by a completely empty line.
|
||||||
|
|
||||||
|
Translations for these strings will also be handled via gettext, so you
|
||||||
|
should arrange for these strings to be extracted into your gettext catalog.
|
||||||
|
Gettext supports GSettings schemas natively since version 0.19, so all you
|
||||||
|
have to do is add the XML schema file to the list of translatable files
|
||||||
|
inside your `POTFILES.in`.
|
||||||
|
|
||||||
|
GSettings is a bit more restrictive about key names than GConf. Key names in
|
||||||
|
GSettings can be at most 32 characters long, and must only consist of
|
||||||
|
lowercase characters, numbers and dashes, with no consecutive dashes. The
|
||||||
|
first character must not be a number or dash, and the last character cannot
|
||||||
|
be '-'.
|
||||||
|
|
||||||
|
If you are using the GConf backend for GSettings during the transition, you
|
||||||
|
may want to keep your key names the same they were in GConf, so that
|
||||||
|
existing settings in the users GConf database are preserved. You can achieve
|
||||||
|
this by using the `--allow-any-name` with the `glib-compile-schemas` schema
|
||||||
|
compiler. Note that this option is only meant to ease the process of porting
|
||||||
|
your application, allowing parts of your application to continue to access
|
||||||
|
GConf and parts to use GSettings. By the time you have finished porting your
|
||||||
|
application you must ensure that all key names are valid.
|
||||||
|
|
||||||
|
## Data conversion
|
||||||
|
|
||||||
|
GConf comes with a GSettings backend that can be used to facility the
|
||||||
|
transition to the GSettings API until you are ready to make the jump to a
|
||||||
|
different backend (most likely dconf). To use it, you need to set the
|
||||||
|
`GSETTINGS_BACKEND` to 'gconf', e.g. by using
|
||||||
|
|
||||||
|
```c
|
||||||
|
g_setenv ("GSETTINGS_BACKEND", "gconf", TRUE);
|
||||||
|
```
|
||||||
|
|
||||||
|
early on in your program. Note that this backend is meant purely as a
|
||||||
|
transition tool, and should not be used in production.
|
||||||
|
|
||||||
|
GConf also comes with a utility called `gsettings-data-convert`, which is
|
||||||
|
designed to help with the task of migrating user settings from GConf into
|
||||||
|
another GSettings backend. It can be run manually, but it is designed to be
|
||||||
|
executed automatically, every time a user logs in. It keeps track of the
|
||||||
|
data migrations that it has already done, and it is harmless to run it more
|
||||||
|
than once.
|
||||||
|
|
||||||
|
To make use of this utility, you must install a keyfile in the directory
|
||||||
|
`/usr/share/GConf/gsettings` which lists the GSettings keys and GConf paths
|
||||||
|
to map to each other, for each schema that you want to migrate user data
|
||||||
|
for.
|
||||||
|
|
||||||
|
Here is an example:
|
||||||
|
|
||||||
|
```
|
||||||
|
[org.gnome.fonts]
|
||||||
|
antialiasing = /desktop/gnome/font_rendering/antialiasing
|
||||||
|
dpi = /desktop/gnome/font_rendering/dpi
|
||||||
|
hinting = /desktop/gnome/font_rendering/hinting
|
||||||
|
rgba-order = /desktop/gnome/font_rendering/rgba_order
|
||||||
|
|
||||||
|
[apps.myapp:/path/to/myapps/]
|
||||||
|
some-odd-key1 = /apps/myapp/some_ODD-key1
|
||||||
|
```
|
||||||
|
|
||||||
|
The last key demonstrates that it may be necessary to modify the key name to
|
||||||
|
comply with stricter GSettings key name rules. Of course, that means your
|
||||||
|
application must use the new key names when looking up settings in
|
||||||
|
GSettings.
|
||||||
|
|
||||||
|
The last group in the example also shows how to handle the case of
|
||||||
|
'relocatable' schemas, which don't have a fixed path. You can specify the
|
||||||
|
path to use in the group name, separated by a colon.
|
||||||
|
|
||||||
|
There are some limitations: `gsettings-data-convert` does not do any
|
||||||
|
transformation of the values. And it does not handle complex GConf types
|
||||||
|
other than lists of strings or integers.
|
||||||
|
|
||||||
|
**Don't forget to require GConf 2.31.1 or newer in your configure script if
|
||||||
|
you are making use of the GConf backend or the conversion utility.**
|
||||||
|
|
||||||
|
If, as an application developer, you are interested in manually ensuring
|
||||||
|
that `gsettings-data-convert` has been invoked (for example, to deal with the
|
||||||
|
case where the user is logged in during a distribution upgrade or for
|
||||||
|
non-XDG desktop environments which do not run the command as an autostart)
|
||||||
|
you may invoke it manually during your program initialisation. This is not
|
||||||
|
recommended for all application authors -- it is your choice if this use
|
||||||
|
case concerns you enough.
|
||||||
|
|
||||||
|
Internally, `gsettings-data-convert` uses a keyfile to track which settings
|
||||||
|
have been migrated. The following code fragment will check that keyfile to
|
||||||
|
see if your data conversion script has been run yet and, if not, will
|
||||||
|
attempt to invoke the tool to run it. You should adapt it to your
|
||||||
|
application as you see fit.
|
||||||
|
|
||||||
|
```c
|
||||||
|
static void
|
||||||
|
ensure_migrated (const gchar *name)
|
||||||
|
{
|
||||||
|
gboolean needed = TRUE;
|
||||||
|
GKeyFile *kf;
|
||||||
|
gchar **list;
|
||||||
|
gsize i, n;
|
||||||
|
|
||||||
|
kf = g_key_file_new ();
|
||||||
|
|
||||||
|
g_key_file_load_from_data_dirs (kf, "gsettings-data-convert",
|
||||||
|
NULL, G_KEY_FILE_NONE, NULL);
|
||||||
|
list = g_key_file_get_string_list (kf, "State", "converted", &n, NULL);
|
||||||
|
|
||||||
|
if (list)
|
||||||
|
{
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
if (strcmp (list[i], name) == 0)
|
||||||
|
{
|
||||||
|
needed = FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_strfreev (list);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_key_file_free (kf);
|
||||||
|
|
||||||
|
if (needed)
|
||||||
|
g_spawn_command_line_sync ("gsettings-data-convert",
|
||||||
|
NULL, NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Although there is the possibility that the `gsettings-data-convert` script
|
||||||
|
will end up running multiple times concurrently with this approach, it is
|
||||||
|
believed that this is safe.
|
@ -1,515 +0,0 @@
|
|||||||
<chapter>
|
|
||||||
<title>Migrating from GConf to GSettings</title>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Before you start</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Converting individual applications and their settings from GConf to
|
|
||||||
GSettings can be done at will. But desktop-wide settings like font or
|
|
||||||
theme settings often have consumers in multiple modules. Therefore,
|
|
||||||
some consideration has to go into making sure that all users of a setting
|
|
||||||
are converted to GSettings at the same time or that the program
|
|
||||||
responsible for configuring that setting continues to update the value in
|
|
||||||
both places.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
It is always a good idea to have a look at how others have handled
|
|
||||||
similar problems before.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Conceptual differences</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Conceptually, GConf and GSettings are fairly similar. Both
|
|
||||||
have a concept of pluggable backends. Both keep information
|
|
||||||
about keys and their types in schemas. Both have a concept of
|
|
||||||
mandatory values, which lets you implement lock-down.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
There are some differences in the approach to schemas. GConf
|
|
||||||
installs the schemas into the database and has API to handle
|
|
||||||
schema information (gconf_client_get_default_from_schema(),
|
|
||||||
gconf_value_get_schema(), etc). GSettings on the other hand
|
|
||||||
assumes that an application knows its own schemas, and does
|
|
||||||
not provide API to handle schema information at runtime.
|
|
||||||
GSettings is also more strict about requiring a schema whenever
|
|
||||||
you want to read or write a key. To deal with more free-form
|
|
||||||
information that would appear in schema-less entries in GConf,
|
|
||||||
GSettings allows for schemas to be 'relocatable'.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
One difference in the way applications interact with their
|
|
||||||
settings is that with GConf you interact with a tree of
|
|
||||||
settings (ie the keys you pass to functions when reading
|
|
||||||
or writing values are actually paths with the actual name
|
|
||||||
of the key as the last element. With GSettings, you create
|
|
||||||
a GSettings object which has an implicit prefix that determines
|
|
||||||
where the settings get stored in the global tree of settings,
|
|
||||||
but the keys you pass when reading or writing values are just
|
|
||||||
the key names, not the full path.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>GConfClient (and GConfBridge) API conversion</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Most people use GConf via the high-level #GConfClient API.
|
|
||||||
The corresponding API is the #GSettings object. While not
|
|
||||||
every GConfClient function has a direct GSettings equivalent,
|
|
||||||
many do:
|
|
||||||
<table id="gconf-client-vs-gsettings">
|
|
||||||
<tgroup cols="2">
|
|
||||||
<thead>
|
|
||||||
<row><entry>GConfClient</entry><entry>GSettings</entry></row>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<row><entry>gconf_client_get_default()</entry><entry>no direct equivalent,
|
|
||||||
instead you call g_settings_new() for the schemas you use</entry></row>
|
|
||||||
<row><entry>gconf_client_set()</entry><entry>g_settings_set()</entry></row>
|
|
||||||
<row><entry>gconf_client_get()</entry><entry>g_settings_get()</entry></row>
|
|
||||||
<row><entry>gconf_client_get_bool()</entry><entry>g_settings_get_boolean()</entry></row>
|
|
||||||
<row><entry>gconf_client_set_bool()</entry><entry>g_settings_set_boolean()</entry></row>
|
|
||||||
<row><entry>gconf_client_get_int()</entry><entry>g_settings_get_int()</entry></row>
|
|
||||||
<row><entry>gconf_client_set_int()</entry><entry>g_settings_set_int()</entry></row>
|
|
||||||
<row><entry>gconf_client_get_float()</entry><entry>g_settings_get_double()</entry></row>
|
|
||||||
<row><entry>gconf_client_set_float()</entry><entry>g_settings_set_double()</entry></row>
|
|
||||||
<row><entry>gconf_client_get_string()</entry><entry>g_settings_get_string()</entry></row>
|
|
||||||
<row><entry>gconf_client_set_string()</entry><entry>g_settings_set_string()</entry></row>
|
|
||||||
<row><entry>gconf_client_get_list()</entry><entry>for string lists, see g_settings_get_strv(), else see g_settings_get_value() and #GVariant API</entry></row>
|
|
||||||
<row><entry>gconf_client_set_list()</entry><entry>for string lists, see g_settings_set_strv(), else see g_settings_set_value() and #GVariant API</entry></row>
|
|
||||||
<row><entry>gconf_entry_get_is_writable()</entry><entry>g_settings_is_writable()</entry></row>
|
|
||||||
<row><entry>gconf_client_notify_add()</entry><entry>not required, the #GSettings::changed signal is emitted automatically</entry></row>
|
|
||||||
<row><entry>gconf_client_add_dir()</entry><entry>not required, each GSettings instance automatically watches all keys in its path</entry></row>
|
|
||||||
<row><entry>#GConfChangeSet</entry><entry>g_settings_delay(), g_settings_apply()</entry></row>
|
|
||||||
<row><entry>gconf_client_get_default_from_schema()</entry><entry>no equivalent, applications are expected to know their schema</entry></row>
|
|
||||||
<row><entry>gconf_client_all_entries()</entry><entry>no equivalent, applications are expected to know their schema, and GSettings does not allow schema-less entries</entry></row>
|
|
||||||
<row><entry>gconf_client_get_without_default()</entry><entry>no equivalent</entry></row>
|
|
||||||
<row><entry>gconf_bridge_bind_property()</entry><entry>g_settings_bind()</entry></row>
|
|
||||||
<row><entry>gconf_bridge_bind_property_full()</entry><entry>g_settings_bind_with_mapping()</entry></row>
|
|
||||||
</tbody>
|
|
||||||
</tgroup>
|
|
||||||
</table>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
GConfBridge was a third-party library that used GConf to bind an object property
|
|
||||||
to a particular configuration key. GSettings offers this service itself.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
There is a pattern that is sometimes used for GConf, where a setting can have
|
|
||||||
explicit 'value A', explicit 'value B' or 'use the system default'. With GConf,
|
|
||||||
'use the system default' is sometimes implemented by unsetting the user value.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This is not possible in GSettings, since it does not have API to determine if a value
|
|
||||||
is the default and does not let you unset values. The recommended way (and much
|
|
||||||
clearer) way in which this can be implemented in GSettings is to have a separate
|
|
||||||
'use-system-default' boolean setting.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Change notification</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
GConf requires you to call gconf_client_add_dir() and
|
|
||||||
gconf_client_notify_add() to get change notification. With
|
|
||||||
GSettings, this is not necessary; signals get emitted automatically
|
|
||||||
for every change.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The #GSettings::changed signal is emitted for each changed key.
|
|
||||||
There is also a #GSettings::change-event signal that you can handle
|
|
||||||
if you need to see groups of keys that get changed at the same time.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
GSettings also notifies you about changes in writability of keys,
|
|
||||||
with the #GSettings::writable-changed signal (and the
|
|
||||||
#GSettings::writable-change-event signal).
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section><title>Change sets</title>
|
|
||||||
<para>
|
|
||||||
GConf has a concept of a set of changes which can be applied or reverted
|
|
||||||
at once: #GConfChangeSet (GConf doesn't actually apply changes atomically,
|
|
||||||
which is one of its shortcomings).
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Instead of a separate object to represent a change set, GSettings has a
|
|
||||||
'delayed-apply' mode, which can be turned on for a GSettings object by
|
|
||||||
calling g_settings_delay(). In this mode, changes done to the GSettings
|
|
||||||
object are not applied - they are still visible when calling g_settings_get()
|
|
||||||
<emphasis>on the same object</emphasis>, but not to other GSettings instances
|
|
||||||
or even other processes.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To apply the pending changes all at once (GSettings <emphasis>does</emphasis>
|
|
||||||
atomicity here), call g_settings_apply(). To revert the pending changes,
|
|
||||||
call g_settings_revert() or just drop the reference to the #GSettings object.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Schema conversion</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
If you are porting your application from GConf, most likely you already
|
|
||||||
have a GConf schema. GConf comes with a commandline tool
|
|
||||||
gsettings-schema-convert that can help with the task of converting
|
|
||||||
a GConf schema into an equivalent GSettings schema. The tool is not
|
|
||||||
perfect and may need assistance in some cases.
|
|
||||||
</para>
|
|
||||||
<example><title>An example for using gsettings-schema-convert</title>
|
|
||||||
<para>Running <userinput>gsettings-schema-convert --gconf --xml --schema-id "org.gnome.font-rendering" --output org.gnome.font-rendering.gschema.xml destop_gnome_font_rendering.schemas</userinput> on the following <filename>desktop_gnome_font_rendering.schemas</filename> file:
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
<?xml version="1.0"?>
|
|
||||||
<gconfschemafile>
|
|
||||||
<schemalist>
|
|
||||||
<schema>
|
|
||||||
<key>/schemas/desktop/gnome/font_rendering/dpi</key>
|
|
||||||
<applyto>/desktop/gnome/font_rendering/dpi</applyto>
|
|
||||||
<owner>gnome</owner>
|
|
||||||
<type>int</type>
|
|
||||||
<default>96</default>
|
|
||||||
<locale name="C">
|
|
||||||
<short>DPI</short>
|
|
||||||
<long>The resolution used for converting font sizes to pixel sizes, in dots per inch.</long>
|
|
||||||
</locale>
|
|
||||||
</schema>
|
|
||||||
</schemalist>
|
|
||||||
</gconfschemafile>
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
produces a <filename>org.gnome.font-rendering.gschema.xml</filename> file with the following content:
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
<schemalist>
|
|
||||||
<schema id="org.gnome.font-rendering" path="/desktop/gnome/font_rendering/">
|
|
||||||
<key name="dpi" type="i">
|
|
||||||
<default>96</default>
|
|
||||||
<summary>DPI</summary>
|
|
||||||
<description>The resolution used for converting font sizes to pixel sizes, in dots per inch.</description>
|
|
||||||
</key>
|
|
||||||
</schema>
|
|
||||||
</schemalist>
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
</example>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
GSettings schemas are identified at runtime by their id (as specified
|
|
||||||
in the XML source file). It is recommended to use a dotted name as schema
|
|
||||||
id, similar in style to a D-Bus bus name, e.g. "org.gnome.SessionManager".
|
|
||||||
In cases where the settings are general and not specific to one application,
|
|
||||||
the id should not use StudlyCaps, e.g. "org.gnome.font-rendering".
|
|
||||||
The filename used for the XML schema source is immaterial, but
|
|
||||||
schema compiler expects the files to have the extension
|
|
||||||
<filename>.gschema.xml</filename>. It is recommended to simply
|
|
||||||
use the schema id as the filename, followed by this extension,
|
|
||||||
e.g. <filename>org.gnome.SessionManager.gschema.xml</filename>.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The XML source file for your GSettings schema needs to get installed
|
|
||||||
into <filename>$datadir/glib-2.0/schemas</filename>, and needs to be
|
|
||||||
compiled into a binary form. At runtime, GSettings looks for compiled
|
|
||||||
schemas in the <filename>glib-2.0/schemas</filename> subdirectories
|
|
||||||
of all <envar>XDG_DATA_DIRS</envar> directories, so if you install
|
|
||||||
your schema in a different location, you need to set the
|
|
||||||
<envar>XDG_DATA_DIRS</envar> environment variable appropriately.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Schemas are compiled into binary form by the
|
|
||||||
<link linkend="glib-compile-schemas">glib-compile-schemas</link> utility.
|
|
||||||
GIO provides a <literal>glib_compile_schemas</literal>
|
|
||||||
variable for the schema compiler.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
You can ignore all of this by using the provided m4 macros. To
|
|
||||||
do this, add to your <filename>configure.ac</filename>:
|
|
||||||
<programlisting>
|
|
||||||
GLIB_GSETTINGS
|
|
||||||
</programlisting>
|
|
||||||
The corresponding <filename>Makefile.am</filename> fragment looks like
|
|
||||||
this:
|
|
||||||
<programlisting>
|
|
||||||
# gsettings_SCHEMAS is a list of all the schemas you want to install
|
|
||||||
gsettings_SCHEMAS = my.app.gschema.xml
|
|
||||||
|
|
||||||
# include the appropriate makefile rules for schema handling
|
|
||||||
@GSETTINGS_RULES@
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
This is not sufficient on its own. You need to mention what the source
|
|
||||||
of the <filename>my.app.gschema.xml</filename> file is. If the schema
|
|
||||||
file is distributed directly with your project's tarball then a mention
|
|
||||||
in <varname>EXTRA_DIST</varname> is appropriate. If the schema file is
|
|
||||||
generated from another source then you will need the appropriate rule
|
|
||||||
for that, plus probably an item in <varname>EXTRA_DIST</varname> for the
|
|
||||||
source files used by that rule.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
One possible pitfall in doing schema conversion is that the default
|
|
||||||
values in GSettings schemas are parsed by the #GVariant parser.
|
|
||||||
This means that strings need to include quotes in the XML. Also note
|
|
||||||
that the types are now specified as #GVariant type strings.
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
<type>string</type>
|
|
||||||
<default>rgb</default>
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
becomes
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
<key name="rgba-order" type="s">
|
|
||||||
<default>'rgb'</default> <!-- note quotes -->
|
|
||||||
</key>
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Another possible complication is that GConf specifies full paths
|
|
||||||
for each key, while a GSettings schema has a 'path' attribute that
|
|
||||||
contains the prefix for all the keys in the schema, and individual
|
|
||||||
keys just have a simple name. So
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
<key>/schemas/desktop/gnome/font_rendering/antialiasing</key>
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
becomes
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
<schema id="org.gnome.font" path="/desktop/gnome/font_rendering/">
|
|
||||||
<key name="antialiasing" type="s">
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Default values can be localized in both GConf and GSettings schemas,
|
|
||||||
but GSettings uses gettext for the localization. You can specify
|
|
||||||
the gettext domain to use in the <tag class="attribute">gettext-domain</tag>
|
|
||||||
attribute. Therefore, when converting localized defaults in GConf,
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
<key>/schemas/apps/my_app/font_size</key>
|
|
||||||
<locale name="C">
|
|
||||||
<default>18</default>
|
|
||||||
</locale>
|
|
||||||
<locale name="be">
|
|
||||||
<default>24</default>
|
|
||||||
</locale>
|
|
||||||
</key>
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
becomes
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
<schema id="..." gettext-domain="your-domain">
|
|
||||||
...
|
|
||||||
<key name="font-size" type="i">
|
|
||||||
<default l10n="messages" context="font_size">18</default>
|
|
||||||
</key>
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
GSettings uses gettext for translation of default values.
|
|
||||||
The string that is translated is exactly the string that appears
|
|
||||||
inside of the <tag class='starttag'>default</tag> element. This
|
|
||||||
includes the quotation marks that appear around strings.
|
|
||||||
Default values must be marked with the <varname>l10n</varname>
|
|
||||||
attribute in the <tag class='starttag'>default</tag> tag, which
|
|
||||||
should be set as equal to <literal>'messages'</literal> or
|
|
||||||
<literal>'time'</literal> depending on the desired category. An
|
|
||||||
optional translation context can also be specified with the
|
|
||||||
<varname>context</varname> attribute, as in the example. This
|
|
||||||
is usually recommended, since the string "<literal>18</literal>"
|
|
||||||
is not particularly easy to translate without context. The
|
|
||||||
translated version of the default value should be stored in the
|
|
||||||
specified <varname>gettext-domain</varname>. Care must be taken
|
|
||||||
during translation to ensure that all translated values remain
|
|
||||||
syntactically valid; mistakes here will cause runtime errors.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
GSettings schemas have optional <tag class="starttag">summary</tag> and
|
|
||||||
<tag class="starttag">description</tag> elements for each key which
|
|
||||||
correspond to the <tag class="starttag">short</tag> and
|
|
||||||
<tag class="starttag">long</tag> elements in the GConf schema and
|
|
||||||
will be used in similar ways by a future gsettings-editor, so you
|
|
||||||
should use the same conventions for them: The summary is just a short
|
|
||||||
label with no punctuation, the description can be one or more complete
|
|
||||||
sentences. If multiple paragraphs are desired for the description, the
|
|
||||||
paragraphs should be separated by a completely empty line.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Translations for these strings will also be handled
|
|
||||||
via gettext, so you should arrange for these strings to be
|
|
||||||
extracted into your gettext catalog. One way to do that is to use
|
|
||||||
intltool. Since intltool 0.50.1, schema files are
|
|
||||||
supported, so all you have to do is to add your .gschema.xml
|
|
||||||
files to <filename>POTFILES.in</filename> with a line like
|
|
||||||
<programlisting>
|
|
||||||
[type: gettext/gsettings]data/org.foo.MyApp.gschema.xml
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
GSettings is a bit more restrictive about key names than GConf. Key
|
|
||||||
names in GSettings can be at most 32 characters long, and must only
|
|
||||||
consist of lowercase characters, numbers and dashes, with no
|
|
||||||
consecutive dashes. The first character must not be a number or dash,
|
|
||||||
and the last character cannot be '-'.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
If you are using the GConf backend for GSettings during the
|
|
||||||
transition, you may want to keep your key names the same they
|
|
||||||
were in GConf, so that existing settings in the users GConf
|
|
||||||
database are preserved. You can achieve this by using the
|
|
||||||
<option>--allow-any-name</option> with the
|
|
||||||
<link linkend="glib-compile-schemas">glib-compile-schemas</link> schema
|
|
||||||
compiler. Note that this option is only meant
|
|
||||||
to ease the process of porting your application, allowing parts
|
|
||||||
of your application to continue to access GConf and parts to use
|
|
||||||
GSettings. By the time you have finished porting your application
|
|
||||||
you must ensure that all key names are valid.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section><title>Data conversion</title>
|
|
||||||
<para>
|
|
||||||
GConf comes with a GSettings backend that can be used to
|
|
||||||
facility the transition to the GSettings API until you are
|
|
||||||
ready to make the jump to a different backend (most likely
|
|
||||||
dconf). To use it, you need to set the <envar>GSETTINGS_BACKEND</envar>
|
|
||||||
to 'gconf', e.g. by using
|
|
||||||
<programlisting>
|
|
||||||
g_setenv ("GSETTINGS_BACKEND", "gconf", TRUE);
|
|
||||||
</programlisting>
|
|
||||||
early on in your program. Note that this backend is meant purely
|
|
||||||
as a transition tool, and should not be used in production.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
GConf also comes with a utility called
|
|
||||||
<command>gsettings-data-convert</command>, which is designed to help
|
|
||||||
with the task of migrating user settings from GConf into another
|
|
||||||
GSettings backend. It can be run manually, but it is designed to be
|
|
||||||
executed automatically, every time a user logs in. It keeps track of
|
|
||||||
the data migrations that it has already done, and it is harmless to
|
|
||||||
run it more than once.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To make use of this utility, you must install a keyfile in the
|
|
||||||
directory <filename>/usr/share/GConf/gsettings</filename> which
|
|
||||||
lists the GSettings keys and GConf paths to map to each other, for
|
|
||||||
each schema that you want to migrate user data for.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Here is an example:
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
[org.gnome.fonts]
|
|
||||||
antialiasing = /desktop/gnome/font_rendering/antialiasing
|
|
||||||
dpi = /desktop/gnome/font_rendering/dpi
|
|
||||||
hinting = /desktop/gnome/font_rendering/hinting
|
|
||||||
rgba-order = /desktop/gnome/font_rendering/rgba_order
|
|
||||||
|
|
||||||
[apps.myapp:/path/to/myapps/]
|
|
||||||
some-odd-key1 = /apps/myapp/some_ODD-key1
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
The last key demonstrates that it may be necessary to modify the key
|
|
||||||
name to comply with stricter GSettings key name rules. Of course,
|
|
||||||
that means your application must use the new key names when looking
|
|
||||||
up settings in GSettings.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The last group in the example also shows how to handle the case
|
|
||||||
of 'relocatable' schemas, which don't have a fixed path. You can
|
|
||||||
specify the path to use in the group name, separated by a colon.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
There are some limitations: <command>gsettings-data-convert</command>
|
|
||||||
does not do any transformation of the values. And it does not handle
|
|
||||||
complex GConf types other than lists of strings or integers.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Don't forget to require GConf 2.31.1 or newer in your configure
|
|
||||||
script if you are making use of the GConf backend or the conversion
|
|
||||||
utility.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
If, as an application developer, you are interested in manually
|
|
||||||
ensuring that <command>gsettings-data-convert</command> has been
|
|
||||||
invoked (for example, to deal with the case where the user is
|
|
||||||
logged in during a distribution upgrade or for non-XDG desktop
|
|
||||||
environments which do not run the command as an autostart) you
|
|
||||||
may invoke it manually during your program initialisation. This
|
|
||||||
is not recommended for all application authors -- it is your
|
|
||||||
choice if this use case concerns you enough.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Internally, <command>gsettings-data-convert</command> uses a
|
|
||||||
keyfile to track which settings have been migrated. The
|
|
||||||
following code fragment will check that keyfile to see if your
|
|
||||||
data conversion script has been run yet and, if not, will
|
|
||||||
attempt to invoke the tool to run it. You should adapt it to
|
|
||||||
your application as you see fit.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
static void
|
|
||||||
ensure_migrated (const gchar *name)
|
|
||||||
{
|
|
||||||
gboolean needed = TRUE;
|
|
||||||
GKeyFile *kf;
|
|
||||||
gchar **list;
|
|
||||||
gsize i, n;
|
|
||||||
|
|
||||||
kf = g_key_file_new ();
|
|
||||||
|
|
||||||
g_key_file_load_from_data_dirs (kf, "gsettings-data-convert",
|
|
||||||
NULL, G_KEY_FILE_NONE, NULL);
|
|
||||||
list = g_key_file_get_string_list (kf, "State", "converted", &n, NULL);
|
|
||||||
|
|
||||||
if (list)
|
|
||||||
{
|
|
||||||
for (i = 0; i < n; i++)
|
|
||||||
if (strcmp (list[i], name) == 0)
|
|
||||||
{
|
|
||||||
needed = FALSE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_strfreev (list);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_key_file_free (kf);
|
|
||||||
|
|
||||||
if (needed)
|
|
||||||
g_spawn_command_line_sync ("gsettings-data-convert",
|
|
||||||
NULL, NULL, NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Although there is the possibility that the
|
|
||||||
<command>gsettings-data-convert</command> script will end up
|
|
||||||
running multiple times concurrently with this approach, it is
|
|
||||||
believed that this is safe.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
Loading…
Reference in New Issue
Block a user