[gnome-control-center/wip/region-panel: 39/39] region: New 'Add Input Source' dialog design
- From: Rui Matos <rtcm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-control-center/wip/region-panel: 39/39] region: New 'Add Input Source' dialog design
- Date: Sun, 10 Feb 2013 01:40:09 +0000 (UTC)
commit 0e1fa1fc779ee5027e1093e4c5c6c5158db6e297
Author: Rui Matos <tiagomatos gmail com>
Date: Wed Feb 6 19:41:01 2013 +0100
region: New 'Add Input Source' dialog design
panels/region/cc-input-chooser.c | 703 ++++++++++++++++++++++++++++----------
panels/region/cc-input-chooser.h | 2 +
panels/region/cc-region-panel.c | 24 +-
panels/region/input-chooser.ui | 164 +++------
4 files changed, 605 insertions(+), 288 deletions(-)
---
diff --git a/panels/region/cc-input-chooser.c b/panels/region/cc-input-chooser.c
index b250cc3..7f521c6 100644
--- a/panels/region/cc-input-chooser.c
+++ b/panels/region/cc-input-chooser.c
@@ -21,6 +21,10 @@
#include <config.h>
#include <glib/gi18n.h>
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+#include <libgnome-desktop/gnome-languages.h>
+
+#include "egg-list-box/egg-list-box.h"
#include "cc-input-chooser.h"
#ifdef HAVE_IBUS
@@ -31,192 +35,500 @@
#define INPUT_SOURCE_TYPE_XKB "xkb"
#define INPUT_SOURCE_TYPE_IBUS "ibus"
+typedef struct {
+ /* Not owned */
+ GtkWidget *filter_entry;
+ GtkWidget *list;
+ GtkWidget *scrolledwindow;
+ GtkWidget *back_button;
+ GnomeXkbInfo *xkb_info;
+ GHashTable *ibus_engines;
+
+ /* Owned */
+ GHashTable *locales;
+ GHashTable *locales_by_language;
+} CcInputChooserPrivate;
+
+#define GET_PRIVATE(chooser) ((CcInputChooserPrivate *) g_object_get_data (G_OBJECT (chooser), "private"))
#define WID(name) ((GtkWidget *) gtk_builder_get_object (builder, name))
-enum {
- NAME_COLUMN,
- TYPE_COLUMN,
- ID_COLUMN,
- SETUP_COLUMN,
- N_COLUMNS
-};
+typedef struct {
+ gchar *id;
+ const gchar *default_input_source_type;
+ const gchar *default_input_source_id;
+ GHashTable *layout_ids;
+ GHashTable *engine_ids;
+} LocaleInfo;
static void
-filter_clear (GtkEntry *entry,
- GtkEntryIconPosition icon_pos,
- GdkEvent *event,
- gpointer user_data)
+locale_info_free (gpointer data)
{
- gtk_entry_set_text (entry, "");
-}
+ LocaleInfo *info = data;
-static gchar **search_pattern_list;
+ g_free (info->id);
+ g_hash_table_destroy (info->layout_ids);
+ g_hash_table_destroy (info->engine_ids);
+ g_free (info);
+}
-static void
-filter_changed (GtkBuilder *builder)
+static GtkWidget *
+padded_label_new (const gchar *text)
{
- GtkTreeModelFilter *filtered_model;
- GtkTreeView *tree_view;
- GtkTreeSelection *selection;
- GtkTreeIter selected_iter;
- GtkWidget *filter_entry;
- const gchar *pattern;
- gchar *upattern;
+ GtkWidget *widget;
+ GtkWidget *label;
- filter_entry = WID ("input_source_filter");
- pattern = gtk_entry_get_text (GTK_ENTRY (filter_entry));
- upattern = g_utf8_strup (pattern, -1);
- if (!g_strcmp0 (pattern, ""))
- g_object_set (G_OBJECT (filter_entry),
- "secondary-icon-name", "edit-find-symbolic",
- "secondary-icon-activatable", FALSE,
- "secondary-icon-sensitive", FALSE,
- NULL);
- else
- g_object_set (G_OBJECT (filter_entry),
- "secondary-icon-name", "edit-clear-symbolic",
- "secondary-icon-activatable", TRUE,
- "secondary-icon-sensitive", TRUE,
- NULL);
+ widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
- if (search_pattern_list != NULL)
- g_strfreev (search_pattern_list);
+ label = gtk_label_new (text);
+ gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+ gtk_widget_set_margin_left (label, 20);
+ gtk_widget_set_margin_right (label, 20);
+ gtk_widget_set_margin_top (label, 6);
+ gtk_widget_set_margin_bottom (label, 6);
+ gtk_box_pack_start (GTK_BOX (widget), label, TRUE, TRUE, 0);
- search_pattern_list = g_strsplit (upattern, " ", -1);
- g_free (upattern);
- filtered_model = GTK_TREE_MODEL_FILTER (gtk_builder_get_object (builder, "filtered_input_source_model"));
- gtk_tree_model_filter_refilter (filtered_model);
+ return widget;
+}
- tree_view = GTK_TREE_VIEW (WID ("filtered_input_source_list"));
- selection = gtk_tree_view_get_selection (tree_view);
- if (gtk_tree_selection_get_selected (selection, NULL, &selected_iter))
+static GtkWidget *
+input_source_widget_new (GtkWidget *chooser,
+ const gchar *type,
+ const gchar *id)
+{
+ CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
+ GtkWidget *widget;
+
+ if (g_str_equal (type, INPUT_SOURCE_TYPE_XKB))
{
- GtkTreePath *path = gtk_tree_model_get_path (GTK_TREE_MODEL (filtered_model),
- &selected_iter);
- gtk_tree_view_scroll_to_cell (tree_view, path, NULL, TRUE, 0.5, 0.5);
- gtk_tree_path_free (path);
+ const gchar *display_name;
+
+ gnome_xkb_info_get_layout_info (priv->xkb_info, id, &display_name, NULL, NULL, NULL);
+
+ widget = padded_label_new (display_name);
+ g_object_set_data (G_OBJECT (widget), "name", (gpointer) display_name);
}
- else
+ else if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS))
+ {
+#ifdef HAVE_IBUS
+ gchar *display_name;
+
+ display_name = engine_get_display_name (g_hash_table_lookup (priv->ibus_engines, id));
+
+ widget = padded_label_new (display_name);
+ g_object_set_data_full (G_OBJECT (widget), "name", display_name, g_free);
+#else
+ widget = NULL;
+#endif
+ }
+
+ if (widget)
{
- GtkTreeIter iter;
- if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (filtered_model), &iter))
- gtk_tree_selection_select_iter (selection, &iter);
+ g_object_set_data (G_OBJECT (widget), "type", (gpointer) type);
+ g_object_set_data (G_OBJECT (widget), "id", (gpointer) id);
}
+
+ return widget;
}
-static void
-selection_changed (GtkTreeSelection *selection,
- GtkBuilder *builder)
+static gint
+sort_input_sources (gconstpointer a,
+ gconstpointer b,
+ gpointer data)
{
- gtk_widget_set_sensitive (WID ("ok-button"),
- gtk_tree_selection_get_selected (selection, NULL, NULL));
+ const gchar *la;
+ const gchar *lb;
+
+ if (g_object_get_data (G_OBJECT (a), "default"))
+ return -1;
+
+ if (g_object_get_data (G_OBJECT (b), "default"))
+ return 1;
+
+ la = g_object_get_data (G_OBJECT (a), "name");
+ lb = g_object_get_data (G_OBJECT (b), "name");
+
+ return g_strcmp0 (la, lb);
}
static void
-row_activated (GtkTreeView *tree_view,
- GtkTreePath *path,
- GtkTreeViewColumn *column,
- GtkBuilder *builder)
+show_input_sources_for_locale (GtkWidget *chooser,
+ LocaleInfo *info)
{
- GtkWidget *add_button;
- GtkWidget *dialog;
+ CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
+ GtkWidget *widget;
+ GHashTableIter iter;
+ const gchar *id;
+
+ gtk_container_foreach (GTK_CONTAINER (priv->list),
+ (GtkCallback) gtk_widget_destroy,
+ NULL);
+ egg_list_box_set_sort_func (EGG_LIST_BOX (priv->list), sort_input_sources, chooser, NULL);
+ egg_list_box_set_selection_mode (EGG_LIST_BOX (priv->list), GTK_SELECTION_SINGLE);
+
+ if (info->default_input_source_type)
+ {
+ widget = input_source_widget_new (chooser,
+ info->default_input_source_type,
+ info->default_input_source_id);
+ if (widget)
+ {
+ g_object_set_data (G_OBJECT (widget), "default", GINT_TO_POINTER (TRUE));
+ gtk_container_add (GTK_CONTAINER (priv->list), widget);
+ }
+ }
- add_button = WID ("ok-button");
- dialog = WID ("input_source_chooser");
- if (gtk_widget_is_sensitive (add_button))
- gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+ g_hash_table_iter_init (&iter, info->layout_ids);
+ while (g_hash_table_iter_next (&iter, (gpointer *) &id, NULL))
+ {
+ if (g_strcmp0 (info->default_input_source_type, INPUT_SOURCE_TYPE_XKB) == 0 &&
+ g_strcmp0 (info->default_input_source_id, id) == 0)
+ continue;
+
+ widget = input_source_widget_new (chooser, INPUT_SOURCE_TYPE_XKB, id);
+ if (widget)
+ gtk_container_add (GTK_CONTAINER (priv->list), widget);
+ }
+
+ g_hash_table_iter_init (&iter, info->engine_ids);
+ while (g_hash_table_iter_next (&iter, (gpointer *) &id, NULL))
+ {
+ if (g_strcmp0 (info->default_input_source_type, INPUT_SOURCE_TYPE_IBUS) == 0 &&
+ g_strcmp0 (info->default_input_source_id, id) == 0)
+ continue;
+
+ widget = input_source_widget_new (chooser, INPUT_SOURCE_TYPE_IBUS, id);
+ if (widget)
+ gtk_container_add (GTK_CONTAINER (priv->list), widget);
+ }
+
+ gtk_widget_show_all (priv->list);
+ gtk_widget_grab_focus (priv->filter_entry);
+ gtk_widget_show (priv->back_button);
}
static void
-entry_activated (GtkBuilder *builder,
- gpointer data)
+child_activated (EggListBox *box,
+ GtkWidget *child,
+ GtkWidget *chooser)
{
- row_activated (NULL, NULL, NULL, builder);
+ gpointer data;
+
+ if (!child)
+ return;
+
+ data = g_object_get_data (G_OBJECT (child), "locale-info");
+ if (data)
+ {
+ show_input_sources_for_locale (chooser, (LocaleInfo *) data);
+ return;
+ }
}
-static gboolean
-filter_func (GtkTreeModel *model,
- GtkTreeIter *iter,
- gpointer data)
+static gint
+sort_locales (gconstpointer a,
+ gconstpointer b,
+ gpointer data)
{
- gchar *name = NULL;
- gchar **pattern;
- gboolean rv = TRUE;
-
- if (search_pattern_list == NULL || search_pattern_list[0] == NULL)
- return TRUE;
-
- gtk_tree_model_get (model, iter,
- NAME_COLUMN, &name,
- -1);
-
- pattern = search_pattern_list;
- do {
- gboolean is_pattern_found = FALSE;
- gchar *udesc = g_utf8_strup (name, -1);
- if (udesc != NULL && g_strstr_len (udesc, -1, *pattern))
- {
- is_pattern_found = TRUE;
- }
- g_free (udesc);
-
- if (!is_pattern_found)
- {
- rv = FALSE;
- break;
- }
-
- } while (*++pattern != NULL);
- g_free (name);
-
- return rv;
+ const gchar *id;
+ const gchar *la;
+ const gchar *lb;
+
+ id = g_object_get_data (G_OBJECT (a), "locale-id");
+ if (!id[0])
+ return 1;
+
+ id = g_object_get_data (G_OBJECT (b), "locale-id");
+ if (!id[0])
+ return -1;
+
+ la = g_object_get_data (G_OBJECT (a), "locale-name");
+ lb = g_object_get_data (G_OBJECT (b), "locale-name");
+
+ return g_strcmp0 (la, lb);
}
-static void
-populate_model (GtkListStore *store,
- GnomeXkbInfo *xkb_info,
- GHashTable *ibus_engines)
+static GtkWidget *
+locale_widget_new (const gchar *locale_id)
{
- GtkTreeIter iter;
- const gchar *name;
- GList *sources, *tmp;
+ gchar *locale_name;
+ gchar *locale_untranslated_name;
+ GtkWidget *widget;
+ GtkWidget *arrow;
+ const gchar *icon_name;
- sources = gnome_xkb_info_get_all_layouts (xkb_info);
- for (tmp = sources; tmp; tmp = tmp->next)
+ if (locale_id[0])
+ {
+ locale_name = gnome_get_language_from_locale (locale_id, NULL);
+ locale_untranslated_name = gnome_get_country_from_locale (locale_id, "C");
+ }
+ else
{
- gnome_xkb_info_get_layout_info (xkb_info, (const gchar *)tmp->data,
- &name, NULL, NULL, NULL);
- gtk_list_store_append (store, &iter);
- gtk_list_store_set (store, &iter,
- NAME_COLUMN, name,
- TYPE_COLUMN, INPUT_SOURCE_TYPE_XKB,
- ID_COLUMN, tmp->data,
- -1);
+ locale_name = g_strdup (_("Other"));
+ locale_untranslated_name = g_strdup ("");
}
- g_list_free (sources);
+
+ widget = padded_label_new (locale_name);
+
+ if (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL)
+ icon_name = "go-previous-symbolic";
+ else
+ icon_name = "go-next-symbolic";
+
+ arrow = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU);
+ gtk_widget_set_margin_left (arrow, 20);
+ gtk_widget_set_margin_right (arrow, 20);
+ gtk_widget_set_margin_top (arrow, 6);
+ gtk_widget_set_margin_bottom (arrow, 6);
+ gtk_box_pack_start (GTK_BOX (widget), arrow, FALSE, TRUE, 0);
+
+ g_object_set_data_full (G_OBJECT (widget), "locale-id", g_strdup (locale_id), g_free);
+ g_object_set_data_full (G_OBJECT (widget), "locale-name", locale_name, g_free);
+ g_object_set_data_full (G_OBJECT (widget), "locale-untranslated-name", locale_untranslated_name, g_free);
+
+ return widget;
+}
+
+static void
+show_locale_widgets (GtkWidget *chooser)
+{
+ CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
+ LocaleInfo *info;
+ GtkWidget *widget;
+ GHashTableIter iter;
+
+ gtk_container_foreach (GTK_CONTAINER (priv->list),
+ (GtkCallback) gtk_widget_destroy,
+ NULL);
+ egg_list_box_set_sort_func (EGG_LIST_BOX (priv->list), sort_locales, chooser, NULL);
+ egg_list_box_set_selection_mode (EGG_LIST_BOX (priv->list), GTK_SELECTION_NONE);
+
+ g_hash_table_iter_init (&iter, priv->locales);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &info))
+ {
+ if (!info->default_input_source_type &&
+ !g_hash_table_size (info->layout_ids) &&
+ !g_hash_table_size (info->engine_ids))
+ continue;
+
+ widget = locale_widget_new (info->id);
+ gtk_container_add (GTK_CONTAINER (priv->list), widget);
+
+ g_object_set_data (G_OBJECT (widget), "locale-info", info);
+ }
+
+ gtk_widget_show_all (priv->list);
+ gtk_widget_grab_focus (priv->filter_entry);
+ gtk_widget_hide (priv->back_button);
+}
#ifdef HAVE_IBUS
- if (ibus_engines)
+static void
+get_ibus_locale_infos (GtkWidget *chooser)
+{
+ CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
+ GHashTableIter iter;
+ LocaleInfo *info;
+ const gchar *engine_id;
+ IBusEngineDesc *engine;
+
+ if (!priv->ibus_engines)
+ return;
+
+ g_hash_table_iter_init (&iter, priv->ibus_engines);
+ while (g_hash_table_iter_next (&iter, (gpointer *) &engine_id, (gpointer *) &engine))
{
- gchar *display_name;
+ gchar *lang_code = NULL;
+ gchar *country_code = NULL;
+ const gchar *ibus_locale = ibus_engine_desc_get_language (engine);
- sources = g_hash_table_get_keys (ibus_engines);
- for (tmp = sources; tmp; tmp = tmp->next)
+ if (gnome_parse_locale (ibus_locale, &lang_code, &country_code, NULL, NULL) &&
+ lang_code != NULL &&
+ country_code != NULL)
+ {
+ gchar *locale = g_strdup_printf ("%s_%s.utf8", lang_code, country_code);
+
+ info = g_hash_table_lookup (priv->locales, locale);
+ if (info)
+ {
+ const gchar *type, *id;
+
+ g_hash_table_add (info->engine_ids, (gpointer) engine_id);
+
+ if (gnome_get_input_source_from_locale (locale, &type, &id) &&
+ g_str_equal (type, INPUT_SOURCE_TYPE_IBUS) &&
+ g_str_equal (id, engine_id))
+ {
+ info->default_input_source_type = type;
+ info->default_input_source_id = id;
+ }
+ }
+ else
+ {
+ g_warning ("IBus returned locale '%s' that we don't know about", locale);
+ }
+
+ g_free (locale);
+ }
+ else if (lang_code != NULL)
+ {
+ GHashTableIter iter;
+ GHashTable *locales_for_language;
+ gchar *language;
+
+ language = gnome_get_language_from_code (lang_code, NULL);
+ if (language)
+ locales_for_language = g_hash_table_lookup (priv->locales_by_language, language);
+ else
+ locales_for_language = NULL;
+ g_free (language);
+
+ if (locales_for_language)
+ {
+ g_hash_table_iter_init (&iter, locales_for_language);
+ while (g_hash_table_iter_next (&iter, (gpointer *) &info, NULL))
+ g_hash_table_add (info->engine_ids, (gpointer) engine_id);
+ }
+ }
+ else
{
- display_name = engine_get_display_name (g_hash_table_lookup (ibus_engines, tmp->data));
- gtk_list_store_append (store, &iter);
- gtk_list_store_set (store, &iter,
- NAME_COLUMN, display_name,
- TYPE_COLUMN, INPUT_SOURCE_TYPE_IBUS,
- ID_COLUMN, tmp->data,
- -1);
- g_free (display_name);
+ /* Add it to the "Other" locale */
+ info = g_hash_table_lookup (priv->locales, "");
+ g_hash_table_add (info->engine_ids, (gpointer) engine_id);
}
- g_list_free (sources);
+
+ g_free (country_code);
+ g_free (lang_code);
}
+}
#endif
+
+static void
+add_locale_to_table (GHashTable *table,
+ const gchar *lang_code,
+ LocaleInfo *info)
+{
+ GHashTable *set;
+ gchar *language;
+
+ language = gnome_get_language_from_code (lang_code, NULL);
+
+ set = g_hash_table_lookup (table, language);
+ if (!set)
+ {
+ set = g_hash_table_new (NULL, NULL);
+ g_hash_table_replace (table, g_strdup (language), set);
+ }
+ g_hash_table_add (set, info);
+
+ g_free (language);
+}
+
+static void
+add_ids_to_set (GHashTable *set,
+ GList *list)
+{
+ while (list)
+ {
+ g_hash_table_add (set, list->data);
+ list = list->next;
+ }
}
+static void
+get_locale_infos (GtkWidget *chooser)
+{
+ CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
+ GHashTable *layouts_with_locale;
+ LocaleInfo *info;
+ gchar **locale_ids;
+ gchar **locale;
+ GList *list, *l;
+
+ priv->locales = g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL, locale_info_free);
+ priv->locales_by_language = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, (GDestroyNotify) g_hash_table_destroy);
+
+ layouts_with_locale = g_hash_table_new (g_str_hash, g_str_equal);
+
+ locale_ids = gnome_get_all_locales ();
+ for (locale = locale_ids; *locale; ++locale)
+ {
+ const gchar *type, *id;
+ gchar *lang_code, *country_code;
+ gchar *simple_locale;
+
+ if (!gnome_parse_locale (*locale, &lang_code, &country_code, NULL, NULL))
+ continue;
+
+ simple_locale = g_strdup_printf ("%s_%s.utf8", lang_code, country_code);
+ if (g_hash_table_contains (priv->locales, simple_locale))
+ {
+ g_free (simple_locale);
+ g_free (country_code);
+ g_free (lang_code);
+ continue;
+ }
+
+ info = g_new0 (LocaleInfo, 1);
+ info->id = simple_locale; /* Take ownership */
+ g_hash_table_replace (priv->locales, simple_locale, info);
+ add_locale_to_table (priv->locales_by_language, lang_code, info);
+
+ if (gnome_get_input_source_from_locale (simple_locale, &type, &id) &&
+ g_str_equal (type, INPUT_SOURCE_TYPE_XKB))
+ {
+ g_hash_table_add (layouts_with_locale, (gpointer) id);
+ info->default_input_source_type = type;
+ info->default_input_source_id = id;
+ }
+
+ /* We don't own these ids */
+ info->layout_ids = g_hash_table_new (g_str_hash, g_str_equal);
+ info->engine_ids = g_hash_table_new (g_str_hash, g_str_equal);
+
+ list = gnome_xkb_info_get_layouts_for_language (priv->xkb_info, lang_code);
+ add_ids_to_set (info->layout_ids, list);
+ add_ids_to_set (layouts_with_locale, list);
+ g_list_free (list);
+
+ list = gnome_xkb_info_get_layouts_for_country (priv->xkb_info, country_code);
+ add_ids_to_set (info->layout_ids, list);
+ add_ids_to_set (layouts_with_locale, list);
+ g_list_free (list);
+
+ g_free (lang_code);
+ g_free (country_code);
+ }
+ /* String ownership went to the LocaleInfo structs */
+ g_strfreev (locale_ids);
+
+ /* Add a "Other" locale to hold the remaining input sources */
+ info = g_new0 (LocaleInfo, 1);
+ info->id = g_strdup ("");
+ g_hash_table_replace (priv->locales, info->id, info);
+
+ info->layout_ids = g_hash_table_new (g_str_hash, g_str_equal);
+ info->engine_ids = g_hash_table_new (g_str_hash, g_str_equal);
+
+ list = gnome_xkb_info_get_all_layouts (priv->xkb_info);
+ for (l = list; l; l = l->next)
+ if (!g_hash_table_contains (layouts_with_locale, l->data))
+ g_hash_table_add (info->layout_ids, l->data);
+ g_list_free (list);
+
+ g_hash_table_destroy (layouts_with_locale);
+}
+
+static void
+cc_input_chooser_private_free (gpointer data)
+{
+ CcInputChooserPrivate *priv = data;
+
+ g_hash_table_destroy (priv->locales);
+ g_hash_table_destroy (priv->locales_by_language);
+ g_free (priv);
+}
GtkWidget *
cc_input_chooser_new (GtkWindow *main_window,
@@ -225,21 +537,52 @@ cc_input_chooser_new (GtkWindow *main_window,
{
GtkBuilder *builder;
GtkWidget *chooser;
- GtkWidget *filtered_list;
- GtkWidget *filter_entry;
- GtkTreeViewColumn *visible_column;
- GtkTreeSelection *selection;
- GtkListStore *model;
- GtkTreeModelFilter *filtered_model;
- GtkTreeIter iter;
+ CcInputChooserPrivate *priv;
+ GError *error = NULL;
builder = gtk_builder_new ();
- gtk_builder_add_from_resource (builder,
- "/org/gnome/control-center/region/input-chooser.ui",
- NULL);
- chooser = WID ("input_source_chooser");
+ gtk_builder_add_from_resource (builder, "/org/gnome/control-center/region/input-chooser.ui", &error);
+ if (error)
+ {
+ g_object_unref (builder);
+ g_warning ("failed to load input chooser: %s", error->message);
+ g_error_free (error);
+ return NULL;
+ }
+ chooser = WID ("input-dialog");
+ priv = g_new0 (CcInputChooserPrivate, 1);
+ g_object_set_data_full (G_OBJECT (chooser), "private", priv, cc_input_chooser_private_free);
g_object_set_data_full (G_OBJECT (chooser), "builder", builder, g_object_unref);
+ priv->xkb_info = xkb_info;
+ priv->ibus_engines = ibus_engines;
+
+ priv->filter_entry = WID ("filter-entry");
+ priv->list = WID ("list");
+ priv->scrolledwindow = WID ("scrolledwindow");
+ priv->back_button = WID ("back-button");
+
+ gtk_widget_set_size_request (chooser, 400, 500);
+ gtk_window_set_resizable (GTK_WINDOW (chooser), TRUE);
+
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scrolledwindow),
+ GTK_POLICY_NEVER,
+ GTK_POLICY_AUTOMATIC);
+
+ egg_list_box_set_adjustment (EGG_LIST_BOX (priv->list),
+ gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scrolledwindow)));
+ g_signal_connect (priv->list, "child-activated", G_CALLBACK (child_activated), chooser);
+
+ gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (WID ("action-area")), priv->back_button, TRUE);
+ g_signal_connect_swapped (priv->back_button, "clicked", G_CALLBACK (show_locale_widgets), chooser);
+
+ get_locale_infos (chooser);
+#ifdef HAVE_IBUS
+ get_ibus_locale_infos (chooser);
+#endif
+ show_locale_widgets (chooser);
+
+#if 0
filtered_list = WID ("filtered_input_source_list");
filter_entry = WID ("input_source_filter");
@@ -251,8 +594,6 @@ cc_input_chooser_new (GtkWindow *main_window,
"text", NAME_COLUMN,
NULL);
- gtk_window_set_transient_for (GTK_WINDOW (chooser), main_window);
-
gtk_tree_view_append_column (GTK_TREE_VIEW (filtered_list),
visible_column);
/* We handle searching ourselves, thank you. */
@@ -291,36 +632,54 @@ cc_input_chooser_new (GtkWindow *main_window,
g_signal_connect (G_OBJECT (filtered_list), "row-activated",
G_CALLBACK (row_activated), builder);
+#endif
- gtk_widget_grab_focus (filter_entry);
-
- gtk_widget_show (chooser);
+ gtk_window_set_transient_for (GTK_WINDOW (chooser), main_window);
return chooser;
}
+void
+cc_input_chooser_set_ibus_engines (GtkWidget *chooser,
+ GHashTable *ibus_engines)
+{
+#ifdef HAVE_IBUS
+ CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
+
+ /* This should only be called once when IBus shows up in case it
+ wasn't up yet when the user opened the input chooser dialog. */
+ g_return_if_fail (priv->ibus_engines == NULL);
+
+ priv->ibus_engines = ibus_engines;
+ get_ibus_locale_infos (chooser);
+ show_locale_widgets (chooser);
+#endif
+}
+
gboolean
cc_input_chooser_get_selected (GtkWidget *chooser,
gchar **type,
gchar **id,
gchar **name)
{
- GtkWidget *tv;
- GtkTreeModel *model;
- GtkTreeIter iter;
- GtkTreeSelection *selection;
-
- tv = g_object_get_data (G_OBJECT (chooser), "filtered_input_source_list");
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tv));
- if (gtk_tree_selection_get_selected (selection, &model, &iter))
- {
- gtk_tree_model_get (model, &iter,
- TYPE_COLUMN, type,
- ID_COLUMN, id,
- NAME_COLUMN, name,
- -1);
- return TRUE;
- }
+ CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
+ GtkWidget *selected;
+ const gchar *t, *i, *n;
+
+ selected = egg_list_box_get_selected_child (EGG_LIST_BOX (priv->list));
+ if (!selected)
+ return FALSE;
+
+ t = g_object_get_data (G_OBJECT (selected), "type");
+ i = g_object_get_data (G_OBJECT (selected), "id");
+ n = g_object_get_data (G_OBJECT (selected), "name");
+
+ if (!t || !i || !n)
+ return FALSE;
+
+ *type = g_strdup (t);
+ *id = g_strdup (i);
+ *name = g_strdup (n);
- return FALSE;
+ return TRUE;
}
diff --git a/panels/region/cc-input-chooser.h b/panels/region/cc-input-chooser.h
index 394db82..05fa448 100644
--- a/panels/region/cc-input-chooser.h
+++ b/panels/region/cc-input-chooser.h
@@ -32,6 +32,8 @@ G_BEGIN_DECLS
GtkWidget *cc_input_chooser_new (GtkWindow *parent,
GnomeXkbInfo *xkb_info,
GHashTable *ibus_engines);
+void cc_input_chooser_set_ibus_engines (GtkWidget *chooser,
+ GHashTable *ibus_engines);
gboolean cc_input_chooser_get_selected (GtkWidget *chooser,
gchar **type,
gchar **id,
diff --git a/panels/region/cc-region-panel.c b/panels/region/cc-region-panel.c
index e39afa2..1242c46 100644
--- a/panels/region/cc-region-panel.c
+++ b/panels/region/cc-region-panel.c
@@ -527,6 +527,19 @@ update_ibus_active_sources (CcRegionPanel *self)
}
static void
+update_input_chooser (CcRegionPanel *self)
+{
+ CcRegionPanelPrivate *priv = self->priv;
+ GtkWidget *chooser;
+
+ chooser = g_object_get_data (G_OBJECT (self), "input-chooser");
+ if (!chooser)
+ return;
+
+ cc_input_chooser_set_ibus_engines (chooser, priv->ibus_engines);
+}
+
+static void
fetch_ibus_engines_result (GObject *object,
GAsyncResult *result,
CcRegionPanel *self)
@@ -559,6 +572,7 @@ fetch_ibus_engines_result (GObject *object,
g_list_free (list);
update_ibus_active_sources (self);
+ update_input_chooser (self);
}
static void
@@ -902,9 +916,6 @@ input_response (GtkWidget *chooser, gint response_id, gpointer data)
if (response_id == GTK_RESPONSE_OK) {
if (cc_input_chooser_get_selected (chooser, &type, &id, &name)) {
-
- gtk_widget_destroy (chooser);
-
if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS)) {
g_free (type);
type = INPUT_SOURCE_TYPE_IBUS;
@@ -927,9 +938,9 @@ input_response (GtkWidget *chooser, gint response_id, gpointer data)
g_free (name);
g_clear_object (&app_info);
}
- } else {
- gtk_widget_destroy (chooser);
}
+ gtk_widget_destroy (chooser);
+ g_object_set_data (G_OBJECT (self), "input-chooser", NULL);
}
static void
@@ -950,6 +961,9 @@ show_input_chooser (CcRegionPanel *self)
);
g_signal_connect (chooser, "response",
G_CALLBACK (input_response), self);
+ gtk_window_present (GTK_WINDOW (chooser));
+
+ g_object_set_data (G_OBJECT (self), "input-chooser", chooser);
}
static void
diff --git a/panels/region/input-chooser.ui b/panels/region/input-chooser.ui
index 0a3f346..d2beffc 100644
--- a/panels/region/input-chooser.ui
+++ b/panels/region/input-chooser.ui
@@ -1,138 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
- <requires lib="gtk+" version="2.16"/>
- <object class="GtkListStore" id="input_source_model">
- <columns>
- <!-- display name -->
- <column type="gchararray"/>
- <!-- input source type -->
- <column type="gchararray"/>
- <!-- type specific identifier -->
- <column type="gchararray"/>
- </columns>
- </object>
- <object class="GtkTreeModelFilter" id="filtered_input_source_model">
- <property name="child_model">input_source_model</property>
- </object>
- <object class="GtkDialog" id="input_source_chooser">
- <property name="visible">False</property>
- <property name="can_focus">False</property>
- <property name="border_width">5</property>
- <property name="title" translatable="yes">Select an input source</property>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkDialog" id="input-dialog">
+ <property name="title" translatable="yes">Add an Input Source</property>
<property name="modal">True</property>
- <property name="window_position">center-on-parent</property>
- <property name="type_hint">dialog</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="resizable">False</property>
<child internal-child="vbox">
- <object class="GtkBox" id="dialog-vbox3">
+ <object class="GtkBox" id="vbox">
<property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="orientation">vertical</property>
- <property name="spacing">2</property>
- <child internal-child="action_area">
- <object class="GtkButtonBox" id="hbtnBox">
+ <property name="spacing">0</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="layout_style">end</property>
- <child>
- <object class="GtkButton" id="cancel-button">
- <property name="label">gtk-cancel</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="can_default">True</property>
- <property name="receives_default">False</property>
- <property name="use_action_appearance">False</property>
- <property name="use_stock">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="pack_type">end</property>
- <property name="position">1</property>
- </packing>
- </child>
+ <property name="hscrollbar-policy">never</property>
+ <property name="vscrollbar-policy">never</property>
+ <property name="shadow-type">in</property>
+ <property name="margin-left">6</property>
+ <property name="margin-right">6</property>
+ <property name="margin-top">6</property>
+ <property name="margin-bottom">6</property>
<child>
- <object class="GtkButton" id="ok-button">
- <property name="label">gtk-add</property>
+ <object class="GtkViewport" id="viewport">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="can_default">True</property>
- <property name="receives_default">False</property>
- <property name="use_action_appearance">False</property>
- <property name="use_stock">True</property>
+ <child>
+ <object class="EggListBox" id="list">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="vexpand">True</property>
+ <property name="halign">fill</property>
+ <property name="valign">fill</property>
+ </object>
+ </child>
</object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="pack_type">end</property>
- <property name="position">2</property>
- </packing>
</child>
</object>
</child>
<child>
- <object class="GtkVBox" id="vbox40">
+ <object class="GtkSearchEntry" id="filter-entry">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="border_width">5</property>
- <property name="spacing">6</property>
+ <property name="hexpand">True</property>
+ <property name="margin-left">6</property>
+ <property name="margin-right">6</property>
+ <property name="margin-top">6</property>
+ <property name="margin-bottom">6</property>
+ </object>
+ </child>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="action-area">
+ <property name="visible">True</property>
+ <property name="orientation">horizontal</property>
<child>
- <object class="GtkVBox" id="vbox1">
+ <object class="GtkButton" id="back-button">
+ <property name="visible">False</property>
+ <property name="label" translatable="yes">_Back</property>
+ <property name="use_underline" >True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel-button">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="spacing">6</property>
- <child>
- <object class="GtkScrolledWindow" id="scrolledwindow1">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hscrollbar_policy">never</property>
- <property name="shadow_type">etched-in</property>
- <property name="min_content_width">450</property>
- <property name="min_content_height">250</property>
- <child>
- <object class="GtkTreeView" id="filtered_input_source_list">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="model">filtered_input_source_model</property>
- <property name="headers_visible">False</property>
- <property name="search_column">0</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
+ <property name="label">gtk-cancel</property>
+ <property name="use_stock">True</property>
+ <property name="use_underline" >True</property>
</object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
</child>
<child>
- <object class="GtkEntry" id="input_source_filter">
+ <object class="GtkButton" id="ok-button">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="invisible_char">â</property>
- <property name="secondary-icon-name">edit-find-symbolic</property>
- <property name="secondary-icon-activatable">False</property>
- <property name="secondary-icon-sensitive">False</property>
+ <property name="label">gtk-add</property>
+ <property name="use_stock">True</property>
+ <property name="use_underline" >True</property>
</object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="pack_type">end</property>
- <property name="position">1</property>
- </packing>
</child>
</object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
</child>
</object>
</child>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]