GSettings 简介

2019-08-04  本文已影响0人  jouyouyun

GSettings 实际上是一套可使用多个 storage backendsAPI ,默认使用 dconf 作为 backend ,也可以使用 keyfile 作为 backend

但由于 gio 提供了 GKeyFile 结构来处理 keyfile 文件,所以解析 keyfile 文件时很少通过 GSettings API ,在这里只介绍使用 dconf 作为 backend 的使用方法。


dconf

dconf 是一个底层的配置管理系统,被设计用来作为 GSettingsbackend ,并提供了图形化的配置管理工具 dconf-editor ,具有以下特点:


配置文件

GSettings 的配置文件是 xml 格式的,文件需以 .gschema.xml 结尾,文件名通常与 id 相同。配置文件安装在 /usr/share/glib-2.0/schemas/ 目录下,手动添加进去的文件需要执行 sudo glib-complie-schemas /usr/share/glib-2.0/schemas 让其生效。

文件内容简要格式如下:

<?xml version="1.0" encoding="UTF-8"?>
<schemalist>
    <schema path="" id="">
        <key type=""  name="">
            <default></default>
            <summary></summary>
            <description></description>
        </key>
    </schema>
</schemalist>

可以看到一个文件里可以包含多个 schema ,每个 schema 可由多个 key 组成。详细说明如下:


下面给出一个例子:

schema 文件:

<?xml version="1.0" encoding="UTF-8"?>
<schemalist>
    <enum id="com.deepin.test.LogLevel">
        <value nick="debug" value="1" />
        <value nick="info" value="2" />
        <value nick="fatal" value="3" />
    </enum>

    <schema path="/com/deepin/test/" id="com.deepin.test">
        <key type="b"  name="enabled">
            <default>true</default>
            <summary>Enable this module.</summary>
            <description>Whether enable this module.</description>
        </key>
        <key enum="com.deepin.test.LogLevel" name="loglevel">
            <default>'info'</default>
            <summary>Log level.</summary>
            <description>Log level.</description>
        </key>
        <key type="i" name="interval">
            <default>10</default>
            <range min="0" max="60" />
            <summary>Timer duration.</summary>
            <description>Timer duration.</description>
        </key>
        <key type="(ii)" name="size">
            <default>(800,600)</default>
            <summary>The window size.</summary>
            <description>The window size.</description>
        </key>
    </schema>
</schemalist>

程序代码如下:

/**
 * Copyright (C) 2019 jouyouyun <jouyouwen717@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * example.c -- An example for gsettings.
 *
 * compile:
 *    gcc -Wall -g example.c `pkg-config --libs --cflags gio-2.0`
 *
 */
#include <gio/gio.h>

int
main(int argc, char *argv[])
{
    GSettings *gs;
    gboolean enabled;
    gint loglevel, interval, width, height;

    // if failed, will segmetfault
    gs = g_settings_new("com.deepin.test");

    enabled = g_settings_get_boolean(gs, "enabled");
    g_print("Enabled: %d\n", enabled);

    loglevel = g_settings_get_enum(gs, "loglevel");
    g_print("Log level: %d\n", loglevel);

    interval = g_settings_get_int(gs, "interval");
    g_print("Timer duration: %d\n", interval);

    g_settings_get(gs, "size", "(ii)", &width, &height);
    g_print("Width: %d, height: %d\n", width, height);

    g_object_unref(gs);
    return 0;
}

注意: 在使用接口调用时,需要确保 schemakey 存在,不然会触发 段错误


Relocatable Schema

通常一个 id 对应一个固定的 path ,但也可以没有,即不设置 path ,这样就是一个可重定位的 schema 。这个特性对于可变的配置很有用,如用户自定义的快捷键:快捷键的个数是不可知,这时可利用这个特性先声明一个快捷键 schema 作为模板,然后动态创建多个 path 来使用。示例如下:

schema 文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<schemalist>
    <schema id="com.deepin.test.keybind">
        <key type="s"  name="name">
            <default>''</default>
            <summary>Shortcut name.</summary>
            <description>Shortcut name.</description>
        </key>
        <key type="as"  name="shortcuts">
            <default>['']</default>
            <summary>Shortcut keys.</summary>
            <description>Shortcut keys.</description>
        </key>
        <key type="s"  name="action">
            <default>''</default>
            <summary>Shortcut action.</summary>
            <description>Shortcut action.</description>
        </key>
        <key type="s"  name="description">
            <default>''</default>
            <summary>Shortcut description.</summary>
            <description>Shortcut description.</description>
        </key>
    </schema>
</schemalist>

程序代码如下:

/**
 * Copyright (C) 2019 jouyouyun <jouyouwen717@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * relocatable.c -- An example for gsettings relocatable path.
 *
 * compile:
 *    gcc -Wall -g relocatable.c `pkg-config --libs --cflags gio-2.0`
 */

#include <stdio.h>
#include <gio/gio.h>

static void set_keybind(GSettings *gs);
static void get_keybind(GSettings *gs);

static void
set_keybind(GSettings *gs)
{
    gboolean ok;

    ok = g_settings_set_string(gs, "name", "test");
    if (!ok) {
        g_warning("Failed to set name to 'test'");
    }

    const gchar *shortcuts[] = {"Control-Alt-T", "Super-T", NULL};
    ok = g_settings_set_strv(gs, "shortcuts", shortcuts);
    if (!ok) {
        g_warning("Failed to set shortcuts");
    }
    ok = g_settings_set_string(gs, "action", "terminator");
    if (!ok) {
        g_warning("Failed to set action to 'terminator'");
    }
    ok = g_settings_set_string(gs, "description", "the shortcuts for terminator");
    if (!ok) {
        g_warning("Failed to set description to 'the shortcuts for terminator'");
    }
}

static void
get_keybind(GSettings *gs)
{
    gchar *name, *action, *desc;
    gchar **shortcuts = NULL;

    name = g_settings_get_string(gs, "name");
    if (name) {
        g_print("Shortcut name: %s\n", name);
        g_free(name);
    }

    shortcuts = g_settings_get_strv(gs, "shortcuts");
    if (shortcuts) {
        int i = 0;
        g_print("Shortcut key: ");
        for (; shortcuts[i]; i++) {
            if (i != 0) {
                g_print(", ");
            }
            g_print("%s", shortcuts[i]);
            g_free(shortcuts[i]);
        }
        g_print("\n");
        g_free(shortcuts);
    }

    action = g_settings_get_string(gs, "action");
    if (action) {
        g_print("Shortcut action: %s\n", action);
        g_free(action);
    }

    desc = g_settings_get_string(gs, "description");
    if (desc) {
        g_print("Shortcut desc: %s\n", desc);
        g_free(desc);
    }
}

int
main(int argc, char *argv[])
{
    if (argc != 3) {
        g_print("Usage: %s <action> <keybind id>\n"
                "\taction: get or set\n"
                "\tkeybind id: a non-negative integer\n", argv[0]);
        return 0;
    }

    GSettings *gs;
    gchar buf[1024] = {0};

    if (sprintf(buf, "/com/deepin/test/keybind/%s/", argv[2]) < 0) {
        g_error("Failed to combains path: %s\n", argv[2]);
        return -1;
    }
    gs = g_settings_new_with_path("com.deepin.test.keybind", buf);

    if (g_strcmp0(argv[1], "set") == 0) {
        set_keybind(gs);
    } else if (g_strcmp0(argv[1], "get") == 0) {
        get_keybind(gs);
    } else {
        g_warning("invalid action: %s", argv[1]);
    }

    g_object_unref(gs);
    g_settings_sync();
    return 0;
}

override

gsettings 支持 override 机制,可以更改默认值。

通常 key 的默认值在文件中已经指定,但有时不同的版本上需要的默认值不同,这时 override 机制就很有用,可以在不修改配置文件的情况下更改默认值。

override 文件以 数字_ 开头,并以 .gschema.override 结尾,数字为两位整数,数值越大优先级越高。

override 文件同样安装在 /usr/share/glib-2.0/schemas 目录下,并需要使用 glib-compile-schemas 编译。

override 文件的格式如下:

[schema id]
key=value

如更改 com.deepin.testinterval 的默认值为 30 ,则内容如下:

[com.deepin.test]
interval=30

然后执行:

sudo cp ./90_com.deepin.test.gschema.override /usr/share/glib-2.0/schemas/
sudo glib-compile-schemas /usr/share/glib-2.0/schemas

key 改变信号

GSettings 提供了 changed 信号来发送 key 改变的事件,如有需要可监听此信号。


工具

glib-sompile-schemas {#glib-sompile-schemas}

编译 schema 文件的命令

dconf-editor {#dconf-editor}

dconf 的图形工具,根据 path 检索,可管理 key

devhelp

一款 API 文档查看工具,安装了 libglib2.0-docs 后,可在 devhelp 中查看 GSettingsAPI 文档

gsettings

这是一个 gsettings 的配置管理工具,下面介绍一些常用的子命令,详细用法请查看 man 手册:


参考资料

上一篇 下一篇

猜你喜欢

热点阅读