Blame conf/gconf/config.c

Packit 3ff832
/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
Packit 3ff832
/* vim:set et sts=4: */
Packit 3ff832
Packit 3ff832
#include <string.h>
Packit 3ff832
#include <ibus.h>
Packit 3ff832
#include "config.h"
Packit 3ff832
Packit 3ff832
#define GCONF_PREFIX "/desktop/ibus"
Packit 3ff832
Packit 3ff832
struct _IBusConfigGConf {
Packit 3ff832
    IBusConfigService parent;
Packit 3ff832
    GConfClient *client;
Packit 3ff832
};
Packit 3ff832
Packit 3ff832
struct _IBusConfigGConfClass {
Packit 3ff832
    IBusConfigServiceClass parent;
Packit 3ff832
Packit 3ff832
};
Packit 3ff832
Packit 3ff832
/* functions prototype */
Packit 3ff832
static void         ibus_config_gconf_class_init    (IBusConfigGConfClass   *class);
Packit 3ff832
static void         ibus_config_gconf_init          (IBusConfigGConf        *config);
Packit 3ff832
static void         ibus_config_gconf_destroy       (IBusConfigGConf        *config);
Packit 3ff832
static gboolean     ibus_config_gconf_set_value     (IBusConfigService      *config,
Packit 3ff832
                                                     const gchar            *section,
Packit 3ff832
                                                     const gchar            *name,
Packit 3ff832
                                                     GVariant               *value,
Packit 3ff832
                                                     GError                **error);
Packit 3ff832
static GVariant    *ibus_config_gconf_get_value     (IBusConfigService      *config,
Packit 3ff832
                                                     const gchar            *section,
Packit 3ff832
                                                     const gchar            *name,
Packit 3ff832
                                                     GError                **error);
Packit 3ff832
static GVariant    *ibus_config_gconf_get_values    (IBusConfigService      *config,
Packit 3ff832
                                                     const gchar            *section,
Packit 3ff832
                                                     GError                **error);
Packit 3ff832
static gboolean     ibus_config_gconf_unset_value   (IBusConfigService      *config,
Packit 3ff832
                                                     const gchar            *section,
Packit 3ff832
                                                     const gchar            *name,
Packit 3ff832
                                                     GError                **error);
Packit 3ff832
static GConfValue   *_to_gconf_value                (GVariant               *value);
Packit 3ff832
static GVariant     *_from_gconf_value              (const GConfValue       *gvalue);
Packit 3ff832
Packit 3ff832
G_DEFINE_TYPE (IBusConfigGConf, ibus_config_gconf, IBUS_TYPE_CONFIG_SERVICE)
Packit 3ff832
Packit 3ff832
static void
Packit 3ff832
ibus_config_gconf_class_init (IBusConfigGConfClass *class)
Packit 3ff832
{
Packit 3ff832
    GObjectClass *object_class = G_OBJECT_CLASS (class);
Packit 3ff832
Packit 3ff832
    IBUS_OBJECT_CLASS (object_class)->destroy = (IBusObjectDestroyFunc) ibus_config_gconf_destroy;
Packit 3ff832
    IBUS_CONFIG_SERVICE_CLASS (object_class)->set_value   = ibus_config_gconf_set_value;
Packit 3ff832
    IBUS_CONFIG_SERVICE_CLASS (object_class)->get_value   = ibus_config_gconf_get_value;
Packit 3ff832
    IBUS_CONFIG_SERVICE_CLASS (object_class)->get_values  = ibus_config_gconf_get_values;
Packit 3ff832
    IBUS_CONFIG_SERVICE_CLASS (object_class)->unset_value = ibus_config_gconf_unset_value;
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
static void
Packit 3ff832
_value_changed_cb (GConfClient     *client,
Packit 3ff832
                   const gchar     *key,
Packit 3ff832
                   GConfValue      *value,
Packit 3ff832
                   IBusConfigGConf *config)
Packit 3ff832
{
Packit 3ff832
    gchar *p, *section, *name;
Packit 3ff832
Packit 3ff832
    g_return_if_fail (key != NULL);
Packit 3ff832
Packit 3ff832
    p = g_strdup (key);
Packit 3ff832
    section = p + sizeof (GCONF_PREFIX);
Packit 3ff832
    name = rindex (p, '/') + 1;
Packit 3ff832
    *(name - 1) = '\0';
Packit 3ff832
    
Packit 3ff832
    GVariant *variant;
Packit 3ff832
    if (value) {
Packit 3ff832
        variant = _from_gconf_value (value);
Packit 3ff832
    }
Packit 3ff832
    else {
Packit 3ff832
        /* Use a empty typle for a unset value */
Packit 3ff832
        variant = g_variant_new_tuple (NULL, 0);
Packit 3ff832
    }
Packit 3ff832
    g_return_if_fail (variant != NULL);
Packit 3ff832
    ibus_config_service_value_changed ((IBusConfigService *) config,
Packit 3ff832
                                       section,
Packit 3ff832
                                       name,
Packit 3ff832
                                       variant);
Packit 3ff832
    g_variant_unref (variant);
Packit 3ff832
    g_free (p);
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
static void
Packit 3ff832
ibus_config_gconf_init (IBusConfigGConf *config)
Packit 3ff832
{
Packit 3ff832
    config->client = gconf_client_get_default ();
Packit 3ff832
    gconf_client_add_dir (config->client,
Packit 3ff832
                          GCONF_PREFIX,
Packit 3ff832
                          GCONF_CLIENT_PRELOAD_RECURSIVE,
Packit 3ff832
                          NULL);
Packit 3ff832
    g_signal_connect (config->client, "value-changed", G_CALLBACK (_value_changed_cb), config);
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
static void
Packit 3ff832
ibus_config_gconf_destroy (IBusConfigGConf *config)
Packit 3ff832
{
Packit 3ff832
    if (config->client) {
Packit 3ff832
        g_signal_handlers_disconnect_by_func (config->client, G_CALLBACK (_value_changed_cb), config);
Packit 3ff832
        g_object_unref (config->client);
Packit 3ff832
        config->client = NULL;
Packit 3ff832
    }
Packit 3ff832
Packit 3ff832
    IBUS_OBJECT_CLASS (ibus_config_gconf_parent_class)->destroy ((IBusObject *)config);
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
static GConfValue *
Packit 3ff832
_to_gconf_value (GVariant *value)
Packit 3ff832
{
Packit 3ff832
    GConfValue *gv = NULL;
Packit 3ff832
Packit 3ff832
    switch (g_variant_classify (value)) {
Packit 3ff832
    case G_VARIANT_CLASS_STRING:
Packit 3ff832
        {
Packit 3ff832
            gv = gconf_value_new (GCONF_VALUE_STRING);
Packit 3ff832
            gconf_value_set_string (gv, g_variant_get_string (value, NULL));
Packit 3ff832
        }
Packit 3ff832
        break;
Packit 3ff832
    case G_VARIANT_CLASS_INT32:
Packit 3ff832
        {
Packit 3ff832
            gv = gconf_value_new (GCONF_VALUE_INT);
Packit 3ff832
            gconf_value_set_int (gv, g_variant_get_int32 (value));
Packit 3ff832
        }
Packit 3ff832
        break;
Packit 3ff832
    case G_VARIANT_CLASS_BOOLEAN:
Packit 3ff832
        {
Packit 3ff832
            gv = gconf_value_new (GCONF_VALUE_BOOL);
Packit 3ff832
            gconf_value_set_bool (gv, g_variant_get_boolean (value));
Packit 3ff832
        }
Packit 3ff832
        break;
Packit 3ff832
    case G_VARIANT_CLASS_DOUBLE:
Packit 3ff832
        {
Packit 3ff832
            gv = gconf_value_new (GCONF_VALUE_FLOAT);
Packit 3ff832
            gconf_value_set_float (gv, g_variant_get_double (value));
Packit 3ff832
        }
Packit 3ff832
        break;
Packit 3ff832
    case G_VARIANT_CLASS_ARRAY:
Packit 3ff832
        {
Packit 3ff832
            const GVariantType *element_type = g_variant_type_element (g_variant_get_type (value));
Packit 3ff832
Packit 3ff832
            GConfValueType type = GCONF_VALUE_INVALID;
Packit 3ff832
            if (g_variant_type_equal (element_type, G_VARIANT_TYPE_STRING))
Packit 3ff832
                type = GCONF_VALUE_STRING;
Packit 3ff832
            else if (g_variant_type_equal (element_type, G_VARIANT_TYPE_INT32))
Packit 3ff832
                type = GCONF_VALUE_INT;
Packit 3ff832
            else if (g_variant_type_equal (element_type, G_VARIANT_TYPE_BOOLEAN))
Packit 3ff832
                type = GCONF_VALUE_BOOL;
Packit 3ff832
            else if (g_variant_type_equal (element_type, G_VARIANT_TYPE_DOUBLE))
Packit 3ff832
                type = GCONF_VALUE_FLOAT;
Packit 3ff832
            else
Packit 3ff832
                g_return_val_if_reached (NULL);
Packit 3ff832
Packit 3ff832
            gv = gconf_value_new (GCONF_VALUE_LIST);
Packit 3ff832
            gconf_value_set_list_type (gv, type);
Packit 3ff832
Packit 3ff832
            GSList *elements = NULL;
Packit 3ff832
            GVariantIter iter;
Packit 3ff832
            GVariant *child;
Packit 3ff832
            g_variant_iter_init (&iter, value);
Packit 3ff832
            while ((child = g_variant_iter_next_value (&iter)) != NULL) {
Packit 3ff832
                elements = g_slist_append (elements, _to_gconf_value (child));
Packit 3ff832
                g_variant_unref (child);
Packit 3ff832
            }
Packit 3ff832
            gconf_value_set_list_nocopy (gv, elements);
Packit 3ff832
        }
Packit 3ff832
        break;
Packit 3ff832
    default:
Packit 3ff832
        g_return_val_if_reached (NULL);
Packit 3ff832
    }
Packit 3ff832
Packit 3ff832
    return gv;
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
static GVariant *
Packit 3ff832
_from_gconf_value (const GConfValue *gv)
Packit 3ff832
{
Packit 3ff832
    g_assert (gv != NULL);
Packit 3ff832
Packit 3ff832
    switch (gv->type) {
Packit 3ff832
    case GCONF_VALUE_STRING:
Packit 3ff832
        return g_variant_new_string (gconf_value_get_string (gv));
Packit 3ff832
    case GCONF_VALUE_INT:
Packit 3ff832
        return g_variant_new_int32 (gconf_value_get_int (gv));
Packit 3ff832
    case GCONF_VALUE_FLOAT:
Packit 3ff832
        return g_variant_new_double (gconf_value_get_float (gv));
Packit 3ff832
    case GCONF_VALUE_BOOL:
Packit 3ff832
        return g_variant_new_boolean (gconf_value_get_bool (gv));
Packit 3ff832
    case GCONF_VALUE_LIST:
Packit 3ff832
        {
Packit 3ff832
            GVariantBuilder builder;
Packit 3ff832
            switch (gconf_value_get_list_type (gv)) {
Packit 3ff832
            case GCONF_VALUE_STRING:
Packit 3ff832
                g_variant_builder_init (&builder, G_VARIANT_TYPE("as")); break;
Packit 3ff832
            case GCONF_VALUE_INT:
Packit 3ff832
                g_variant_builder_init (&builder, G_VARIANT_TYPE("ai")); break;
Packit 3ff832
            case GCONF_VALUE_FLOAT:
Packit 3ff832
                g_variant_builder_init (&builder, G_VARIANT_TYPE("ad")); break;
Packit 3ff832
            case GCONF_VALUE_BOOL:
Packit 3ff832
                g_variant_builder_init (&builder, G_VARIANT_TYPE("ab")); break;
Packit 3ff832
                break;
Packit 3ff832
            default:
Packit 3ff832
                g_assert_not_reached ();
Packit 3ff832
            }
Packit 3ff832
Packit 3ff832
            GSList *list = gconf_value_get_list (gv);
Packit 3ff832
            GSList *p = list;
Packit 3ff832
            while (p != NULL) {
Packit 3ff832
                switch (gconf_value_get_list_type (gv)) {
Packit 3ff832
                case GCONF_VALUE_STRING:
Packit 3ff832
                    g_variant_builder_add (&builder, "s", gconf_value_get_string ((GConfValue *)p->data));
Packit 3ff832
                    break;
Packit 3ff832
                case GCONF_VALUE_INT:
Packit 3ff832
                    g_variant_builder_add (&builder, "i", gconf_value_get_int ((GConfValue *)p->data));
Packit 3ff832
                    break;
Packit 3ff832
                case GCONF_VALUE_FLOAT:
Packit 3ff832
                    g_variant_builder_add (&builder, "d", gconf_value_get_float ((GConfValue *)p->data));
Packit 3ff832
                    break;
Packit 3ff832
                case GCONF_VALUE_BOOL:
Packit 3ff832
                    g_variant_builder_add (&builder, "b", gconf_value_get_bool ((GConfValue *)p->data));
Packit 3ff832
                    break;
Packit 3ff832
                default:
Packit 3ff832
                    g_assert_not_reached ();
Packit 3ff832
                }
Packit 3ff832
                p = p->next;
Packit 3ff832
            }
Packit 3ff832
            return g_variant_builder_end (&builder);
Packit 3ff832
        }
Packit 3ff832
    default:
Packit 3ff832
        g_assert_not_reached ();
Packit 3ff832
    }
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
Packit 3ff832
static gboolean
Packit 3ff832
ibus_config_gconf_set_value (IBusConfigService      *config,
Packit 3ff832
                             const gchar            *section,
Packit 3ff832
                             const gchar            *name,
Packit 3ff832
                             GVariant               *value,
Packit 3ff832
                             GError                **error)
Packit 3ff832
{
Packit 3ff832
    gchar *key;
Packit 3ff832
    GConfValue *gv;
Packit 3ff832
Packit 3ff832
    gv = _to_gconf_value (value);
Packit 3ff832
    if (gv == NULL) {
Packit 3ff832
        gchar *str = g_variant_print (value, TRUE);
Packit 3ff832
        g_set_error (error,
Packit 3ff832
                     G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
Packit 3ff832
                     "Can not set config value [%s:%s] to %s.",
Packit 3ff832
                     section, name, str);
Packit 3ff832
        g_free (str);
Packit 3ff832
        return FALSE;
Packit 3ff832
    }
Packit 3ff832
    key = g_strdup_printf (GCONF_PREFIX"/%s/%s", section, name);
Packit 3ff832
    gconf_client_set (((IBusConfigGConf *)config)->client, key, gv, error);
Packit 3ff832
Packit 3ff832
    g_free (key);
Packit 3ff832
    gconf_value_free (gv);
Packit 3ff832
Packit 3ff832
    if (*error != NULL) {
Packit 3ff832
        return FALSE;
Packit 3ff832
    }
Packit 3ff832
    return TRUE;
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
static GVariant *
Packit 3ff832
ibus_config_gconf_get_value (IBusConfigService      *config,
Packit 3ff832
                             const gchar            *section,
Packit 3ff832
                             const gchar            *name,
Packit 3ff832
                             GError                **error)
Packit 3ff832
{
Packit 3ff832
    gchar *key = g_strdup_printf (GCONF_PREFIX"/%s/%s", section, name);
Packit 3ff832
Packit 3ff832
    GConfValue *gv = gconf_client_get (((IBusConfigGConf *) config)->client, key, NULL);
Packit 3ff832
Packit 3ff832
    g_free (key);
Packit 3ff832
Packit 3ff832
    if (gv == NULL) {
Packit 3ff832
        g_set_error (error,
Packit 3ff832
                     G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
Packit 3ff832
                     "Config value [%s:%s] does not exist.", section, name);
Packit 3ff832
        return NULL;
Packit 3ff832
    }
Packit 3ff832
Packit 3ff832
    GVariant *variant = _from_gconf_value (gv);
Packit 3ff832
    gconf_value_free (gv);
Packit 3ff832
Packit 3ff832
    return g_variant_ref_sink (variant);
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
static GVariant *
Packit 3ff832
ibus_config_gconf_get_values (IBusConfigService      *config,
Packit 3ff832
                              const gchar            *section,
Packit 3ff832
                              GError                **error)
Packit 3ff832
{
Packit 3ff832
    gchar *dir = g_strdup_printf (GCONF_PREFIX"/%s", section);
Packit 3ff832
    gint len = strlen(dir) + 1;
Packit 3ff832
    GSList *entries = gconf_client_all_entries (((IBusConfigGConf *) config)->client, dir, NULL);
Packit 3ff832
    g_free (dir);
Packit 3ff832
Packit 3ff832
    GSList *p;
Packit 3ff832
    GVariantBuilder builder;
Packit 3ff832
Packit 3ff832
    g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
Packit 3ff832
    for (p = entries; p != NULL; p = p->next) {
Packit 3ff832
        GConfEntry *entry = (GConfEntry *)p->data;
Packit 3ff832
        if (entry->key != NULL && entry->value != NULL) {
Packit 3ff832
            const gchar *name = entry->key + len;
Packit 3ff832
            GVariant *value = _from_gconf_value (entry->value);
Packit 3ff832
            g_variant_builder_add (&builder, "{sv}", name, value);
Packit 3ff832
        }
Packit 3ff832
        gconf_entry_free (entry);
Packit 3ff832
    }
Packit 3ff832
    g_slist_free (entries);
Packit 3ff832
Packit 3ff832
    return g_variant_builder_end (&builder);
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
static gboolean
Packit 3ff832
ibus_config_gconf_unset_value (IBusConfigService      *config,
Packit 3ff832
                               const gchar            *section,
Packit 3ff832
                               const gchar            *name,
Packit 3ff832
                               GError                **error)
Packit 3ff832
{
Packit 3ff832
    gchar *key = g_strdup_printf (GCONF_PREFIX"/%s/%s", section, name);
Packit 3ff832
Packit 3ff832
    gboolean retval = gconf_client_unset (((IBusConfigGConf *)config)->client, key, error);
Packit 3ff832
    g_free (key);
Packit 3ff832
Packit 3ff832
    return retval;
Packit 3ff832
}
Packit 3ff832
Packit 3ff832
IBusConfigGConf *
Packit 3ff832
ibus_config_gconf_new (GDBusConnection *connection)
Packit 3ff832
{
Packit 3ff832
    IBusConfigGConf *config;
Packit 3ff832
    config = (IBusConfigGConf *) g_object_new (IBUS_TYPE_CONFIG_GCONF,
Packit 3ff832
                                               "object-path", IBUS_PATH_CONFIG,
Packit 3ff832
                                               "connection", connection,
Packit 3ff832
                                               NULL);
Packit 3ff832
    return config;
Packit 3ff832
}