From 047452beffd7cb429bf4dfeb2371f120cc8041a6 Mon Sep 17 00:00:00 2001 From: fujiwarat Date: Fri, 11 Mar 2011 16:07:09 +0900 Subject: [PATCH] Reload preload engines until users customize the list. The idea is, if users don't customize the preload_engines with ibus-setup, users would prefer to load the system default engines again by login. The gconf value 'preload_engine_mode' is IBUS_PRELOAD_ENGINE_MODE_LANG_RELATIVE by default. If preload_engine_mode is IBUS_PRELOAD_ENGINE_MODE_LANG_RELATIVE, ibus-daemon loads the system preload engines by langs. If preload_engine_mode is IBUS_PRELOAD_ENGINE_MODE_USER, ibus-daemon do not update the gconf value preload_engines. On the other hand, if users enable the customized engine checkbutton on ibus-setup, ibus-setup sets 'preload_engine_mode' as IBUS_PRELOAD_ENGINE_MODE_USER and users can customize the value 'preload_engines'. Loading system default may spend the startup time. If you mind it, your dist may like to put TRUE in 'use_local_preload_engines' value. --- bus/ibusimpl.c | 286 +++++++++++++++++++++++++++++++++++--------------- data/ibus.schemas.in | 13 +++ ibus/common.py | 6 + setup/main.py | 37 ++++++- setup/setup.ui | 21 +++- src/ibustypes.h | 10 ++ 6 files changed, 279 insertions(+), 94 deletions(-) diff --git a/bus/ibusimpl.c b/bus/ibusimpl.c index 8d4ec36..0caa8c7 100644 --- a/bus/ibusimpl.c +++ b/bus/ibusimpl.c @@ -144,6 +144,9 @@ static void bus_ibus_impl_set_previo static void bus_ibus_impl_set_preload_engines (BusIBusImpl *ibus, GVariant *value); +static void bus_ibus_impl_set_preload_engine_mode + (BusIBusImpl *ibus, + GVariant *value); static void bus_ibus_impl_set_use_sys_layout (BusIBusImpl *ibus, GVariant *value); @@ -284,6 +287,142 @@ _panel_destroy_cb (BusPanelProxy *panel, g_object_unref (panel); } +#ifndef OS_CHROMEOS +static gint +_engine_desc_cmp (IBusEngineDesc *desc1, + IBusEngineDesc *desc2) +{ + return - ((gint) ibus_engine_desc_get_rank (desc1)) + + ((gint) ibus_engine_desc_get_rank (desc2)); +} +#endif + +#ifndef OS_CHROMEOS +static gint +_get_config_preload_engine_mode (BusIBusImpl *ibus) +{ + GVariant *variant = NULL; + gint preload_engine_mode = IBUS_PRELOAD_ENGINE_MODE_LANG_RELATIVE; + + g_assert (BUS_IS_IBUS_IMPL (ibus)); + + if (ibus->config == NULL) { + return preload_engine_mode; + } + + variant = ibus_config_get_value (ibus->config, "general", + "preload_engine_mode"); + if (variant != NULL) { + if (g_variant_classify (variant) == G_VARIANT_CLASS_INT32) { + preload_engine_mode = g_variant_get_int32 (variant); + } + g_variant_unref (variant); + } + + return preload_engine_mode; +} +#endif + +static void +_set_preload_engines (BusIBusImpl *ibus, + GVariant *value) +{ + GList *engine_list = NULL; + + g_assert (BUS_IS_IBUS_IMPL (ibus)); + + g_list_foreach (ibus->engine_list, (GFunc) g_object_unref, NULL); + g_list_free (ibus->engine_list); + + if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_ARRAY) { + GVariantIter iter; + g_variant_iter_init (&iter, value); + const gchar *engine_name = NULL; + while (g_variant_iter_loop (&iter, "&s", &engine_name)) { + IBusEngineDesc *engine = bus_registry_find_engine_by_name (ibus->registry, engine_name); + if (engine == NULL || g_list_find (engine_list, engine) != NULL) + continue; + engine_list = g_list_append (engine_list, engine); + } + + if (engine_list != NULL && + ibus->config != NULL && + ibus_config_get_value (ibus->config, "general", + "preload_engines") == NULL) { + ibus_config_set_value (ibus->config, "general", + "preload_engines", value); + } else { + /* We don't update preload_engines with an empty string for safety. + * Just unref the floating value. */ + g_variant_unref (value); + } + } else if (value != NULL) { + g_variant_unref (value); + } + + g_list_foreach (engine_list, (GFunc) g_object_ref, NULL); + ibus->engine_list = engine_list; + + if (ibus->engine_list) { + BusComponent *component = bus_component_from_engine_desc ((IBusEngineDesc *) ibus->engine_list->data); + if (component && !bus_component_is_running (component)) { + bus_component_start (component, g_verbose); + } + } + + bus_ibus_impl_check_global_engine (ibus); + bus_ibus_impl_update_engines_hotkey_profile (ibus); +} + +#ifndef OS_CHROMEOS +static void +_set_language_relative_preload_engines (BusIBusImpl *ibus) +{ + gchar *lang = NULL; + gchar *p = NULL; + GList *engines = NULL; + GList *list; + GVariantBuilder builder; + + g_assert (BUS_IS_IBUS_IMPL (ibus)); + + /* The setlocale call first checks LC_ALL. If it's not available, checks + * LC_CTYPE. If it's also not available, checks LANG. */ + lang = g_strdup (setlocale (LC_CTYPE, NULL)); + if (lang == NULL) { + return; + } + + p = index (lang, '.'); + if (p) { + *p = '\0'; + } + + engines = bus_registry_get_engines_by_language (ibus->registry, lang); + if (engines == NULL) { + p = index (lang, '_'); + if (p) { + *p = '\0'; + engines = bus_registry_get_engines_by_language (ibus->registry, lang); + } + } + g_free (lang); + + /* sort engines by rank */ + engines = g_list_sort (engines, (GCompareFunc) _engine_desc_cmp); + + g_variant_builder_init (&builder, G_VARIANT_TYPE ("as")); + for (list = engines; list != NULL; list = list->next) { + IBusEngineDesc *desc = (IBusEngineDesc *)list->data; + /* ignore engines with rank <== 0 */ + if (ibus_engine_desc_get_rank (desc) > 0) + g_variant_builder_add (&builder, "s", ibus_engine_desc_get_name (desc)); + } + _set_preload_engines (ibus, g_variant_builder_end (&builder)); + g_list_free (engines); +} +#endif + static void bus_ibus_impl_set_hotkey (BusIBusImpl *ibus, GQuark hotkey, @@ -394,35 +533,50 @@ static void bus_ibus_impl_set_preload_engines (BusIBusImpl *ibus, GVariant *value) { - GList *engine_list = NULL; - - g_list_foreach (ibus->engine_list, (GFunc) g_object_unref, NULL); - g_list_free (ibus->engine_list); +#ifndef OS_CHROMEOS + gint preload_engine_mode = _get_config_preload_engine_mode (ibus); - if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_ARRAY) { - GVariantIter iter; - g_variant_iter_init (&iter, value); - const gchar *engine_name = NULL; - while (g_variant_iter_loop (&iter, "&s", &engine_name)) { - IBusEngineDesc *engine = bus_registry_find_engine_by_name (ibus->registry, engine_name); - if (engine == NULL || g_list_find (engine_list, engine) != NULL) - continue; - engine_list = g_list_append (engine_list, engine); + if (preload_engine_mode == IBUS_PRELOAD_ENGINE_MODE_USER) { + if (value == NULL) { + _set_language_relative_preload_engines (ibus); + } else { + _set_preload_engines (ibus, value); } } +#else + _set_preload_engines (ibus, value); +#endif +} - g_list_foreach (engine_list, (GFunc) g_object_ref, NULL); - ibus->engine_list = engine_list; +/** + * bus_ibus_impl_set_preload_engine_mode: + * + * A function to be called when "preload_engines_mode" config is updated. + */ +static void +bus_ibus_impl_set_preload_engine_mode (BusIBusImpl *ibus, + GVariant *value) +{ +#ifndef OS_CHROMEOS + gint preload_engine_mode = IBUS_PRELOAD_ENGINE_MODE_LANG_RELATIVE; - if (ibus->engine_list) { - BusComponent *component = bus_component_from_engine_desc ((IBusEngineDesc *) ibus->engine_list->data); - if (component && !bus_component_is_running (component)) { - bus_component_start (component, g_verbose); - } + /* bus_ibus_impl_reload_config() sets value = NULL. + * bus_ibus_impl_reload_config() is always called when + * RequestName signal is sent so it is good to get the gconf value + * again when value == NULL. + */ + if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_INT32) { + preload_engine_mode = g_variant_get_int32 (value); + } else { + preload_engine_mode = _get_config_preload_engine_mode (ibus); } - bus_ibus_impl_check_global_engine (ibus); - bus_ibus_impl_update_engines_hotkey_profile (ibus); + if (preload_engine_mode == IBUS_PRELOAD_ENGINE_MODE_USER) { + return; + } + + _set_language_relative_preload_engines (ibus); +#endif } /** @@ -503,89 +657,48 @@ bus_ibus_impl_set_use_global_engine (Bus } } -#ifndef OS_CHROMEOS -static gint -_engine_desc_cmp (IBusEngineDesc *desc1, - IBusEngineDesc *desc2) -{ - return - ((gint) ibus_engine_desc_get_rank (desc1)) + - ((gint) ibus_engine_desc_get_rank (desc2)); -} -#endif - /** * bus_ibus_impl_set_default_preload_engines: * - * If the "preload_engines" config variable is not set yet, set the default value which is determined based on a current locale. + * bus_ibus_impl_set_default_preload_engines handles the gconf value + * /desktop/ibus/general/preload_engines and preload_engine_mode. + * The idea is, if users don't customize the preload_engines with ibus-setup, + * users would prefer to load the system default engines again by login. + * The gconf value 'preload_engine_mode' is + * IBUS_PRELOAD_ENGINE_MODE_USER by default. + * If preload_engine_mode is IBUS_PRELOAD_ENGINE_MODE_LANG_RELATIVE, + * ibus-daemon loads the system preload engines by langs. + * If preload_engine_mode is IBUS_PRELOAD_ENGINE_MODE_USER, + * ibus-daemon do not update the gconf value preload_engines. + * On the other hand, if users enable the customized engine checkbutton + * on ibus-setup, ibus-setup sets 'preload_engine_mode' as + * IBUS_PRELOAD_ENGINE_MODE_USER and users can customize the value + * 'preload_engines'. + * Loading system default may spend the startup time. If you mind it, + * your dist may like to put TRUE in 'use_local_preload_engines' value. */ static void bus_ibus_impl_set_default_preload_engines (BusIBusImpl *ibus) { #ifndef OS_CHROMEOS - g_assert (BUS_IS_IBUS_IMPL (ibus)); - static gboolean done = FALSE; + gint preload_engine_mode = IBUS_PRELOAD_ENGINE_MODE_LANG_RELATIVE; + + g_assert (BUS_IS_IBUS_IMPL (ibus)); if (done || ibus->config == NULL) { return; } - GVariant *variant = ibus_config_get_value (ibus->config, "general", "preload_engines"); - if (variant != NULL) { + preload_engine_mode = _get_config_preload_engine_mode (ibus); + + if (preload_engine_mode == IBUS_PRELOAD_ENGINE_MODE_USER) { done = TRUE; - g_variant_unref (variant); return; } done = TRUE; - - /* The setlocale call first checks LC_ALL. If it's not available, checks - * LC_CTYPE. If it's also not available, checks LANG. */ - gchar *lang = g_strdup (setlocale (LC_CTYPE, NULL)); - if (lang == NULL) { - return; - } - - gchar *p = index (lang, '.'); - if (p) { - *p = '\0'; - } - - GList *engines = bus_registry_get_engines_by_language (ibus->registry, lang); - if (engines == NULL) { - p = index (lang, '_'); - if (p) { - *p = '\0'; - engines = bus_registry_get_engines_by_language (ibus->registry, lang); - } - } - g_free (lang); - - /* sort engines by rank */ - engines = g_list_sort (engines, (GCompareFunc) _engine_desc_cmp); - - GVariantBuilder builder; - g_variant_builder_init (&builder, G_VARIANT_TYPE ("as")); - GList *list; - for (list = engines; list != NULL; list = list->next) { - IBusEngineDesc *desc = (IBusEngineDesc *) list->data; - /* ignore engines with rank <= 0 */ - if (ibus_engine_desc_get_rank (desc) > 0) - g_variant_builder_add (&builder, "s", ibus_engine_desc_get_name (desc)); - } - - GVariant *value = g_variant_builder_end (&builder); - if (value != NULL) { - if (g_variant_n_children (value) > 0) { - ibus_config_set_value (ibus->config, - "general", "preload_engines", value); - } else { - /* We don't update preload_engines with an empty string for safety. - * Just unref the floating value. */ - g_variant_unref (value); - } - } - g_list_free (engines); + _set_language_relative_preload_engines (ibus); #endif } @@ -601,6 +714,7 @@ const static struct { { "general/hotkey", "next_engine_in_menu", bus_ibus_impl_set_next_engine_in_menu }, { "general/hotkey", "previous_engine", bus_ibus_impl_set_previous_engine }, { "general", "preload_engines", bus_ibus_impl_set_preload_engines }, + { "general", "preload_engines_mode", bus_ibus_impl_set_preload_engine_mode }, { "general", "use_system_keyboard_layout", bus_ibus_impl_set_use_sys_layout }, { "general", "use_global_engine", bus_ibus_impl_set_use_global_engine }, { "general", "embed_preedit_text", bus_ibus_impl_set_embed_preedit_text }, diff --git a/data/ibus.schemas.in b/data/ibus.schemas.in index 7ca4899..39922a0 100644 --- a/data/ibus.schemas.in +++ b/data/ibus.schemas.in @@ -13,6 +13,19 @@ + /schemas/desktop/ibus/general/preload_engine_mode + /desktop/ibus/general/preload_engine_mode + ibus + int + 1 + + Preload engine mode + Preload engines are loaded with this mode. + 0 = user customized engines. + 1 = language related engines. + + + /schemas/desktop/ibus/general/hotkey/trigger /desktop/ibus/general/hotkey/trigger ibus diff --git a/ibus/common.py b/ibus/common.py index e105f18..20c0710 100644 --- a/ibus/common.py +++ b/ibus/common.py @@ -40,6 +40,8 @@ __all__ = ( "BUS_REQUEST_NAME_REPLY_IN_QUEUE", "BUS_REQUEST_NAME_REPLY_EXISTS", "BUS_REQUEST_NAME_REPLY_ALREADY_OWNER", + "PRELOAD_ENGINE_MODE_USER", + "PRELOAD_ENGINE_MODE_LANG_RELATIVE", "default_reply_handler", "default_error_handler", "DEFAULT_ASYNC_HANDLERS", @@ -150,6 +152,10 @@ BUS_REQUEST_NAME_REPLY_IN_QUEUE = 2 BUS_REQUEST_NAME_REPLY_EXISTS = 3 BUS_REQUEST_NAME_REPLY_ALREADY_OWNER = 4 +# define preload engine mode +PRELOAD_ENGINE_MODE_USER = 0 +PRELOAD_ENGINE_MODE_LANG_RELATIVE = 1 + def default_reply_handler( *args): pass diff --git a/setup/main.py b/setup/main.py index 7f4a040..9cdce02 100644 --- a/setup/main.py +++ b/setup/main.py @@ -213,15 +213,22 @@ class Setup(object): self.__checkbutton_use_global_engine.connect("toggled", self.__checkbutton_use_global_engine_toggled_cb) # init engine page + preload_engine_mode = self.__config.get_value("general", + "preload_engine_mode", + ibus.common.PRELOAD_ENGINE_MODE_USER) + button = self.__builder.get_object("checkbutton_preload_engine_mode") + if preload_engine_mode == ibus.common.PRELOAD_ENGINE_MODE_USER: + button.set_active(True) + self.__builder.get_object("hbox_customize_active_input_methods").set_sensitive(True) + else: + button.set_active(False) + self.__builder.get_object("hbox_customize_active_input_methods").set_sensitive(False) + button.connect("toggled", self.__checkbutton_preload_engine_mode_toggled_cb) self.__engines = self.__bus.list_engines() self.__combobox = self.__builder.get_object("combobox_engines") self.__combobox.set_engines(self.__engines) - tmp_dict = {} - for e in self.__engines: - tmp_dict[e.name] = e - engine_names = self.__config.get_value("general", "preload_engines", []) - engines = [tmp_dict[name] for name in engine_names if name in tmp_dict] + engines = self.__bus.list_active_engines() self.__treeview = self.__builder.get_object("treeview_engines") self.__treeview.set_engines(engines) @@ -265,6 +272,13 @@ class Setup(object): engine_names = map(lambda e: e.name, engines) self.__config.set_list("general", "preload_engines", engine_names, "s") + def __get_engine_descs_from_names(self, engine_names): + tmp_dict = {} + for e in self.__engines: + tmp_dict[e.name] = e + engines = [tmp_dict[name] for name in engine_names if name in tmp_dict] + return engines + def __button_engine_add_cb(self, button): engine = self.__combobox.get_active_engine() self.__treeview.append_engine(engine) @@ -276,6 +290,19 @@ class Setup(object): about.run() about.destroy() + def __checkbutton_preload_engine_mode_toggled_cb(self, button): + if button.get_active(): + self.__config.set_value("general", + "preload_engine_mode", + ibus.common.PRELOAD_ENGINE_MODE_USER) + self.__builder.get_object("hbox_customize_active_input_methods").set_sensitive(True) + self.__treeview.notify("engines") + else: + self.__config.set_value("general", + "preload_engine_mode", + ibus.common.PRELOAD_ENGINE_MODE_LANG_RELATIVE) + self.__builder.get_object("hbox_customize_active_input_methods").set_sensitive(False) + def __init_bus(self): try: self.__bus = ibus.Bus() diff --git a/setup/setup.ui b/setup/setup.ui index f1e6d0b..562c091 100644 --- a/setup/setup.ui +++ b/setup/setup.ui @@ -582,7 +582,22 @@ True vertical - + + True + Customize active input _methods + True + True + False + Customize active input methods + True + + + False + 0 + + + + True @@ -733,7 +748,7 @@ - 0 + 1 @@ -772,7 +787,7 @@ You may use up/down buttons to change it.</i></small> False - 1 + 2 diff --git a/src/ibustypes.h b/src/ibustypes.h index 035d124..0a9d7b2 100644 --- a/src/ibustypes.h +++ b/src/ibustypes.h @@ -177,6 +177,16 @@ typedef enum { } IBusBusRequestNameReply; /** + * IBusPreloadEngineMode: + * @IBUS_PRELOAD_ENGINE_MODE_USER: user custimized engines + * @IBUS_PRELOAD_ENGINE_MODE_LANG_RELATIVE: language related engines. + */ +typedef enum { + IBUS_PRELOAD_ENGINE_MODE_USER = 0, + IBUS_PRELOAD_ENGINE_MODE_LANG_RELATIVE = 1, +} IBusPreloadEngineMode; + +/** * IBusRectangle: * @x: x coordinate. * @y: y coordinate. -- 1.7.4.1