diff options
author | Peng Huang <shawn.p.huang@gmail.com> | 2011-12-17 15:20:29 -0500 |
---|---|---|
committer | Peng Huang <shawn.p.huang@gmail.com> | 2012-02-21 11:51:51 -0500 |
commit | 303308e397f409e3c74be72eaf307efc2a7cb832 (patch) | |
tree | b9ba7de8ee4df03a285f0a372b6ab3a7d03641ed /conf | |
parent | 07c3d35786349db0f0b561e4ccb5051b71c8b0ed (diff) |
WIP move all conf components into conf dir
Diffstat (limited to 'conf')
-rw-r--r-- | conf/Makefile.am | 47 | ||||
-rw-r--r-- | conf/dconf/Makefile.am | 83 | ||||
-rw-r--r-- | conf/dconf/config.c | 429 | ||||
-rw-r--r-- | conf/dconf/config.h | 47 | ||||
-rw-r--r-- | conf/dconf/dconf.xml.in.in | 12 | ||||
-rw-r--r-- | conf/dconf/main.c | 87 | ||||
-rw-r--r-- | conf/gconf/Makefile.am | 79 | ||||
-rw-r--r-- | conf/gconf/config.c | 346 | ||||
-rw-r--r-- | conf/gconf/config.h | 28 | ||||
-rw-r--r-- | conf/gconf/gconf.xml.in.in | 12 | ||||
-rw-r--r-- | conf/gconf/main.c | 65 | ||||
-rw-r--r-- | conf/memconf/Makefile.am | 76 | ||||
-rw-r--r-- | conf/memconf/config.c | 202 | ||||
-rw-r--r-- | conf/memconf/config.h | 45 | ||||
-rw-r--r-- | conf/memconf/main.c | 83 | ||||
-rw-r--r-- | conf/memconf/memconf.xml.in.in | 11 |
16 files changed, 1652 insertions, 0 deletions
diff --git a/conf/Makefile.am b/conf/Makefile.am new file mode 100644 index 00000000..86127b2f --- /dev/null +++ b/conf/Makefile.am @@ -0,0 +1,47 @@ +# vim:set noet ts=4: +# +# ibus - The Input Bus +# +# Copyright (c) 2007-2010 Peng Huang <shawn.p.huang@gmail.com> +# Copyright (c) 2007-2010 Red Hat, Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place, Suite 330, +# Boston, MA 02111-1307 USA + +if ENABLE_GCONF +GCONF_DIR = \ + gconf \ + $(NULL) +endif + +if ENABLE_MEMCONF +MEMCONF_DIR = \ + memconf \ + $(NULL) +endif + +if ENABLE_DCONF +DCONF_DIR = \ + dconf \ + $(NULL) +endif + +SUBDIRS = \ + $(DCONF_DIR) \ + $(GCONF_DIR) \ + $(MEMCONF_DIR) \ + $(NULL) + +-include $(top_srcdir)/git.mk diff --git a/conf/dconf/Makefile.am b/conf/dconf/Makefile.am new file mode 100644 index 00000000..148ba621 --- /dev/null +++ b/conf/dconf/Makefile.am @@ -0,0 +1,83 @@ +# vim:set noet ts=4: +# +# ibus - The Input Bus +# +# Copyright (c) 2007-2010 Peng Huang <shawn.p.huang@gmail.com> +# Copyright (c) 2007-2010 Red Hat, Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place, Suite 330, +# Boston, MA 02111-1307 USA + +libibus = $(top_builddir)/src/libibus-@IBUS_API_VERSION@.la + +libexec_PROGRAMS = \ + ibus-dconf \ + $(NULL) + +ibus_dconf_SOURCES = \ + main.c \ + config.c \ + config.h \ + $(NULL) +ibus_dconf_CFLAGS = \ + @GLIB2_CFLAGS@ \ + @GIO2_CFLAGS@ \ + @DCONF_CFLAGS@ \ + -DG_LOG_DOMAIN=\"IBUS\" \ + -I$(top_srcdir)/src \ + -I$(top_builddir)/src \ + $(NULL) +ibus_dconf_LDADD = \ + @GOBJECT2_LIBS@ \ + @GLIB2_LIBS@ \ + @GIO2_LIBS@ \ + @DCONF_LIBS@ \ + $(libibus) \ + $(NULL) +ibus_dconf_DEPENDENCIES = \ + $(libibus) \ + $(NULL) + +component_DATA = \ + dconf.xml \ + $(NULL) + +componentdir = $(pkgdatadir)/component + +CLEANFILES = \ + dconf.xml \ + *.pyc \ + $(NULL) + +DISTCLEANFILES = \ + dconf-override-db \ + $(NULL) + +EXTRA_DIST = \ + dconf.xml.in.in \ + $(NULL) + +dconf.xml: dconf.xml.in + $(AM_V_GEN) \ + ( \ + libexecdir=${libexecdir}; \ + s=`cat $<`; \ + eval "echo \"$${s}\""; \ + ) > $@ + +$(libibus): + $(MAKE) -C $(top_builddir)/src + +-include $(top_srcdir)/git.mk diff --git a/conf/dconf/config.c b/conf/dconf/config.c new file mode 100644 index 00000000..02506fba --- /dev/null +++ b/conf/dconf/config.c @@ -0,0 +1,429 @@ +/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com> + * Copyright (C) 2011 Daiki Ueno <ueno@unixuser.org> + * Copyright (C) 2008-2011 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <string.h> +#include <ibus.h> +#include "config.h" + +#define DCONF_PREFIX "/desktop/ibus" +#define DCONF_PRESERVE_NAME_PREFIXES_KEY \ + DCONF_PREFIX"/general/dconf-preserve-name-prefixes" + +struct _IBusConfigDConf { + IBusConfigService parent; + DConfClient *client; + + /* if a dconf path matches one of preserve_name_prefixes, don't convert + key names from/to GSettings key names (see _to_gsettings_name + and _from_gsettings_name) */ + GSList *preserve_name_prefixes; +}; + +struct _IBusConfigDConfClass { + IBusConfigServiceClass parent; +}; + +/* functions prototype */ +static void ibus_config_dconf_class_init (IBusConfigDConfClass *class); +static void ibus_config_dconf_init (IBusConfigDConf *config); +static void ibus_config_dconf_destroy (IBusConfigDConf *config); +static gboolean ibus_config_dconf_set_value (IBusConfigService *config, + const gchar *section, + const gchar *name, + GVariant *value, + GError **error); +static GVariant *ibus_config_dconf_get_value (IBusConfigService *config, + const gchar *section, + const gchar *name, + GError **error); +static GVariant *ibus_config_dconf_get_values (IBusConfigService *config, + const gchar *section, + GError **error); +static gboolean ibus_config_dconf_unset_value (IBusConfigService *config, + const gchar *section, + const gchar *name, + GError **error); + +G_DEFINE_TYPE (IBusConfigDConf, ibus_config_dconf, IBUS_TYPE_CONFIG_SERVICE) + +static void +ibus_config_dconf_class_init (IBusConfigDConfClass *class) +{ + IBusObjectClass *object_class = IBUS_OBJECT_CLASS (class); + IBusConfigServiceClass *config_class = IBUS_CONFIG_SERVICE_CLASS (class); + + object_class->destroy = (IBusObjectDestroyFunc) ibus_config_dconf_destroy; + config_class->set_value = ibus_config_dconf_set_value; + config_class->get_value = ibus_config_dconf_get_value; + config_class->get_values = ibus_config_dconf_get_values; + config_class->unset_value = ibus_config_dconf_unset_value; +} + +static gboolean +_has_prefixes (const gchar *path, GSList *prefixes) +{ + GSList *head = prefixes; + for (; head; head = head->next) { + if (g_str_has_prefix (path, head->data)) { + return TRUE; + } + } + return FALSE; +} + +/* Convert key names from/to GSettings names. While GSettings only + * accepts lowercase letters / numbers / and dash ('-'), IBus uses + * underscore ('_') and some engines even use uppercase letters. + * + * To minimize the gap, we do the following conversion: + * + * - when converting from IBus names to GSettings names, first convert + * all letters to lowercase and then replace underscores with dashes. + * - when converting from GSettings names to IBus names, simply + * replace dashes with underscores. + * + * Note that though the conversion does not always roundtrip, it does + * in most cases. + */ +static gchar * +_to_gsettings_name (const gchar *name) +{ + return g_strcanon (g_ascii_strdown (name, -1), + "abcdefghijklmnopqrstuvwxyz0123456789-", + '-'); +} + +static gchar * +_from_gsettings_name (const gchar *name) +{ + gchar *retval = g_strdup (name), *p; + for (p = retval; *p != '\0'; p++) + if (*p == '-') + *p = '_'; + return retval; +} + +typedef gchar *(* NameConvFunc) (const gchar *); + +static gchar * +_conv_path (const gchar *path, NameConvFunc conv_func) +{ + gchar **strv = g_strsplit (path, "/", -1), **p; + gchar *retval; + + for (p = strv; *p; p++) { + gchar *canon; + canon = (*conv_func) (*p); + g_free (*p); + *p = canon; + } + + retval = g_strjoinv ("/", strv); + g_strfreev (strv); + return retval; +} + +static gchar * +_to_gsettings_path (const gchar *path) +{ + return _conv_path (path, _to_gsettings_name); +} + +static gchar * +_from_gsettings_path (const gchar *gpath) +{ + return _conv_path (gpath, _from_gsettings_name); +} + +static void +_watch_func (DConfClient *client, + const gchar *gpath, + const gchar * const *items, + gint n_items, + const gchar *tag, + IBusConfigDConf *config) +{ + gchar **gkeys = NULL; + gint i; + + g_return_if_fail (gpath != NULL); + g_return_if_fail (n_items >= 0); + + if (dconf_is_key (gpath, NULL)) { + /* If path is a key, the notification should be taken to mean + that one key may have changed. */ + n_items = 1; + gkeys = g_malloc0_n (n_items + 1, sizeof (gchar *)); + gkeys[0] = g_strdup (gpath); + } else { + if (n_items == 0) { + /* If path is a dir and items is empty then it is an + indication that any key under path may have + changed. */ + gkeys = dconf_client_list (config->client, gpath, &n_items); + } else { + gkeys = g_boxed_copy (G_TYPE_STRV, items); + } + for (i = 0; i < n_items; i++) { + gchar *gname = gkeys[i]; + gkeys[i] = g_strdup_printf ("%s/%s", gpath, gname); + g_free (gname); + } + } + + for (i = 0; i < n_items; i++) { + gchar *gname, *path, *name; + GVariant *variant = dconf_client_read (config->client, gkeys[i]); + + if (variant == NULL) { + /* Use a empty tuple for a unset value */ + variant = g_variant_new_tuple (NULL, 0); + } + + gname = strrchr (gkeys[i], '/'); + g_assert (gname); + *gname++ = '\0'; + + if (_has_prefixes (gkeys[i], config->preserve_name_prefixes)) { + path = gkeys[i]; + name = gname; + } else { + path = _from_gsettings_path (gkeys[i]); + name = _from_gsettings_name (gname); + } + + ibus_config_service_value_changed ((IBusConfigService *) config, + path + sizeof (DCONF_PREFIX), + name, + variant); + if (path != gkeys[i]) { + g_free (path); + } + if (name != gname) { + g_free (name); + } + g_variant_unref (variant); + } + g_strfreev (gkeys); +} + +static void +ibus_config_dconf_init (IBusConfigDConf *config) +{ + GVariant *variant; + GError *error; + + config->client = dconf_client_new ("ibus", + (DConfWatchFunc)_watch_func, + config, + NULL); + + error = NULL; + if (!dconf_client_watch (config->client, DCONF_PREFIX"/", NULL, &error)) + g_warning ("Can not watch dconf path %s", DCONF_PREFIX"/"); + + config->preserve_name_prefixes = NULL; + variant = dconf_client_read (config->client, + DCONF_PRESERVE_NAME_PREFIXES_KEY); + if (variant != NULL) { + GVariantIter iter; + GVariant *child; + + g_variant_iter_init (&iter, variant); + while ((child = g_variant_iter_next_value (&iter))) { + char *prefix = g_variant_dup_string (child, NULL); + config->preserve_name_prefixes = + g_slist_prepend (config->preserve_name_prefixes, + prefix); + g_variant_unref (child); + } + g_variant_unref (variant); + } +} + +static void +ibus_config_dconf_destroy (IBusConfigDConf *config) +{ + if (config->client) { + GError *error = NULL; + if (!dconf_client_unwatch (config->client, DCONF_PREFIX"/", NULL, &error)) + g_warning ("Can not unwatch dconf path %s", DCONF_PREFIX"/"); + + g_object_unref (config->client); + config->client = NULL; + } + + g_slist_free_full (config->preserve_name_prefixes, (GDestroyNotify) g_free); + config->preserve_name_prefixes = NULL; + + IBUS_OBJECT_CLASS (ibus_config_dconf_parent_class)-> + destroy ((IBusObject *)config); +} + +static gboolean +ibus_config_dconf_set_value (IBusConfigService *config, + const gchar *section, + const gchar *name, + GVariant *value, + GError **error) +{ + IBusConfigDConf *dconf = IBUS_CONFIG_DCONF (config); + DConfClient *client = dconf->client; + gchar *path, *gpath, *gname, *gkey; + gboolean retval; + + path = g_strdup_printf (DCONF_PREFIX"/%s", section); + gpath = _to_gsettings_path (path); + g_free (path); + + if (_has_prefixes (gpath, dconf->preserve_name_prefixes)) { + gname = (char *) name; + } else { + gname = _to_gsettings_name (name); + } + gkey = g_strconcat (gpath, "/", gname, NULL); + g_free (gpath); + if (gname != name) { + g_free (gname); + } + + retval = dconf_client_write (client, + gkey, + value, + NULL, /* tag */ + NULL, /* cancellable */ + error); + g_free (gkey); + + /* notify the caller that the value has changed, as dconf does not + call watch_func when the caller is the process itself */ + if (retval) { + if (value == NULL) { + /* Use a empty tuple for a unset value */ + value = g_variant_new_tuple (NULL, 0); + } + ibus_config_service_value_changed (config, section, name, value); + } + return retval; +} + +static GVariant * +ibus_config_dconf_get_value (IBusConfigService *config, + const gchar *section, + const gchar *name, + GError **error) +{ + IBusConfigDConf *dconf = IBUS_CONFIG_DCONF (config); + DConfClient *client = dconf->client; + gchar *path, *gpath, *gname, *gkey; + GVariant *variant; + + path = g_strdup_printf (DCONF_PREFIX"/%s", section); + gpath = _to_gsettings_path (path); + g_free (path); + + if (_has_prefixes (gpath, dconf->preserve_name_prefixes)) { + gname = (char *) name; + } else { + gname = _to_gsettings_name (name); + } + gkey = g_strconcat (gpath, "/", gname, NULL); + g_free (gpath); + if (gname != name) { + g_free (gname); + } + + variant = dconf_client_read (client, gkey); + g_free (gkey); + + if (variant == NULL) { + *error = g_error_new (G_DBUS_ERROR, G_DBUS_ERROR_FAILED, + "Config value [%s:%s] does not exist.", section, name); + return NULL; + } + + return variant; +} + +static GVariant * +ibus_config_dconf_get_values (IBusConfigService *config, + const gchar *section, + GError **error) +{ + IBusConfigDConf *dconf = IBUS_CONFIG_DCONF (config); + DConfClient *client = dconf->client; + gchar *dir, *gdir; + gint len; + gchar **entries, **p; + GVariantBuilder *builder; + gboolean preserve_name; + + dir = g_strdup_printf (DCONF_PREFIX"/%s/", section); + gdir = _to_gsettings_path (dir); + g_free (dir); + + preserve_name = _has_prefixes (gdir, dconf->preserve_name_prefixes); + + entries = dconf_client_list (client, gdir, &len); + builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}")); + for (p = entries; *p != NULL; p++) { + gchar *gkey = g_strconcat (gdir, *p, NULL); + GVariant *value = dconf_client_read (client, gkey); + g_free (gkey); + if (value) { + gchar *name = *p; + if (!preserve_name) { + name = _from_gsettings_name (*p); + } + g_variant_builder_add (builder, "{sv}", name, value); + if (name != *p) { + g_free (name); + } + g_variant_unref (value); + } + } + g_strfreev (entries); + g_free (gdir); + + return g_variant_builder_end (builder); +} + +static gboolean +ibus_config_dconf_unset_value (IBusConfigService *config, + const gchar *section, + const gchar *name, + GError **error) +{ + return ibus_config_dconf_set_value (config, section, name, NULL, error); +} + +IBusConfigDConf * +ibus_config_dconf_new (GDBusConnection *connection) +{ + IBusConfigDConf *config; + config = (IBusConfigDConf *) g_object_new (IBUS_TYPE_CONFIG_DCONF, + "object-path", IBUS_PATH_CONFIG, + "connection", connection, + NULL); + return config; +} diff --git a/conf/dconf/config.h b/conf/dconf/config.h new file mode 100644 index 00000000..9f602d6a --- /dev/null +++ b/conf/dconf/config.h @@ -0,0 +1,47 @@ +/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com> + * Copyright (C) 2008-2010 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __CONFIG_DCONF_H__ +#define __CONFIG_DCONF_H__ + +#include <ibus.h> +#include <dconf/dconf.h> + +#define IBUS_TYPE_CONFIG_DCONF \ + (ibus_config_dconf_get_type ()) +#define IBUS_CONFIG_DCONF(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_CONFIG_DCONF, IBusConfigDConf)) +#define IBUS_CONFIG_DCONF_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_CONFIG_DCONF, IBusConfigDConfClass)) +#define IBUS_IS_CONFIG_DCONF(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_CONFIG_DCONF)) +#define IBUS_IS_CONFIG_DCONF_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_CONFIG_DCONF)) +#define IBUS_CONFIG_DCONF_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_CONFIG_DCONF, IBusConfigDConfClass)) + +typedef struct _IBusConfigDConf IBusConfigDConf; +typedef struct _IBusConfigDConfClass IBusConfigDConfClass; + +GType ibus_config_dconf_get_type (void); +IBusConfigDConf *ibus_config_dconf_new (GDBusConnection *connection); + +#endif diff --git a/conf/dconf/dconf.xml.in.in b/conf/dconf/dconf.xml.in.in new file mode 100644 index 00000000..0367008e --- /dev/null +++ b/conf/dconf/dconf.xml.in.in @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- filename: dconf.xml --> +<component> + <name>org.freedesktop.IBus.Config</name> + <description>Dconf Config Component</description> + <exec>${libexecdir}/ibus-dconf</exec> + <version>@VERSION@</version> + <author>Daiki Ueno <ueno@unixuser.org></author> + <license>GPL</license> + <homepage>http://code.google.com/p/ibus</homepage> + <textdomain>ibus</textdomain> +</component> diff --git a/conf/dconf/main.c b/conf/dconf/main.c new file mode 100644 index 00000000..1b69baa3 --- /dev/null +++ b/conf/dconf/main.c @@ -0,0 +1,87 @@ +/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com> + * Copyright (C) 2008-2010 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <ibus.h> +#include <stdlib.h> +#include <locale.h> +#include "config.h" + +static IBusBus *bus = NULL; +static IBusConfigDConf *config = NULL; + +/* options */ +static gboolean ibus = FALSE; +static gboolean verbose = FALSE; + +static const GOptionEntry entries[] = +{ + { "ibus", 'i', 0, G_OPTION_ARG_NONE, &ibus, "component is executed by ibus", + NULL }, + { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "verbose", NULL }, + { NULL }, +}; + + +static void +ibus_disconnected_cb (IBusBus *bus, + gpointer user_data) +{ + ibus_quit (); +} + +static void +ibus_dconf_start (void) +{ + ibus_init (); + bus = ibus_bus_new (); + if (!ibus_bus_is_connected (bus)) { + exit (1); + } + g_signal_connect (bus, "disconnected", G_CALLBACK (ibus_disconnected_cb), + NULL); + config = ibus_config_dconf_new (ibus_bus_get_connection (bus)); + ibus_bus_request_name (bus, IBUS_SERVICE_CONFIG, 0); + ibus_main (); +} + +gint +main (gint argc, gchar **argv) +{ + GError *error = NULL; + GOptionContext *context; + + setlocale (LC_ALL, ""); + + context = g_option_context_new ("- ibus dconf component"); + + g_option_context_add_main_entries (context, entries, "ibus-dconf"); + + if (!g_option_context_parse (context, &argc, &argv, &error)) { + g_print ("Option parsing failed: %s\n", error->message); + exit (-1); + } + + ibus_set_log_handler (verbose); + ibus_dconf_start (); + + return 0; +} diff --git a/conf/gconf/Makefile.am b/conf/gconf/Makefile.am new file mode 100644 index 00000000..cf74a4ab --- /dev/null +++ b/conf/gconf/Makefile.am @@ -0,0 +1,79 @@ +# vim:set noet ts=4: +# +# ibus - The Input Bus +# +# Copyright (c) 2007-2010 Peng Huang <shawn.p.huang@gmail.com> +# Copyright (c) 2007-2010 Red Hat, Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place, Suite 330, +# Boston, MA 02111-1307 USA + +libibus = $(top_builddir)/src/libibus-@IBUS_API_VERSION@.la + +libexec_PROGRAMS = \ + ibus-gconf \ + $(NULL) + +ibus_gconf_SOURCES = \ + main.c \ + config.c \ + config.h \ + $(NULL) +ibus_gconf_CFLAGS = \ + @GLIB2_CFLAGS@ \ + @GIO2_CFLAGS@ \ + @GCONF_CFLAGS@ \ + -DG_LOG_DOMAIN=\"IBUS\" \ + -I$(top_srcdir)/src \ + -I$(top_builddir)/src \ + $(NULL) +ibus_gconf_LDADD = \ + @GOBJECT2_LIBS@ \ + @GLIB2_LIBS@ \ + @GIO2_LIBS@ \ + @GCONF_LIBS@ \ + $(libibus) \ + $(NULL) +ibus_gconf_DEPENDENCIES = \ + $(libibus) \ + $(NULL) + +component_DATA = \ + gconf.xml \ + $(NULL) + +componentdir = $(pkgdatadir)/component + +CLEANFILES = \ + gconf.xml \ + *.pyc \ + $(NULL) + +EXTRA_DIST = \ + gconf.xml.in.in \ + $(NULL) + +gconf.xml: gconf.xml.in + $(AM_V_GEN) \ + ( \ + libexecdir=${libexecdir}; \ + s=`cat $<`; \ + eval "echo \"$${s}\""; \ + ) > $@ + +$(libibus): + $(MAKE) -C $(top_builddir)/src + +-include $(top_srcdir)/git.mk diff --git a/conf/gconf/config.c b/conf/gconf/config.c new file mode 100644 index 00000000..64f1c47d --- /dev/null +++ b/conf/gconf/config.c @@ -0,0 +1,346 @@ +/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ +/* vim:set et sts=4: */ + +#include <string.h> +#include <ibus.h> +#include "config.h" + +#define GCONF_PREFIX "/desktop/ibus" + +struct _IBusConfigGConf { + IBusConfigService parent; + GConfClient *client; +}; + +struct _IBusConfigGConfClass { + IBusConfigServiceClass parent; + +}; + +/* functions prototype */ +static void ibus_config_gconf_class_init (IBusConfigGConfClass *class); +static void ibus_config_gconf_init (IBusConfigGConf *config); +static void ibus_config_gconf_destroy (IBusConfigGConf *config); +static gboolean ibus_config_gconf_set_value (IBusConfigService *config, + const gchar *section, + const gchar *name, + GVariant *value, + GError **error); +static GVariant *ibus_config_gconf_get_value (IBusConfigService *config, + const gchar *section, + const gchar *name, + GError **error); +static GVariant *ibus_config_gconf_get_values (IBusConfigService *config, + const gchar *section, + GError **error); +static gboolean ibus_config_gconf_unset_value (IBusConfigService *config, + const gchar *section, + const gchar *name, + GError **error); +static GConfValue *_to_gconf_value (GVariant *value); +static GVariant *_from_gconf_value (const GConfValue *gvalue); + +G_DEFINE_TYPE (IBusConfigGConf, ibus_config_gconf, IBUS_TYPE_CONFIG_SERVICE) + +static void +ibus_config_gconf_class_init (IBusConfigGConfClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + IBUS_OBJECT_CLASS (object_class)->destroy = (IBusObjectDestroyFunc) ibus_config_gconf_destroy; + IBUS_CONFIG_SERVICE_CLASS (object_class)->set_value = ibus_config_gconf_set_value; + IBUS_CONFIG_SERVICE_CLASS (object_class)->get_value = ibus_config_gconf_get_value; + IBUS_CONFIG_SERVICE_CLASS (object_class)->get_values = ibus_config_gconf_get_values; + IBUS_CONFIG_SERVICE_CLASS (object_class)->unset_value = ibus_config_gconf_unset_value; +} + +static void +_value_changed_cb (GConfClient *client, + const gchar *key, + GConfValue *value, + IBusConfigGConf *config) +{ + gchar *p, *section, *name; + + g_return_if_fail (key != NULL); + + p = g_strdup (key); + section = p + sizeof (GCONF_PREFIX); + name = rindex (p, '/') + 1; + *(name - 1) = '\0'; + + GVariant *variant; + if (value) { + variant = _from_gconf_value (value); + } + else { + /* Use a empty typle for a unset value */ + variant = g_variant_new_tuple (NULL, 0); + } + g_return_if_fail (variant != NULL); + ibus_config_service_value_changed ((IBusConfigService *) config, + section, + name, + variant); + g_variant_unref (variant); + g_free (p); +} + +static void +ibus_config_gconf_init (IBusConfigGConf *config) +{ + config->client = gconf_client_get_default (); + gconf_client_add_dir (config->client, + GCONF_PREFIX, + GCONF_CLIENT_PRELOAD_RECURSIVE, + NULL); + g_signal_connect (config->client, "value-changed", G_CALLBACK (_value_changed_cb), config); +} + +static void +ibus_config_gconf_destroy (IBusConfigGConf *config) +{ + if (config->client) { + g_signal_handlers_disconnect_by_func (config->client, G_CALLBACK (_value_changed_cb), config); + g_object_unref (config->client); + config->client = NULL; + } + + IBUS_OBJECT_CLASS (ibus_config_gconf_parent_class)->destroy ((IBusObject *)config); +} + +static GConfValue * +_to_gconf_value (GVariant *value) +{ + GConfValue *gv = NULL; + + switch (g_variant_classify (value)) { + case G_VARIANT_CLASS_STRING: + { + gv = gconf_value_new (GCONF_VALUE_STRING); + gconf_value_set_string (gv, g_variant_get_string (value, NULL)); + } + break; + case G_VARIANT_CLASS_INT32: + { + gv = gconf_value_new (GCONF_VALUE_INT); + gconf_value_set_int (gv, g_variant_get_int32 (value)); + } + break; + case G_VARIANT_CLASS_BOOLEAN: + { + gv = gconf_value_new (GCONF_VALUE_BOOL); + gconf_value_set_bool (gv, g_variant_get_boolean (value)); + } + break; + case G_VARIANT_CLASS_DOUBLE: + { + gv = gconf_value_new (GCONF_VALUE_FLOAT); + gconf_value_set_float (gv, g_variant_get_double (value)); + } + break; + case G_VARIANT_CLASS_ARRAY: + { + const GVariantType *element_type = g_variant_type_element (g_variant_get_type (value)); + + GConfValueType type = GCONF_VALUE_INVALID; + if (g_variant_type_equal (element_type, G_VARIANT_TYPE_STRING)) + type = GCONF_VALUE_STRING; + else if (g_variant_type_equal (element_type, G_VARIANT_TYPE_INT32)) + type = GCONF_VALUE_INT; + else if (g_variant_type_equal (element_type, G_VARIANT_TYPE_BOOLEAN)) + type = GCONF_VALUE_BOOL; + else if (g_variant_type_equal (element_type, G_VARIANT_TYPE_DOUBLE)) + type = GCONF_VALUE_FLOAT; + else + g_return_val_if_reached (NULL); + + gv = gconf_value_new (GCONF_VALUE_LIST); + gconf_value_set_list_type (gv, type); + + GSList *elements = NULL; + GVariantIter iter; + GVariant *child; + g_variant_iter_init (&iter, value); + while ((child = g_variant_iter_next_value (&iter)) != NULL) { + elements = g_slist_append (elements, _to_gconf_value (child)); + g_variant_unref (child); + } + gconf_value_set_list_nocopy (gv, elements); + } + break; + default: + g_return_val_if_reached (NULL); + } + + return gv; +} + +static GVariant * +_from_gconf_value (const GConfValue *gv) +{ + g_assert (gv != NULL); + + switch (gv->type) { + case GCONF_VALUE_STRING: + return g_variant_new_string (gconf_value_get_string (gv)); + case GCONF_VALUE_INT: + return g_variant_new_int32 (gconf_value_get_int (gv)); + case GCONF_VALUE_FLOAT: + return g_variant_new_double (gconf_value_get_float (gv)); + case GCONF_VALUE_BOOL: + return g_variant_new_boolean (gconf_value_get_bool (gv)); + case GCONF_VALUE_LIST: + { + GVariantBuilder builder; + switch (gconf_value_get_list_type (gv)) { + case GCONF_VALUE_STRING: + g_variant_builder_init (&builder, G_VARIANT_TYPE("as")); break; + case GCONF_VALUE_INT: + g_variant_builder_init (&builder, G_VARIANT_TYPE("ai")); break; + case GCONF_VALUE_FLOAT: + g_variant_builder_init (&builder, G_VARIANT_TYPE("ad")); break; + case GCONF_VALUE_BOOL: + g_variant_builder_init (&builder, G_VARIANT_TYPE("ab")); break; + break; + default: + g_assert_not_reached (); + } + + GSList *list = gconf_value_get_list (gv); + GSList *p = list; + while (p != NULL) { + switch (gconf_value_get_list_type (gv)) { + case GCONF_VALUE_STRING: + g_variant_builder_add (&builder, "s", gconf_value_get_string ((GConfValue *)p->data)); + break; + case GCONF_VALUE_INT: + g_variant_builder_add (&builder, "i", gconf_value_get_int ((GConfValue *)p->data)); + break; + case GCONF_VALUE_FLOAT: + g_variant_builder_add (&builder, "d", gconf_value_get_float ((GConfValue *)p->data)); + break; + case GCONF_VALUE_BOOL: + g_variant_builder_add (&builder, "b", gconf_value_get_bool ((GConfValue *)p->data)); + break; + default: + g_assert_not_reached (); + } + p = p->next; + } + return g_variant_builder_end (&builder); + } + default: + g_assert_not_reached (); + } +} + + +static gboolean +ibus_config_gconf_set_value (IBusConfigService *config, + const gchar *section, + const gchar *name, + GVariant *value, + GError **error) +{ + gchar *key; + GConfValue *gv; + + gv = _to_gconf_value (value); + if (gv == NULL) { + gchar *str = g_variant_print (value, TRUE); + *error = g_error_new (G_DBUS_ERROR, G_DBUS_ERROR_FAILED, + "Can not set config value [%s:%s] to %s.", + section, name, str); + g_free (str); + return FALSE; + } + key = g_strdup_printf (GCONF_PREFIX"/%s/%s", section, name); + gconf_client_set (((IBusConfigGConf *)config)->client, key, gv, error); + + g_free (key); + gconf_value_free (gv); + + if (*error != NULL) { + return FALSE; + } + return TRUE; +} + +static GVariant * +ibus_config_gconf_get_value (IBusConfigService *config, + const gchar *section, + const gchar *name, + GError **error) +{ + gchar *key = g_strdup_printf (GCONF_PREFIX"/%s/%s", section, name); + + GConfValue *gv = gconf_client_get (((IBusConfigGConf *) config)->client, key, NULL); + + g_free (key); + + if (gv == NULL) { + *error = g_error_new (G_DBUS_ERROR, G_DBUS_ERROR_FAILED, + "Config value [%s:%s] does not exist.", section, name); + return NULL; + } + + GVariant *variant = _from_gconf_value (gv); + gconf_value_free (gv); + + return variant; +} + +static GVariant * +ibus_config_gconf_get_values (IBusConfigService *config, + const gchar *section, + GError **error) +{ + gchar *dir = g_strdup_printf (GCONF_PREFIX"/%s", section); + gint len = strlen(dir) + 1; + GSList *entries = gconf_client_all_entries (((IBusConfigGConf *) config)->client, dir, NULL); + g_free (dir); + + GSList *p; + GVariantBuilder *builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}")); + for (p = entries; p != NULL; p = p->next) { + GConfEntry *entry = (GConfEntry *)p->data; + if (entry->key != NULL && entry->value != NULL) { + const gchar *name = entry->key + len; + GVariant *value = _from_gconf_value (entry->value); + g_variant_builder_add (builder, "{sv}", name, value); + } + gconf_entry_free (entry); + } + g_slist_free (entries); + + return g_variant_builder_end (builder); +} + +static gboolean +ibus_config_gconf_unset_value (IBusConfigService *config, + const gchar *section, + const gchar *name, + GError **error) +{ + gchar *key = g_strdup_printf (GCONF_PREFIX"/%s/%s", section, name); + + gconf_client_unset (((IBusConfigGConf *)config)->client, key, error); + g_free (key); + + if (*error != NULL) { + return FALSE; + } + return TRUE; +} + +IBusConfigGConf * +ibus_config_gconf_new (GDBusConnection *connection) +{ + IBusConfigGConf *config; + config = (IBusConfigGConf *) g_object_new (IBUS_TYPE_CONFIG_GCONF, + "object-path", IBUS_PATH_CONFIG, + "connection", connection, + NULL); + return config; +} diff --git a/conf/gconf/config.h b/conf/gconf/config.h new file mode 100644 index 00000000..32becaae --- /dev/null +++ b/conf/gconf/config.h @@ -0,0 +1,28 @@ +/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ +/* vim:set et sts=4: */ +#ifndef __CONFIG_GCONF_H__ +#define __CONFIG_GCONF_H__ + +#include <ibus.h> +#include <gconf/gconf-client.h> + +#define IBUS_TYPE_CONFIG_GCONF \ + (ibus_config_gconf_get_type ()) +#define IBUS_CONFIG_GCONF(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_CONFIG_GCONF, IBusConfigGConf)) +#define IBUS_CONFIG_GCONF_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_CONFIG_GCONF, IBusConfigGConfClass)) +#define IBUS_IS_CONFIG_GCONF(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_CONFIG_GCONF)) +#define IBUS_IS_CONFIG_GCONF_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_CONFIG_GCONF)) +#define IBUS_CONFIG_GCONF_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_CONFIG_GCONF, IBusConfigGConfClass)) + +typedef struct _IBusConfigGConf IBusConfigGConf; +typedef struct _IBusConfigGConfClass IBusConfigGConfClass; + +GType ibus_config_gconf_get_type (void); +IBusConfigGConf *ibus_config_gconf_new (GDBusConnection *connection); + +#endif diff --git a/conf/gconf/gconf.xml.in.in b/conf/gconf/gconf.xml.in.in new file mode 100644 index 00000000..0644d7e9 --- /dev/null +++ b/conf/gconf/gconf.xml.in.in @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- filename: pinyin.xml --> +<component> + <name>org.freedesktop.IBus.Config</name> + <description>GConf Config Component</description> + <exec>${libexecdir}/ibus-gconf</exec> + <version>@VERSION@</version> + <author>Peng Huang <shawn.p.huang@gmail.com></author> + <license>GPL</license> + <homepage>http://code.google.com/p/ibus</homepage> + <textdomain>ibus</textdomain> +</component> diff --git a/conf/gconf/main.c b/conf/gconf/main.c new file mode 100644 index 00000000..b1100aa0 --- /dev/null +++ b/conf/gconf/main.c @@ -0,0 +1,65 @@ +/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ +/* vim:set et sts=4: */ + +#include <ibus.h> +#include <stdlib.h> +#include <locale.h> +#include "config.h" + +static IBusBus *bus = NULL; +static IBusConfigGConf *config = NULL; + +/* options */ +static gboolean ibus = FALSE; +static gboolean verbose = FALSE; + +static const GOptionEntry entries[] = +{ + { "ibus", 'i', 0, G_OPTION_ARG_NONE, &ibus, "component is executed by ibus", NULL }, + { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "verbose", NULL }, + { NULL }, +}; + + +static void +ibus_disconnected_cb (IBusBus *bus, + gpointer user_data) +{ + ibus_quit (); +} + +static void +ibus_gconf_start (void) +{ + ibus_init (); + bus = ibus_bus_new (); + if (!ibus_bus_is_connected (bus)) { + exit (-1); + } + g_signal_connect (bus, "disconnected", G_CALLBACK (ibus_disconnected_cb), NULL); + config = ibus_config_gconf_new (ibus_bus_get_connection (bus)); + ibus_bus_request_name (bus, IBUS_SERVICE_CONFIG, 0); + ibus_main (); +} + +gint +main (gint argc, gchar **argv) +{ + GError *error = NULL; + GOptionContext *context; + + setlocale (LC_ALL, ""); + + context = g_option_context_new ("- ibus gconf component"); + + g_option_context_add_main_entries (context, entries, "ibus-gconf"); + + if (!g_option_context_parse (context, &argc, &argv, &error)) { + g_print ("Option parsing failed: %s\n", error->message); + exit (-1); + } + + ibus_gconf_start (); + + return 0; +} diff --git a/conf/memconf/Makefile.am b/conf/memconf/Makefile.am new file mode 100644 index 00000000..f5f5c082 --- /dev/null +++ b/conf/memconf/Makefile.am @@ -0,0 +1,76 @@ +# vim:set noet ts=4: +# +# ibus - The Input Bus +# +# Copyright (c) 2010, Google Inc. All rights reserved. +# Copyright (c) 2007-2010 Peng Huang <shawn.p.huang@gmail.com> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place, Suite 330, +# Boston, MA 02111-1307 USA + +libibus = $(top_builddir)/src/libibus-@IBUS_API_VERSION@.la + +libexec_PROGRAMS = \ + ibus-memconf \ + $(NULL) + +ibus_memconf_SOURCES = \ + main.c \ + config.c \ + config.h \ + $(NULL) +ibus_memconf_CFLAGS = \ + @GLIB2_CFLAGS@ \ + @GIO2_CFLAGS@ \ + -DG_LOG_DOMAIN=\"IBUS\" \ + -I$(top_srcdir)/src \ + -I$(top_builddir)/src \ + $(NULL) +ibus_memconf_LDADD = \ + @GOBJECT2_LIBS@ \ + @GLIB2_LIBS@ \ + @GIO2_LIBS@ \ + $(libibus) \ + $(NULL) +ibus_memconf_DEPENDENCIES = \ + $(libibus) \ + $(NULL) + +component_DATA = \ + memconf.xml \ + $(NULL) + +componentdir = $(pkgdatadir)/component + +CLEANFILES = \ + memconf.xml \ + $(NULL) + +EXTRA_DIST = \ + memconf.xml.in.in \ + $(NULL) + +memconf.xml: memconf.xml.in + $(AM_V_GEN) \ + ( \ + libexecdir=${libexecdir}; \ + s=`cat $<`; \ + eval "echo \"$${s}\""; \ + ) > $@ + +$(libibus): + $(MAKE) -C $(top_builddir)/src + +-include $(top_srcdir)/git.mk diff --git a/conf/memconf/config.c b/conf/memconf/config.c new file mode 100644 index 00000000..dd18f2e7 --- /dev/null +++ b/conf/memconf/config.c @@ -0,0 +1,202 @@ +/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (c) 2010, Google Inc. All rights reserved. + * Copyright (C) 2010 Peng Huang <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#include <string.h> +#include <ibus.h> +#include "config.h" + + +typedef struct _IBusConfigMemconfClass IBusConfigMemconfClass; + +struct _IBusConfigMemconf { + IBusConfigService parent; + GHashTable *values; +}; + +struct _IBusConfigMemconfClass { + IBusConfigServiceClass parent; +}; + +/* functions prototype */ +static void ibus_config_memconf_class_init (IBusConfigMemconfClass *class); +static void ibus_config_memconf_init (IBusConfigMemconf *config); +static void ibus_config_memconf_destroy (IBusConfigMemconf *config); +static gboolean ibus_config_memconf_set_value (IBusConfigService *config, + const gchar *section, + const gchar *name, + GVariant *value, + GError **error); +static GVariant *ibus_config_memconf_get_value (IBusConfigService *config, + const gchar *section, + const gchar *name, + GError **error); +static GVariant *ibus_config_memconf_get_values (IBusConfigService *config, + const gchar *section, + GError **error); +static gboolean ibus_config_memconf_unset_value (IBusConfigService *config, + const gchar *section, + const gchar *name, + GError **error); + +G_DEFINE_TYPE (IBusConfigMemconf, ibus_config_memconf, IBUS_TYPE_CONFIG_SERVICE) + +static void +ibus_config_memconf_class_init (IBusConfigMemconfClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + IBUS_OBJECT_CLASS (object_class)->destroy = (IBusObjectDestroyFunc) ibus_config_memconf_destroy; + IBUS_CONFIG_SERVICE_CLASS (object_class)->set_value = ibus_config_memconf_set_value; + IBUS_CONFIG_SERVICE_CLASS (object_class)->get_value = ibus_config_memconf_get_value; + IBUS_CONFIG_SERVICE_CLASS (object_class)->get_values = ibus_config_memconf_get_values; + IBUS_CONFIG_SERVICE_CLASS (object_class)->unset_value = ibus_config_memconf_unset_value; +} + +static void +ibus_config_memconf_init (IBusConfigMemconf *config) +{ + config->values = g_hash_table_new_full (g_str_hash, + g_str_equal, + (GDestroyNotify)g_free, + (GDestroyNotify)g_variant_unref); +} + +static void +ibus_config_memconf_destroy (IBusConfigMemconf *config) +{ + g_hash_table_destroy (config->values); + IBUS_OBJECT_CLASS (ibus_config_memconf_parent_class)->destroy ((IBusObject *)config); +} + +static gboolean +ibus_config_memconf_set_value (IBusConfigService *config, + const gchar *section, + const gchar *name, + GVariant *value, + GError **error) +{ + g_assert (IBUS_IS_CONFIG_MEMCONF (config)); + g_assert (section); + g_assert (name); + g_assert (value); + g_assert (error == NULL || *error == NULL); + + gchar *key = g_strdup_printf ("%s:%s", section, name); + + g_hash_table_insert (IBUS_CONFIG_MEMCONF (config)->values, + key, g_variant_ref_sink (value)); + + ibus_config_service_value_changed (config, section, name, value); + + return TRUE; +} + +static GVariant * +ibus_config_memconf_get_value (IBusConfigService *config, + const gchar *section, + const gchar *name, + GError **error) +{ + g_assert (IBUS_IS_CONFIG_MEMCONF (config)); + g_assert (section); + g_assert (name); + g_assert (error == NULL || *error == NULL); + + gchar *key = g_strdup_printf ("%s:%s", section, name); + GVariant *value = (GVariant *)g_hash_table_lookup (IBUS_CONFIG_MEMCONF (config)->values, key); + g_free (key); + + if (value != NULL) { + g_variant_ref (value); + } + else if (error != NULL) { + *error = g_error_new (G_DBUS_ERROR, G_DBUS_ERROR_FAILED, + "Config value [%s:%s] does not exist.", section, name); + } + return value; +} + +static GVariant * +ibus_config_memconf_get_values (IBusConfigService *config, + const gchar *section, + GError **error) +{ + g_assert (IBUS_IS_CONFIG_MEMCONF (config)); + g_assert (section); + g_assert (error == NULL || *error == NULL); + + GHashTableIter iter; + const gchar *key; + GVariant *value; + + GVariantBuilder *builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}")); + g_hash_table_iter_init (&iter, IBUS_CONFIG_MEMCONF (config)->values); + while (g_hash_table_iter_next (&iter, (gpointer *)&key, (gpointer *)&value)) { + gchar **v = g_strsplit (key, ":", 2); + if (g_strcmp0 (v[0], section) == 0) { + g_variant_builder_add (builder, "{sv}", v[1], value); + } + g_strfreev(v); + } + + return g_variant_builder_end (builder); +} + +static gboolean +ibus_config_memconf_unset_value (IBusConfigService *config, + const gchar *section, + const gchar *name, + GError **error) +{ + g_assert (IBUS_IS_CONFIG_MEMCONF (config)); + g_assert (section); + g_assert (name); + g_assert (error == NULL || *error == NULL); + + gchar *key = g_strdup_printf ("%s:%s", section, name); + gboolean retval = g_hash_table_remove (IBUS_CONFIG_MEMCONF (config)->values, key); + g_free (key); + + if (retval) { + ibus_config_service_value_changed (config, + section, + name, + g_variant_new_tuple (NULL, 0)); + } + else { + if (error && *error) { + *error = g_error_new (G_DBUS_ERROR, G_DBUS_ERROR_FAILED, + "Config value [%s:%s] does not exist.", section, name); + } + } + return retval; +} + +IBusConfigMemconf * +ibus_config_memconf_new (GDBusConnection *connection) +{ + IBusConfigMemconf *config; + config = (IBusConfigMemconf *) g_object_new (IBUS_TYPE_CONFIG_MEMCONF, + "object-path", IBUS_PATH_CONFIG, + "connection", connection, + NULL); + return config; +} diff --git a/conf/memconf/config.h b/conf/memconf/config.h new file mode 100644 index 00000000..2b745d4f --- /dev/null +++ b/conf/memconf/config.h @@ -0,0 +1,45 @@ +/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (c) 2010, Google Inc. All rights reserved. + * Copyright (C) 2010 Peng Huang <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __CONFIG_MEMCONF_H__ +#define __CONFIG_MEMCONF_H__ + +#include <ibus.h> + +#define IBUS_TYPE_CONFIG_MEMCONF \ + (ibus_config_memconf_get_type ()) +#define IBUS_CONFIG_MEMCONF(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_CONFIG_MEMCONF, IBusConfigMemconf)) +#define IBUS_CONFIG_MEMCONF_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_CONFIG_MEMCONF, IBusConfigMemconfClass)) +#define IBUS_IS_CONFIG_MEMCONF(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_CONFIG_MEMCONF)) +#define IBUS_IS_CONFIG_MEMCONF_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_CONFIG_MEMCONF)) +#define IBUS_CONFIG_MEMCONF_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_CONFIG_MEMCONF, IBusConfigMemconfClass)) + +typedef struct _IBusConfigMemconf IBusConfigMemconf; + +GType ibus_config_memconf_get_type (void); +IBusConfigMemconf *ibus_config_memconf_new (GDBusConnection *connection); + +#endif diff --git a/conf/memconf/main.c b/conf/memconf/main.c new file mode 100644 index 00000000..51dfd7f1 --- /dev/null +++ b/conf/memconf/main.c @@ -0,0 +1,83 @@ +/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (c) 2010, Google Inc. All rights reserved. + * Copyright (C) 2010 Peng Huang <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#include <ibus.h> +#include <stdlib.h> +#include <locale.h> +#include "config.h" + +static IBusBus *bus = NULL; +static IBusConfigMemconf *config = NULL; + +/* options */ +static gboolean ibus = FALSE; +static gboolean verbose = FALSE; + +static const GOptionEntry entries[] = +{ + { "ibus", 'i', 0, G_OPTION_ARG_NONE, &ibus, "component is executed by ibus", NULL }, + { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "verbose", NULL }, + { NULL }, +}; + + +static void +ibus_disconnected_cb (IBusBus *bus, + gpointer user_data) +{ + ibus_quit (); +} + +static void +ibus_memconf_start (void) +{ + ibus_init (); + bus = ibus_bus_new (); + if (!ibus_bus_is_connected (bus)) { + exit (-1); + } + g_signal_connect (bus, "disconnected", G_CALLBACK (ibus_disconnected_cb), NULL); + config = ibus_config_memconf_new (ibus_bus_get_connection (bus)); + ibus_bus_request_name (bus, IBUS_SERVICE_CONFIG, 0); + ibus_main (); +} + +gint +main (gint argc, gchar **argv) +{ + GError *error = NULL; + GOptionContext *context; + + setlocale (LC_ALL, ""); + + context = g_option_context_new ("- ibus memconf component"); + + g_option_context_add_main_entries (context, entries, "ibus-memconf"); + + if (!g_option_context_parse (context, &argc, &argv, &error)) { + g_print ("Option parsing failed: %s\n", error->message); + exit (-1); + } + + ibus_memconf_start (); + + return 0; +} diff --git a/conf/memconf/memconf.xml.in.in b/conf/memconf/memconf.xml.in.in new file mode 100644 index 00000000..b60dbf2e --- /dev/null +++ b/conf/memconf/memconf.xml.in.in @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<component> + <name>org.freedesktop.IBus.Config</name> + <description>On-memory Config Component</description> + <exec>${libexecdir}/ibus-memconf</exec> + <version>@VERSION@</version> + <author>Peng Huang <shawn.p.huang@gmail.com>, modified by the Chromium OS Authors</author> + <license>GPL</license> + <homepage>http://code.google.com/p/ibus</homepage> + <textdomain>ibus</textdomain> +</component> |