1faf033
From d566bc83a4672b88a38fa5de25741b99ebaeae62 Mon Sep 17 00:00:00 2001
8a795bf
From: fujiwarat <takao.fujiwara1@gmail.com>
1faf033
Date: Fri, 20 Sep 2013 17:20:09 +0900
8a795bf
Subject: [PATCH] Reload preload engines until users customize the list.
8a795bf
8a795bf
The idea is, if users don't customize the preload_engines with ibus-setup,
8a795bf
users would prefer to load the system default engines again by login.
1faf033
The gsettings value 'preload-engine-mode' is
63b857f
IBUS_PRELOAD_ENGINE_MODE_USER by default but set
63b857f
IBUS_PRELOAD_ENGINE_MODE_LANG_RELATIVE for the initial login.
1faf033
If 'preload-engine-mode' is IBUS_PRELOAD_ENGINE_MODE_LANG_RELATIVE,
8a795bf
ibus-daemon loads the system preload engines by langs.
1faf033
If 'preload-engine-mode' is IBUS_PRELOAD_ENGINE_MODE_USER,
1faf033
ibus-daemon do not update the gsettings value 'preload-engines'
8a795bf
On the other hand, if users enable the customized engine checkbutton
1faf033
on ibus-setup, ibus-setup sets 'preload-engine-mode' as
8a795bf
IBUS_PRELOAD_ENGINE_MODE_USER and users can customize the value
1faf033
'preload-engines'.
8a795bf
---
1faf033
 data/ibus.schemas.in | 24 ++++++++++++++
1faf033
 setup/main.py        | 70 +++++++++++++++++++++++++++++++++++----
1faf033
 setup/setup.ui       | 22 +++++++++++--
1faf033
 src/ibustypes.h      | 10 ++++++
1faf033
 ui/gtk3/panel.vala   | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1faf033
 5 files changed, 210 insertions(+), 9 deletions(-)
8a795bf
8a795bf
diff --git a/data/ibus.schemas.in b/data/ibus.schemas.in
1faf033
index 88a287f..b6709fd 100644
8a795bf
--- a/data/ibus.schemas.in
8a795bf
+++ b/data/ibus.schemas.in
19c65a7
@@ -2,6 +2,30 @@
19c65a7
 <gconfschemafile>
19c65a7
   <schemalist>
8a795bf
     <schema>
8a795bf
+      <key>/schemas/desktop/ibus/general/preload_engine_mode</key>
8a795bf
+      <applyto>/desktop/ibus/general/preload_engine_mode</applyto>
8a795bf
+      <owner>ibus</owner>
8a795bf
+      <type>int</type>
63b857f
+      <default>0</default>
8a795bf
+      <locale name="C">
8a795bf
+        <short>Preload engine mode</short>
19c65a7
+            <long>Preload engines are loaded with this mode.
19c65a7
+                  0 = user customized engines.
19c65a7
+                  1 = language related engines.</long>
8a795bf
+      </locale>
8a795bf
+    </schema>
8a795bf
+    <schema>
19c65a7
+      <key>/schemas/desktop/ibus/general/preload_engines_inited</key>
19c65a7
+      <applyto>/desktop/ibus/general/preload_engines_inited</applyto>
19c65a7
+      <owner>ibus</owner>
19c65a7
+      <type>bool</type>
19c65a7
+      <default>false</default>
19c65a7
+      <locale name="C">
19c65a7
+        <short>The key preload_engines is initialized</short>
19c65a7
+            <long>The key preload_engines is initialized</long>
19c65a7
+      </locale>
19c65a7
+    </schema>
19c65a7
+    <schema>
19c65a7
       <key>/schemas/desktop/ibus/general/preload_engines</key>
19c65a7
       <applyto>/desktop/ibus/general/preload_engines</applyto>
8a795bf
       <owner>ibus</owner>
8a795bf
diff --git a/setup/main.py b/setup/main.py
1faf033
index d3f4414..235ef9c 100644
8a795bf
--- a/setup/main.py
8a795bf
+++ b/setup/main.py
1faf033
@@ -187,16 +187,30 @@ class Setup(object):
1faf033
                                     'active',
1faf033
                                     Gio.SettingsBindFlags.DEFAULT)
8a795bf
 
19c65a7
+        # set preload mode
1faf033
+        preload_engine_mode = \
1faf033
+                self.__settings_general.get_int('preload-engine-mode')
8a795bf
+        button = self.__builder.get_object("checkbutton_preload_engine_mode")
1faf033
+        hbox = self.__builder.get_object("hbox_customize_active_input_methods")
19c65a7
+        if preload_engine_mode == IBus.PreloadEngineMode.USER:
8a795bf
+            button.set_active(True)
1faf033
+            hbox.set_sensitive(True)
8a795bf
+        else:
8a795bf
+            button.set_active(False)
1faf033
+            hbox.set_sensitive(False)
1faf033
+        button.connect('toggled',
1faf033
+                       self.__checkbutton_preload_engine_mode_toggled_cb)
1faf033
+
1faf033
+        self.__settings_general.connect('changed::preload-engines',
1faf033
+                self.__settings_general_preload_engines_cb)
19c65a7
+
19c65a7
         # init engine page
8a795bf
         self.__engines = self.__bus.list_engines()
ecac051
         self.__combobox = self.__builder.get_object("combobox_engines")
80224fc
         self.__combobox.set_engines(self.__engines)
80224fc
 
80224fc
-        tmp_dict = {}
80224fc
-        for e in self.__engines:
80224fc
-            tmp_dict[e.get_name()] = e
1faf033
         engine_names = self.__settings_general.get_strv('preload-engines')
80224fc
-        engines = [tmp_dict[name] for name in engine_names if name in tmp_dict]
80224fc
+        engines = self.__get_engine_descs_from_names(engine_names)
80224fc
 
80224fc
         self.__treeview = self.__builder.get_object("treeview_engines")
80224fc
         self.__treeview.set_engines(engines)
1faf033
@@ -246,8 +260,8 @@ class Setup(object):
e4605fa
     def __combobox_notify_active_engine_cb(self, combobox, property):
e4605fa
         engine = self.__combobox.get_active_engine()
e4605fa
         button = self.__builder.get_object("button_engine_add")
19c65a7
-        button.set_sensitive(
19c65a7
-                engine != None and engine not in self.__treeview.get_engines())
e4605fa
+        button.set_sensitive(engine != None and \
19c65a7
+                engine.get_name() not in map(lambda e: e.get_name(), self.__treeview.get_engines()))
e4605fa
 
150c9ee
     def __get_engine_setup_exec_args(self, engine):
150c9ee
         args = []
1faf033
@@ -267,6 +281,13 @@ class Setup(object):
80224fc
             args.append(path.basename(setup_path))
80224fc
         return args
80224fc
 
80224fc
+    def __get_engine_descs_from_names(self, engine_names):
80224fc
+        tmp_dict = {}
80224fc
+        for e in self.__engines:
80224fc
+            tmp_dict[e.get_name()] = e
80224fc
+        engines = [tmp_dict[name] for name in engine_names if name in tmp_dict]
80224fc
+        return engines
80224fc
+
80224fc
     def __treeview_notify_cb(self, treeview, prop):
80224fc
         if prop.name not in ("active-engine", "engines"):
80224fc
             return
1faf033
@@ -318,6 +339,43 @@ class Setup(object):
150c9ee
             del self.__engine_setup_exec_list[name]
150c9ee
         self.__engine_setup_exec_list[name] = os.spawnl(os.P_NOWAIT, *args)
8a795bf
 
8a795bf
+    def __checkbutton_preload_engine_mode_toggled_cb(self, button):
8a795bf
+        if button.get_active():
1faf033
+            self.__settings_general.set_int('preload-engine-mode',
1faf033
+                                            IBus.PreloadEngineMode.USER)
1faf033
+            self.__builder.get_object(
1faf033
+                    "hbox_customize_active_input_methods").set_sensitive(True)
1faf033
+            self.__treeview.notify('engines')
8a795bf
+        else:
63b857f
+            message = _("The list of your saved input methods will be " \
63b857f
+                        "cleared immediately and the list will be " \
63b857f
+                        "configured by the login language every time. " \
63b857f
+                        "Do you agree with this?")
19c65a7
+            dlg = Gtk.MessageDialog(type = Gtk.MessageType.QUESTION,
19c65a7
+                    buttons = Gtk.ButtonsType.YES_NO,
63b857f
+                    message_format = message)
63b857f
+            id = dlg.run()
63b857f
+            dlg.destroy()
63b857f
+            self.__flush_gtk_events()
19c65a7
+            if id != Gtk.ResponseType.YES:
63b857f
+                button.set_active(True)
63b857f
+                return
1faf033
+            self.__settings_general.set_int(
1faf033
+                    'preload-engine-mode',
1faf033
+                    IBus.PreloadEngineMode.LANG_RELATIVE)
1faf033
+            self.__builder.get_object(
1faf033
+                    "hbox_customize_active_input_methods").set_sensitive(False)
1faf033
+
1faf033
+    def __settings_general_preload_engines_cb(self, settings, key):
1faf033
+        engine_names = self.__settings_general.get_strv('preload-engines')
1faf033
+        engines = self.__get_engine_descs_from_names(engine_names)
1faf033
+        current_engines = self.__treeview.get_engines()
1faf033
+        engines_csv = str.join(',', map(lambda e: e.get_name(), engines))
1faf033
+        current_engines_csv = \
1faf033
+                str.join(',', map(lambda e: e.get_name(), current_engines))
1faf033
+        if engines_csv != current_engines_csv:
1faf033
+            self.__treeview.set_engines(engines)
8a795bf
+
8a795bf
     def __init_bus(self):
19c65a7
         self.__bus = IBus.Bus()
19c65a7
         if self.__bus.is_connected():
8a795bf
diff --git a/setup/setup.ui b/setup/setup.ui
1faf033
index 1638abb..72a5d57 100644
8a795bf
--- a/setup/setup.ui
8a795bf
+++ b/setup/setup.ui
ecac051
@@ -669,7 +669,23 @@
8a795bf
                     <property name="visible">True</property>
db31e52
                     <property name="can_focus">False</property>
8a795bf
                     <child>
8a795bf
-                      <object class="GtkHBox" id="hbox1">
8a795bf
+                      <object class="GtkCheckButton" id="checkbutton_preload_engine_mode">
8a795bf
+                        <property name="visible">True</property>
8a795bf
+                        <property name="label" translatable="yes">Customize active input _methods</property>
8a795bf
+                        <property name="use_underline">True</property>
8a795bf
+                        <property name="can_focus">True</property>
8a795bf
+                        <property name="receives_default">False</property>
8a795bf
+                        <property name="tooltip_text" translatable="yes">Customize active input methods</property>
8a795bf
+                        <property name="draw_indicator">True</property>
8a795bf
+                      </object>
8a795bf
+                      <packing>
8a795bf
+                        <property name="expand">False</property>
db31e52
+                        <property name="fill">True</property>
8a795bf
+                        <property name="position">0</property>
8a795bf
+                      </packing>
8a795bf
+                    </child>
8a795bf
+                    <child>
8a795bf
+                      <object class="GtkHBox" id="hbox_customize_active_input_methods">
8a795bf
                         <property name="visible">True</property>
db31e52
                         <property name="can_focus">False</property>
8a795bf
                         <child>
ecac051
@@ -858,7 +874,7 @@
8a795bf
                       <packing>
db31e52
                         <property name="expand">True</property>
db31e52
                         <property name="fill">True</property>
8a795bf
-                        <property name="position">0</property>
8a795bf
+                        <property name="position">1</property>
8a795bf
                       </packing>
8a795bf
                     </child>
8a795bf
                     <child>
ecac051
@@ -905,7 +921,7 @@ You may use up/down buttons to change it.</i></small></property>
8a795bf
                       <packing>
8a795bf
                         <property name="expand">False</property>
db31e52
                         <property name="fill">True</property>
8a795bf
-                        <property name="position">1</property>
8a795bf
+                        <property name="position">2</property>
8a795bf
                       </packing>
8a795bf
                     </child>
8a795bf
                   </object>
8a795bf
diff --git a/src/ibustypes.h b/src/ibustypes.h
1faf033
index 6d30a86..dac7f8f 100644
8a795bf
--- a/src/ibustypes.h
8a795bf
+++ b/src/ibustypes.h
fd3eb3d
@@ -204,6 +204,16 @@ typedef enum {
63b857f
 } IBusError;
8a795bf
 
8a795bf
 /**
8a795bf
+ * IBusPreloadEngineMode:
8a795bf
+ * @IBUS_PRELOAD_ENGINE_MODE_USER: user custimized engines
3b5789d
+ * @IBUS_PRELOAD_ENGINE_MODE_LANG_RELATIVE: language related engines.
8a795bf
+ */
8a795bf
+typedef enum {
3b5789d
+    IBUS_PRELOAD_ENGINE_MODE_USER          = 0,
3b5789d
+    IBUS_PRELOAD_ENGINE_MODE_LANG_RELATIVE = 1,
8a795bf
+} IBusPreloadEngineMode;
8a795bf
+
8a795bf
+/**
8a795bf
  * IBusRectangle:
8a795bf
  * @x: x coordinate.
8a795bf
  * @y: y coordinate.
19c65a7
diff --git a/ui/gtk3/panel.vala b/ui/gtk3/panel.vala
1faf033
index c08f6f4..9c1fef5 100644
19c65a7
--- a/ui/gtk3/panel.vala
19c65a7
+++ b/ui/gtk3/panel.vala
1faf033
@@ -130,6 +130,10 @@ class Panel : IBus.PanelService {
1faf033
                                null);
1faf033
         });
1faf033
 
1faf033
+        m_settings_general.changed["preload-engine-mode"].connect((key) => {
1faf033
+                update_im_engines();
1faf033
+        });
1faf033
+
1faf033
         m_settings_general.changed["switcher-delay-time"].connect((key) => {
1faf033
                 set_switcher_delay_time();
1faf033
         });
1faf033
@@ -476,7 +480,96 @@ class Panel : IBus.PanelService {
19c65a7
             init_gkbd();
19c65a7
         }
19c65a7
 
1faf033
+        string[] preload_engines =
1faf033
+                m_settings_general.get_strv("preload-engines");
19c65a7
+
1faf033
+        bool preload_engines_inited =
1faf033
+                m_settings_general.get_boolean("preload-engines-inited");
19c65a7
+
19c65a7
+        // Set preload_engines_inited = true for back compatibility
19c65a7
+        if (preload_engines.length != 0 && !preload_engines_inited) {
19c65a7
+                preload_engines_inited = true;
1faf033
+                m_settings_general.set_boolean("preload-engines-inited", true);
19c65a7
+        }
19c65a7
+
19c65a7
         update_xkb_engines();
19c65a7
+
19c65a7
+        // Before update preload_engine_mode, update_xkb_engines() is called
1faf033
+        // because "preload-engine-mode" signal calls update_im_engines().
1faf033
+        if (!preload_engines_inited)
1faf033
+            m_settings_general.set_int("preload-engine-mode",
1faf033
+                                       IBus.PreloadEngineMode.LANG_RELATIVE);
19c65a7
+
19c65a7
+        update_im_engines();
19c65a7
+
1faf033
+        if (!preload_engines_inited)
1faf033
+            m_settings_general.set_boolean("preload-engines-inited", true);
19c65a7
+    }
19c65a7
+
19c65a7
+    private bool set_lang_relative_preload_engines() {
19c65a7
+        string locale = Intl.setlocale(LocaleCategory.CTYPE, null);
19c65a7
+
1faf033
+        if (locale == null)
19c65a7
+            locale = "C";
19c65a7
+
19c65a7
+        string lang = locale.split(".")[0];
19c65a7
+        GLib.List<IBus.EngineDesc> engines = m_bus.list_engines();
19c65a7
+        string[] im_engines = {};
19c65a7
+
19c65a7
+        for (unowned GLib.List<IBus.EngineDesc> p = engines;
19c65a7
+             p != null;
19c65a7
+             p = p.next) {
19c65a7
+            unowned IBus.EngineDesc engine = p.data;
1faf033
+            if (engine.get_language() == lang && engine.get_rank() > 0)
19c65a7
+                im_engines += engine.get_name();
19c65a7
+        }
19c65a7
+
19c65a7
+        lang = lang.split("_")[0];
19c65a7
+        if (im_engines.length == 0) {
19c65a7
+            for (unowned GLib.List<IBus.EngineDesc> p = engines;
19c65a7
+                 p != null;
19c65a7
+                 p = p.next) {
19c65a7
+                unowned IBus.EngineDesc engine = p.data;
1faf033
+                if (engine.get_language() == lang && engine.get_rank() > 0)
19c65a7
+                    im_engines += engine.get_name();
19c65a7
+            }
19c65a7
+        }
19c65a7
+
1faf033
+        if (im_engines.length == 0)
19c65a7
+            return false;
19c65a7
+
1faf033
+        string[] orig_preload_engines =
1faf033
+                m_settings_general.get_strv("preload-engines");
19c65a7
+        string[] preload_engines = {};
19c65a7
+
19c65a7
+        // clear input method engines
19c65a7
+        foreach (string name in orig_preload_engines) {
1faf033
+            if (name.ascii_ncasecmp("xkb:", 4) != 0)
19c65a7
+                continue;
1faf033
+
19c65a7
+            preload_engines += name;
19c65a7
+        }
19c65a7
+
19c65a7
+        foreach (string name in im_engines) {
1faf033
+            if (!(name in preload_engines))
19c65a7
+                preload_engines += name;
19c65a7
+        }
19c65a7
+
19c65a7
+        if ("".joinv(",", orig_preload_engines) !=
1faf033
+            "".joinv(",", preload_engines))
1faf033
+            m_settings_general.set_strv("preload-engines", preload_engines);
19c65a7
+
19c65a7
+        return true;
19c65a7
+    }
19c65a7
+
19c65a7
+    private void update_im_engines() {
1faf033
+        int preload_engine_mode =
1faf033
+                m_settings_general.get_int("preload-engine-mode");
19c65a7
+
1faf033
+        if (preload_engine_mode == IBus.PreloadEngineMode.USER)
19c65a7
+            return;
19c65a7
+
19c65a7
+        set_lang_relative_preload_engines();
19c65a7
     }
19c65a7
 
19c65a7
     private void update_xkb_engines() {
8a795bf
-- 
a208e6b
1.8.0
8a795bf