[gnome-control-center/wip/input-sources: 13/13] region: Use a hand-crafted input sources list



commit 00c095ec7463ba5ad1df893164f4230d9efaed33
Author: Rui Matos <tiagomatos gmail com>
Date:   Wed Apr 18 17:15:32 2012 +0200

    region: Use a hand-crafted input sources list
    
    Instead of asking IBus, we want to use an hand-crafted list of input
    sources that we are sure that a) is intelligible for the user and b)
    lists both an XKB layout and an IBus engine that work together.
    
    For now we just hard-code this list but we might want to move it into
    its own file and maybe even to some other module.
    
    This also removes the dependency on IBus.

 configure.ac                                      |    3 +-
 panels/region/gnome-region-panel-input-chooser.ui |    7 -
 panels/region/gnome-region-panel-input.c          |  393 +++++++++++----------
 3 files changed, 212 insertions(+), 191 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 3f6bdd6..b2a27b0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -113,8 +113,7 @@ PKG_CHECK_MODULES(COLOR_PANEL, $COMMON_MODULES colord >= 0.1.8)
 PKG_CHECK_MODULES(PRINTERS_PANEL, $COMMON_MODULES
                   polkit-gobject-1 >= $POLKIT_REQUIRED_VERSION)
 PKG_CHECK_MODULES(REGION_PANEL, $COMMON_MODULES
-                  polkit-gobject-1 >= $POLKIT_REQUIRED_VERSION
-                  ibus-1.0)
+                  polkit-gobject-1 >= $POLKIT_REQUIRED_VERSION)
 PKG_CHECK_MODULES(SCREEN_PANEL, $COMMON_MODULES)
 PKG_CHECK_MODULES(SOUND_PANEL, $COMMON_MODULES libxml-2.0
                   libcanberra-gtk3 >= $CANBERRA_REQUIRED_VERSION
diff --git a/panels/region/gnome-region-panel-input-chooser.ui b/panels/region/gnome-region-panel-input-chooser.ui
index 8fc2b74..809e7e6 100644
--- a/panels/region/gnome-region-panel-input-chooser.ui
+++ b/panels/region/gnome-region-panel-input-chooser.ui
@@ -3,16 +3,9 @@
   <requires lib="gtk+" version="2.16"/>
   <object class="GtkListStore" id="input_source_model">
     <columns>
-      <!-- column-name id -->
       <column type="gchararray"/>
-      <!-- column-name name -->
       <column type="gchararray"/>
-      <!-- column-name lang -->
       <column type="gchararray"/>
-      <!-- column-name layout -->
-      <column type="gchararray"/>
-      <!-- column-name xkb -->
-      <column type="gboolean"/>
     </columns>
   </object>
   <object class="GtkTreeModelFilter" id="filtered_input_source_model">
diff --git a/panels/region/gnome-region-panel-input.c b/panels/region/gnome-region-panel-input.c
index f465b23..d715715 100644
--- a/panels/region/gnome-region-panel-input.c
+++ b/panels/region/gnome-region-panel-input.c
@@ -26,12 +26,6 @@
 #include <glib.h>
 #include <glib/gi18n.h>
 
-#include <ibus.h>
-/* http://code.google.com/p/ibus/issues/detail?id=1338 */
-#define IBUS_COMPILATION
-#include <ibusutil.h>
-#undef IBUS_COMPILATION
-
 #include "gnome-region-panel-input.h"
 
 #define WID(s) GTK_WIDGET(gtk_builder_get_object (builder, s))
@@ -56,6 +50,115 @@
  * - Allow changing shortcuts ?
  */
 
+struct _InputSource
+{
+  const gchar *layout;
+  const gchar *engine;
+  const gchar *name;
+};
+
+static const struct _InputSource input_sources[] =
+  {
+    { "us", NULL, "English (US)" },
+    { "ad", NULL, "Catalan" },
+    { "af", NULL, "Afghani" },
+    { "ara", NULL, "Arabic" },
+    { "al", NULL, "Albanian" },
+    { "am", NULL, "Armenian" },
+    { "at", NULL, "German (Austria)" },
+    { "az", NULL, "Azerbaijani" },
+    { "by", NULL, "Belarusian" },
+    { "be", NULL, "Belgian" },
+    { "bd", NULL, "Bengali" },
+    { "in", NULL, "Indian" },
+    { "ba", NULL, "Bosnian" },
+    { "br", NULL, "Portuguese (Brazil)" },
+    { "bg", NULL, "Bulgarian" },
+    { "ma", NULL, "Arabic (Morocco)" },
+    { "cm", NULL, "English (Cameroon)" },
+    { "mm", NULL, "Burmese" },
+    { "ca", NULL, "French (Canada)" },
+    { "cd", NULL, "French (Democratic Republic of the Congo)" },
+    { "cn", NULL, "Chinese" },
+    { "hr", NULL, "Croatian" },
+    { "cz", NULL, "Czech" },
+    { "dk", NULL, "Danish" },
+    { "nl", NULL, "Dutch" },
+    { "bt", NULL, "Dzongkha" },
+    { "ee", NULL, "Estonian" },
+    { "ir", NULL, "Persian" },
+    { "iq", NULL, "Iraqi" },
+    { "fo", NULL, "Faroese" },
+    { "fi", NULL, "Finnish" },
+    { "fr", NULL, "French" },
+    { "gh", NULL, "English (Ghana)" },
+    { "gn", NULL, "French (Guinea)" },
+    { "ge", NULL, "Georgian" },
+    { "de", NULL, "German" },
+    { "gr", NULL, "Greek" },
+    { "hu", NULL, "Hungarian" },
+    { "is", NULL, "Icelandic" },
+    { "il", NULL, "Hebrew" },
+    { "it", NULL, "Italian" },
+    { "jp", "anthy", "Japanese" },
+    { "kg", NULL, "Kyrgyz" },
+    { "kh", NULL, "Khmer (Cambodia)" },
+    { "kz", NULL, "Kazakh" },
+    { "la", NULL, "Lao" },
+    { "latam", NULL, "Spanish (Latin American)" },
+    { "lt", NULL, "Lithuanian" },
+    { "lv", NULL, "Latvian" },
+    { "mao", NULL, "Maori" },
+    { "me", NULL, "Montenegrin" },
+    { "mk", NULL, "Macedonian" },
+    { "mt", NULL, "Maltese" },
+    { "mn", NULL, "Mongolian" },
+    { "no", NULL, "Norwegian" },
+    { "pl", NULL, "Polish" },
+    { "pt", NULL, "Portuguese" },
+    { "ro", NULL, "Romanian" },
+    { "ru", NULL, "Russian" },
+    { "rs", NULL, "Serbian" },
+    { "si", NULL, "Slovenian" },
+    { "sk", NULL, "Slovak" },
+    { "es", NULL, "Spanish" },
+    { "se", NULL, "Swedish" },
+    { "ch", NULL, "German (Switzerland)" },
+    { "sy", NULL, "Arabic (Syria)" },
+    { "tj", NULL, "Tajik" },
+    { "lk", NULL, "Sinhala" },
+    { "th", NULL, "Thai" },
+    { "tr", NULL, "Turkish" },
+    { "tw", NULL, "Taiwanese" },
+    { "ua", NULL, "Ukrainian" },
+    { "gb", NULL, "English (UK)" },
+    { "uz", NULL, "Uzbek" },
+    { "vn", NULL, "Vietnamese" },
+    { "kr", "hangul", "Korean" },
+    { "ie", NULL, "Irish" },
+    { "pk", NULL, "Urdu (Pakistan)" },
+    { "mv", NULL, "Dhivehi" },
+    { "za", NULL, "English (South Africa)" },
+    { "epo", NULL, "Esperanto" },
+    { "np", NULL, "Nepali" },
+    { "ng", NULL, "English (Nigeria)" },
+    { "et", NULL, "Amharic" },
+    { "sn", NULL, "Wolof" },
+    { "brai", NULL, "Braille" },
+    { "tm", NULL, "Turkmen" },
+    { "ml", NULL, "Bambara" },
+    { "tz", NULL, "Swahili (Tanzania)" },
+    { "ke", NULL, "Swahili (Kenya)" },
+    { "bw", NULL, "Tswana" },
+    { "ph", NULL, "Filipino" }
+  };
+
+#define GNOME_DESKTOP_INPUT_SOURCES_DIR "org.gnome.desktop.input-sources"
+
+#define KEY_CURRENT_IS     "current"
+#define KEY_INPUT_SOURCES  "sources"
+
+static GSettings *is_settings = NULL;
 
 static GtkWidget *input_chooser_new          (GtkBuilder    *builder);
 static gboolean   input_chooser_get_selected (GtkWidget     *chooser,
@@ -64,193 +167,124 @@ static gboolean   input_chooser_get_selected (GtkWidget     *chooser,
 
 enum
 {
-  COL_NAME,
-  COL_DESC,
-  COL_LANG,
   COL_LAYOUT,
-  COL_XKB
+  COL_ENGINE,
+  COL_NAME
 };
 
-/* IBus interaction {{{1 */
-
-static gchar *
-engine_description (IBusEngineDesc *description, gboolean unique_lang)
+static gboolean
+add_source_to_hash (GtkTreeModel *model,
+                    GtkTreePath  *path,
+                    GtkTreeIter  *iter,
+                    gpointer      data)
 {
-  const gchar *lang;
-  gchar *longname;
-  gchar *desc;
-
-  lang = ibus_get_language_name (ibus_engine_desc_get_language (description));
-
-  if (g_getenv ("DEBUG_IBUS"))
-    return g_strdup_printf ("%s %s/%s/%s/%s", lang,
-                            ibus_engine_desc_get_name (description),
-                            ibus_engine_desc_get_longname (description),
-                            ibus_engine_desc_get_language (description),
-                            ibus_engine_desc_get_layout (description));
-
-  if (unique_lang)
-    return g_strdup (lang);
-
-  if (g_str_has_prefix (ibus_engine_desc_get_name (description), "xkb:layout:"))
-    {
-      if (strcmp (ibus_engine_desc_get_longname (description), lang) == 0)
-        return g_strdup_printf ("%s (xkb)", lang);
-      else
-        return g_strdup (ibus_engine_desc_get_longname (description));
-    }
-
-  longname = g_strdup (ibus_engine_desc_get_longname (description));
-  if (g_str_has_suffix (longname, " (m17n)"))
-    {
-       longname[strlen (longname) - strlen (" (m17n)")] = '\0';
-    }
-
-  desc = g_strdup_printf ("%s (%s)", lang, longname);
+  GHashTable *hash = data;
+  gchar *layout;
 
-  g_free (longname);
+  gtk_tree_model_get (model, iter, COL_LAYOUT, &layout, -1);
+  g_hash_table_insert (hash, layout, GINT_TO_POINTER (1));
 
-  return desc;
+  return FALSE;
 }
 
 static void
 populate_model (GtkListStore *store,
-                gboolean      only_active)
+                GtkListStore *active_sources)
 {
-  IBusBus *bus;
-  GList *list, *l;
-  GList *active_list;
-  IBusEngineDesc *description;
-  const gchar *name;
-  const gchar *lang;
-  gchar *desc;
-  gint count;
-  GtkTreeIter iter;
-  GHashTable *lang_hash;
   GHashTable *active_hash;
+  GtkTreeIter iter;
+  gint i;
 
-  bus = ibus_bus_new ();
-
-  list = ibus_bus_list_engines (bus);
-  active_list = ibus_bus_list_active_engines (bus);
+  active_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
 
-  lang_hash = g_hash_table_new (g_str_hash, g_str_equal);
-  active_hash = g_hash_table_new (g_str_hash, g_str_equal);
+  gtk_tree_model_foreach (GTK_TREE_MODEL (active_sources),
+                          add_source_to_hash,
+                          active_hash);
 
-  /* Figure out which languages occur more than once
-   * for these, showing only the language is not sufficient
-   */
-  for (l = list; l; l = l->next)
+  for (i = 0; i < G_N_ELEMENTS (input_sources); ++i)
     {
-      description = (IBusEngineDesc *)l->data;
-
-      name = ibus_engine_desc_get_name (description);
-      if (g_str_has_prefix (name, "xkb:layout:default:#"))
+      if (g_hash_table_lookup (active_hash, input_sources[i].layout))
         continue;
 
-      lang = ibus_engine_desc_get_language (description);
-      lang = ibus_get_language_name (lang);
-      if (lang == NULL)
-        continue;
-
-      count = GPOINTER_TO_INT (g_hash_table_lookup (lang_hash, lang));
-      count++;
-      g_hash_table_insert (lang_hash, (gpointer)lang, GINT_TO_POINTER (count));
+      gtk_list_store_append (store, &iter);
+      gtk_list_store_set (store, &iter,
+                          COL_LAYOUT, input_sources[i].layout,
+                          COL_ENGINE, input_sources[i].engine,
+                          COL_NAME, input_sources[i].name,
+                          -1);
     }
 
-  if (only_active)
-    {
-      g_list_free (list);
-      list = active_list;
-      active_list = NULL;
-    }
-  else
+  g_hash_table_destroy (active_hash);
+}
+
+static const gchar *
+get_source_name (const gchar *layout,
+                 const gchar *engine)
+{
+  gint i;
+
+  for (i = 0; i < G_N_ELEMENTS (input_sources); ++i)
     {
-      /* We want to skip active engines when
-       * making a list of inactive engines
-       */
-      for (l = active_list; l; l = l->next)
-        {
-          description = (IBusEngineDesc *)l->data;
-          name = ibus_engine_desc_get_name (description);
-          g_hash_table_insert (active_hash, (gpointer)name, (gpointer)name);
-        }
-      g_list_free (active_list);
-      active_list = NULL;
+      if (!g_strcmp0 (layout, input_sources[i].layout) &&
+          !g_strcmp0 (engine, input_sources[i].engine))
+        return input_sources[i].name;
     }
 
-  for (l = list; l; l = l->next)
-    {
-      description = (IBusEngineDesc *)l->data;
+  return NULL;
+}
 
-      name = ibus_engine_desc_get_name (description);
-      if (g_str_has_prefix (name, "xkb:layout:default:#"))
-        continue;
+static void
+populate_with_active_sources (GtkListStore *store)
+{
+  GVariant *sources;
+  GVariantIter iter;
+  const gchar *layout;
+  const gchar *engine;
+  const gchar *name;
+  GtkTreeIter tree_iter;
 
-      if (g_hash_table_lookup (active_hash, name))
-        continue;
+  sources = g_settings_get_value (is_settings, KEY_INPUT_SOURCES);
 
-      lang = ibus_engine_desc_get_language (description);
-      lang = ibus_get_language_name (lang);
-      if (lang == NULL)
+  g_variant_iter_init (&iter, sources);
+  while (g_variant_iter_loop (&iter, "(&sm&s)", &layout, &engine))
+    {
+      name = get_source_name (layout, engine);
+      if (!name)
         continue;
 
-      count = GPOINTER_TO_INT (g_hash_table_lookup (lang_hash, lang));
-      desc = engine_description (description, count <= 1);
-
-      gtk_list_store_append (store, &iter);
-      gtk_list_store_set (store, &iter,
+      gtk_list_store_append (store, &tree_iter);
+      gtk_list_store_set (store, &tree_iter,
+                          COL_LAYOUT, layout,
+                          COL_ENGINE, engine,
                           COL_NAME, name,
-                          COL_DESC, desc,
-                          COL_LANG, lang,
-                          COL_LAYOUT, ibus_engine_desc_get_layout (description),
-                          COL_XKB, g_str_has_prefix (name, "xkb:layout:"),
                           -1);
-      g_free (desc);
     }
 
-  g_hash_table_unref (lang_hash);
-  g_hash_table_unref (active_hash);
-
-  g_list_free (list);
-
-  g_object_unref (bus);
+  g_variant_unref (sources);
 }
 
 static void
-update_ibus_configuration (GtkTreeModel *model)
+update_configuration (GtkTreeModel *model)
 {
   GtkTreeIter iter;
-  IBusBus *bus;
-  IBusConfig *config;
-  gchar **active;
-  gsize n_active;
-  gchar *name;
-  gint i;
+  gchar *layout;
+  gchar *engine;
+  GVariantBuilder builder;
+
+  g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(sms)"));
 
-  n_active = gtk_tree_model_iter_n_children (model, NULL);
-  active = g_new0 (gchar *, n_active + 1);
   gtk_tree_model_get_iter_first (model, &iter);
-  i = 0;
   do {
-    gtk_tree_model_get (model, &iter, COL_NAME, &name, -1);
-     active[i++] = name;
+    gtk_tree_model_get (model, &iter,
+                        COL_LAYOUT, &layout,
+                        COL_ENGINE, &engine,
+                        -1);
+    g_variant_builder_add (&builder, "(sms)", layout, engine);
+    g_free (layout);
+    g_free (engine);
   } while (gtk_tree_model_iter_next (model, &iter));
-  active[n_active] = NULL;
-
-  bus = ibus_bus_new ();
-  config = ibus_bus_get_config (bus);
-
-  if (!ibus_config_set_value (config,
-                              "general", "preload_engines",
-                              g_variant_new_strv ((const gchar * const *)active, -1)))
-    {
-      g_warning ("Failed to update IBus configuration");
-    }
-
-  g_strfreev (active);
 
-  g_object_unref (bus);
+  g_settings_set_value (is_settings, KEY_INPUT_SOURCES, g_variant_builder_end (&builder));
 }
 
 /* List handling {{{1 */
@@ -341,18 +375,14 @@ chooser_response (GtkWidget *chooser, gint response_id, gpointer data)
           GtkTreeView *my_tv;
           GtkListStore *my_model;
           GtkTreeIter my_iter;
-          gchar *name;
-          gchar *desc;
-          gchar *lang;
           gchar *layout;
-          gboolean xkb;
+          gchar *engine;
+          gchar *name;
 
           gtk_tree_model_get (model, &iter,
-                              COL_NAME, &name,
-                              COL_DESC, &desc,
-                              COL_LANG, &lang,
                               COL_LAYOUT, &layout,
-                              COL_XKB, &xkb,
+                              COL_ENGINE, &engine,
+                              COL_NAME, &name,
                               -1);
 
           my_tv = GTK_TREE_VIEW (WID ("active_input_sources"));
@@ -361,22 +391,19 @@ chooser_response (GtkWidget *chooser, gint response_id, gpointer data)
           gtk_list_store_append (my_model, &my_iter);
 
           gtk_list_store_set (my_model, &my_iter,
-                              COL_NAME, name,
-                              COL_DESC, desc,
-                              COL_LANG, lang,
                               COL_LAYOUT, layout,
-                              COL_XKB, xkb,
+                              COL_ENGINE, engine,
+                              COL_NAME, name,
                               -1);
 
           g_free (name);
-          g_free (desc);
-          g_free (lang);
+          g_free (engine);
           g_free (layout);
 
           gtk_tree_selection_select_iter (gtk_tree_view_get_selection (my_tv), &my_iter);
 
           update_button_sensitivity (builder);
-          update_ibus_configuration (GTK_TREE_MODEL (my_model));
+          update_configuration (GTK_TREE_MODEL (my_model));
         }
       else
         {
@@ -424,7 +451,7 @@ remove_selected_input (GtkButton *button, gpointer data)
   gtk_tree_path_free (path);
 
   update_button_sensitivity (builder);
-  update_ibus_configuration (model);
+  update_configuration (model);
 }
 
 static void
@@ -451,7 +478,7 @@ move_selected_input_up (GtkButton *button, gpointer data)
   gtk_tree_path_free (path);
 
   update_button_sensitivity (builder);
-  update_ibus_configuration (model);
+  update_configuration (model);
 }
 
 static void
@@ -477,7 +504,7 @@ move_selected_input_down (GtkButton *button, gpointer data)
   gtk_tree_path_free (path);
 
   update_button_sensitivity (builder);
-  update_ibus_configuration (model);
+  update_configuration (model);
 }
 
 static void
@@ -539,20 +566,20 @@ setup_input_tabs (GtkBuilder    *builder,
   gchar *next = NULL;
   GtkWidget *label;
 
-  ibus_init ();
+  is_settings = g_settings_new (GNOME_DESKTOP_INPUT_SOURCES_DIR);
 
   /* set up the list of active inputs */
   treeview = WID("active_input_sources");
   column = gtk_tree_view_column_new ();
   cell = gtk_cell_renderer_text_new ();
   gtk_tree_view_column_pack_start (column, cell, TRUE);
-  gtk_tree_view_column_add_attribute (column, cell, "text", COL_DESC);
+  gtk_tree_view_column_add_attribute (column, cell, "text", COL_NAME);
   gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
 
-  /* id, name, language, layout, xkb? */
-  store = gtk_list_store_new (5, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
+  /* layout, engine, name */
+  store = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
 
-  populate_model (store, TRUE);
+  populate_with_active_sources (store);
 
   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
   g_signal_connect_swapped (selection, "changed",
@@ -692,7 +719,7 @@ filter_func (GtkTreeModel *model,
              GtkTreeIter  *iter,
              gpointer      data)
 {
-  gchar *desc = NULL;
+  gchar *name = NULL;
   gchar **pattern;
   gboolean rv = TRUE;
 
@@ -700,13 +727,13 @@ filter_func (GtkTreeModel *model,
     return TRUE;
 
   gtk_tree_model_get (model, iter,
-                      COL_DESC, &desc,
+                      COL_NAME, &name,
                       -1);
 
   pattern = search_pattern_list;
   do {
     gboolean is_pattern_found = FALSE;
-    gchar *udesc = g_utf8_strup (desc, -1);
+    gchar *udesc = g_utf8_strup (name, -1);
     if (udesc != NULL && g_strstr_len (udesc, -1, *pattern))
       {
         is_pattern_found = TRUE;
@@ -721,7 +748,7 @@ filter_func (GtkTreeModel *model,
 
   } while (*++pattern != NULL);
 
-  g_free (desc);
+  g_free (name);
 
   return rv;
 }
@@ -752,9 +779,9 @@ input_chooser_new (GtkBuilder *main_builder)
   g_object_set_data (G_OBJECT (chooser),
                      "filtered_input_source_list", filtered_list);
   visible_column =
-    gtk_tree_view_column_new_with_attributes ("Layout",
+    gtk_tree_view_column_new_with_attributes ("Input Sources",
                                               gtk_cell_renderer_text_new (),
-                                              "text", COL_DESC,
+                                              "text", COL_NAME,
                                               NULL);
 
   gtk_window_set_transient_for (GTK_WINDOW (chooser),
@@ -778,10 +805,12 @@ input_chooser_new (GtkBuilder *main_builder)
   model =
     GTK_LIST_STORE (gtk_builder_get_object (builder, "input_source_model"));
 
-  populate_model (model, FALSE);
+  populate_model (model,
+                  GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (gtk_builder_get_object (main_builder,
+                                                                                                  "active_input_sources")))));
 
   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
-                                        COL_DESC, GTK_SORT_ASCENDING);
+                                        COL_NAME, GTK_SORT_ASCENDING);
 
   gtk_tree_model_filter_set_visible_func (filtered_model,
                                           filter_func,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]