Schema conversion: GIO Reference Manual

## 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 assistence in some cases.

Example 1. 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 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 a `org.gnome.font-rendering.gschema.xml` file with the following content:

    <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 for the schema compiler.

You can ignore all of this by using the provided m4 macros. To do this, add to your `configure.ac`:

    GLIB_GSETTINGS

The corresponding `Makefile.am` fragment looks like this:

    # 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.

    <type>string</type>
    <default>rgb</default>

becomes

    <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

    <key>/schemas/desktop/gnome/font_rendering/antialiasing</key>

becomes

    <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,

    <key>/schemas/apps/my_app/font_size</key>
      <locale name="C">
        <default>18</default>
      </locale>
      <locale name="be">
        <default>24</default>
      </locale>
    </key>

becomes

    <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 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.

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 `POTFILES.in` with a line like

            [type: gettext/gsettings]data/org.foo.MyApp.gschema.xml

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.