From 43702238f93192d7bb2373f50909c4faabd86198 Mon Sep 17 00:00:00 2001 From: "Sergey V. Udaltsov" Date: Sun, 27 Apr 2008 15:13:32 +0000 Subject: [PATCH] Support for countries and languages svn path=/trunk/; revision=8673 --- capplets/keyboard/ChangeLog | 7 + .../keyboard/gnome-keyboard-properties-iso.c | 203 +++++++ .../keyboard/gnome-keyboard-properties-xkb.h | 8 +- .../gnome-keyboard-properties-xkbltadd.c | 514 ++++++++++++------ .../gnome-keyboard-properties-xkbpv.c | 83 +-- .../keyboard/gnome-keyboard-properties.glade | 198 +++++-- 6 files changed, 751 insertions(+), 262 deletions(-) create mode 100644 capplets/keyboard/gnome-keyboard-properties-iso.c diff --git a/capplets/keyboard/ChangeLog b/capplets/keyboard/ChangeLog index 509cd8793..bbcc8c24e 100644 --- a/capplets/keyboard/ChangeLog +++ b/capplets/keyboard/ChangeLog @@ -1,3 +1,10 @@ +2008-04-27 Sergey Udaltsov + + * gnome-keyboard-properties-xkb.h, gnome-keyboard-properties-iso.c, + gnome-keyboard-xkbpv.c, gnome-keyboard-properties.glade, + gnome-keyboard-properties-xkbltadd.c, Makefile.am: Added sorting by + language and country + 2008-04-24 Thomas Wood * gnome-keyboard-properties-xkbot.c: (xkb_options_load_options), diff --git a/capplets/keyboard/gnome-keyboard-properties-iso.c b/capplets/keyboard/gnome-keyboard-properties-iso.c new file mode 100644 index 000000000..cac91b97a --- /dev/null +++ b/capplets/keyboard/gnome-keyboard-properties-iso.c @@ -0,0 +1,203 @@ +/* -*- mode: c; style: linux -*- */ + +/* gnome-keyboard-properties-xkbltadd.c + * Copyright (C) 2007 Sergey V. Udaltsov + * + * Written by: Sergey V. Udaltsov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU 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. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include +#include +#include + +#include + +#define ISO_CODES_DATADIR ISO_CODES_PREFIX "/share/xml/iso-codes" +#define ISO_CODES_LOCALESDIR ISO_CODES_PREFIX "/share/locale" + +static GHashTable *country_code_names = NULL; +static GHashTable *lang_code_names = NULL; + +typedef struct { + const gchar *domain; + const gchar *attr_names[]; +} LookupParams; + +typedef struct { + GHashTable *code_names; + const gchar *tag_name; + LookupParams *params; +} CodeBuildStruct; + +static LookupParams countryLookup = { "iso_3166", {"alpha_2_code", NULL} }; +static LookupParams languageLookup = + { "iso_639", {"iso_639_2B_code", "iso_639_2T_code", NULL} }; + +static void +iso_codes_parse_start_tag (GMarkupParseContext * ctx, + const gchar * element_name, + const gchar ** attr_names, + const gchar ** attr_values, + gpointer user_data, GError ** error) +{ + const gchar *name; + const gchar **san = attr_names, **sav = attr_values; + CodeBuildStruct *cbs = (CodeBuildStruct *) user_data; + + /* Is this the tag we are looking for? */ + if (!g_str_equal (element_name, cbs->tag_name) || + attr_names == NULL || attr_values == NULL) { + return; + } + + name = NULL; + + /* What would be the value? */ + while (*attr_names && *attr_values) { + if (g_str_equal (*attr_names, "name")) { + name = *attr_values; + break; + } + + attr_names++; + attr_values++; + } + + if (!name) { + return; + } + + attr_names = san; + attr_values = sav; + + /* Walk again the attributes */ + while (*attr_names && *attr_values) { + const gchar **attr = cbs->params->attr_names; + /* Look through all the attributess we are interested in */ + while (*attr) { + if (g_str_equal (*attr_names, *attr)) { + if (**attr_values) { + g_hash_table_insert (cbs-> + code_names, + g_strdup + (*attr_values), + g_strdup + (name)); + } + } + attr++; + } + + attr_names++; + attr_values++; + } +} + +static GHashTable * +iso_code_names_init (LookupParams * params) +{ + GError *err = NULL; + gchar *buf, *filename, *tag_name; + gsize buf_len; + CodeBuildStruct cbs; + + GHashTable *ht = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, g_free); + + tag_name = g_strdup_printf ("%s_entry", params->domain); + + cbs.code_names = ht; + cbs.tag_name = tag_name; + cbs.params = params; + + bindtextdomain (params->domain, ISO_CODES_LOCALESDIR); + bind_textdomain_codeset (params->domain, "UTF-8"); + + filename = + g_strdup_printf ("%s/%s.xml", ISO_CODES_DATADIR, + params->domain); + if (g_file_get_contents (filename, &buf, &buf_len, &err)) { + GMarkupParseContext *ctx; + GMarkupParser parser = { + iso_codes_parse_start_tag, + NULL, NULL, NULL, NULL + }; + + ctx = g_markup_parse_context_new (&parser, 0, &cbs, NULL); + if (!g_markup_parse_context_parse + (ctx, buf, buf_len, &err)) { + g_warning ("Failed to parse '%s/%s.xml': %s", + ISO_CODES_DATADIR, + params->domain, err->message); + g_error_free (err); + } + + g_markup_parse_context_free (ctx); + g_free (buf); + } else { + g_warning ("Failed to load '%s/%s.xml': %s", + ISO_CODES_DATADIR, params->domain, + err->message); + g_error_free (err); + } + g_free (filename); + g_free (tag_name); + + return ht; +} + +const char * +get_language_iso_code (const char *code) +{ + const gchar *name; + + if (!lang_code_names) { + lang_code_names = iso_code_names_init (&languageLookup); + } + + name = g_hash_table_lookup (lang_code_names, code); + if (!name) { + return NULL; + } + + return dgettext ("iso_639", name); +} + +const char * +get_country_iso_code (const char *code) +{ + const gchar *name; + + if (!country_code_names) { + country_code_names = iso_code_names_init (&countryLookup); + } + + name = g_hash_table_lookup (country_code_names, code); + if (!name) { + return NULL; + } + + return dgettext ("iso_3166", name); +} diff --git a/capplets/keyboard/gnome-keyboard-properties-xkb.h b/capplets/keyboard/gnome-keyboard-properties-xkb.h index 0efafe408..bdd58450f 100644 --- a/capplets/keyboard/gnome-keyboard-properties-xkb.h +++ b/capplets/keyboard/gnome-keyboard-properties-xkb.h @@ -50,13 +50,13 @@ extern void xkb_layouts_prepare_selected_tree (GladeXML * dialog, extern void xkb_options_load_options (GladeXML * dialog); -extern void xkb_options_popup_dialog(GladeXML * dialog); +extern void xkb_options_popup_dialog (GladeXML * dialog); extern void clear_xkb_elements_list (GSList * list); extern char *xci_desc_to_utf8 (XklConfigItem * ci); -extern gchar *xkb_layout_description_utf8 (const gchar *visible); +extern gchar *xkb_layout_description_utf8 (const gchar * visible); extern void enable_disable_restoring (GladeXML * dialog); @@ -88,8 +88,8 @@ extern GtkWidget *xkb_layout_preview_create_widget (GladeXML * extern void xkb_layout_preview_update (GladeXML * chooser_dialog); -extern void xkb_layout_preview_set_drawing_layout (GtkWidget *kbdraw, - const gchar *id); +extern void xkb_layout_preview_set_drawing_layout (GtkWidget * kbdraw, + const gchar * id); extern gchar *xkb_layout_chooser_get_selected_id (GladeXML * chooser_dialog); diff --git a/capplets/keyboard/gnome-keyboard-properties-xkbltadd.c b/capplets/keyboard/gnome-keyboard-properties-xkbltadd.c index 3495bdde1..aedcf6691 100644 --- a/capplets/keyboard/gnome-keyboard-properties-xkbltadd.c +++ b/capplets/keyboard/gnome-keyboard-properties-xkbltadd.c @@ -40,78 +40,148 @@ #define DEFAULT_GROUP_SWITCH "grp:alts_toggle" #define DEFAULT_VARIANT_ID "__default__" +#define LANG_THRESHOLD_1 15 +#define LANG_THRESHOLD_2 5 + enum { COMBO_BOX_MODEL_COL_DESCRIPTION, - COMBO_BOX_MODEL_COL_ID, - COMBO_BOX_MODEL_COL_IS_DEFAULT + COMBO_BOX_MODEL_COL_XKB_ID, + COMBO_BOX_MODEL_COL_REAL_ID, + COMBO_BOX_MODEL_COL_COUNTER }; +typedef void (*LayoutIterFunc) (XklConfigRegistry * config, + ConfigItemProcessFunc func, gpointer data); + typedef struct { GtkListStore *list_store; - guint n_items; + const gchar *lang_id; } AddVariantData; static void - xkb_layout_chooser_available_layouts_fill (GladeXML * chooser_dialog); + xkb_layout_chooser_available_layouts_fill (GladeXML * chooser_dialog, + const gchar cblid[], + const gchar cbvid[], + LayoutIterFunc layout_iterator, + ConfigItemProcessFunc + layout_handler, + gint sort_column_id, + GtkTreeIterCompareFunc + sort_func, + GCallback + combo_changed_notify); static void - xkb_layout_chooser_available_variants_fill (GladeXML * chooser_dialog); + xkb_layout_chooser_available_language_variants_fill (GladeXML * + chooser_dialog); static void -xkb_layout_chooser_add_variant_to_available_variants (XklConfigRegistry * - config_registry, - XklConfigItem * - config_item, - AddVariantData * - data) -{ - char *utf_variant_name = xci_desc_to_utf8 (config_item); + xkb_layout_chooser_available_country_variants_fill (GladeXML * + chooser_dialog); + +static void + xkb_layout_chooser_add_variant_to_available_country_variants + (XklConfigRegistry * config_registry, + XklConfigItem * parent_config_item, XklConfigItem * config_item, + AddVariantData * data) { + gchar *utf_variant_name = config_item ? + xkb_layout_description_utf8 (gkbd_keyboard_config_merge_items + (parent_config_item->name, + config_item->name)) : + xci_desc_to_utf8 (parent_config_item); GtkTreeIter iter; + const gchar *xkb_id = + config_item ? + gkbd_keyboard_config_merge_items (parent_config_item->name, + config_item-> + name) : parent_config_item-> + name; gtk_list_store_insert_with_values (data->list_store, &iter, -1, COMBO_BOX_MODEL_COL_DESCRIPTION, utf_variant_name, - COMBO_BOX_MODEL_COL_ID, - config_item->name, - COMBO_BOX_MODEL_COL_IS_DEFAULT, - FALSE, -1); + COMBO_BOX_MODEL_COL_XKB_ID, + xkb_id, -1); g_free (utf_variant_name); - - data->n_items++; } static void -xkb_layout_chooser_add_layout_to_available_layouts (XklConfigRegistry * - config_registry, - XklConfigItem * - config_item, - GtkListStore * - list_store) -{ - char *utf_layout_name = xci_desc_to_utf8 (config_item); - GtkTreeIter iter; + xkb_layout_chooser_add_variant_to_available_language_variants + (XklConfigRegistry * config_registry, + XklConfigItem * parent_config_item, XklConfigItem * config_item, + AddVariantData * data) { + xkb_layout_chooser_add_variant_to_available_country_variants + (config_registry, parent_config_item, config_item, data); +} - gtk_list_store_insert_with_values (list_store, &iter, -1, +static void +inc_counter (XklConfigRegistry * config_registry, XklConfigItem * + layout, XklConfigItem * variant, gint * counter) +{ + (*counter)++; +} + +static void +xkb_layout_chooser_add_language_to_available_languages (XklConfigRegistry * + config_registry, + XklConfigItem * + config_item, + GtkListStore * + list_store) +{ + gint counter = 0; + gchar *descr; + gchar *size; + xkl_config_registry_foreach_language_variant + (config_registry, config_item->name, + (TwoConfigItemsProcessFunc) + inc_counter, &counter); + size = + counter > LANG_THRESHOLD_1 ? "x-large" : counter > + LANG_THRESHOLD_2 ? "large" : "medium"; + descr = + g_strdup_printf ("%s", size, + config_item->description); + gtk_list_store_insert_with_values (list_store, NULL, -1, COMBO_BOX_MODEL_COL_DESCRIPTION, - utf_layout_name, - COMBO_BOX_MODEL_COL_ID, + descr, + COMBO_BOX_MODEL_COL_REAL_ID, + config_item->name, + COMBO_BOX_MODEL_COL_COUNTER, + counter, -1); + g_free (descr); +} + +static void +xkb_layout_chooser_add_country_to_available_countries (XklConfigRegistry * + config_registry, + XklConfigItem * + config_item, + GtkListStore * + list_store) +{ + gtk_list_store_insert_with_values (list_store, NULL, -1, + COMBO_BOX_MODEL_COL_DESCRIPTION, + config_item->description, + COMBO_BOX_MODEL_COL_REAL_ID, config_item->name, -1); - g_free (utf_layout_name); } static void xkb_layout_chooser_enable_disable_buttons (GladeXML * chooser_dialog) { - GtkWidget *cbel = CWID ("xkb_layouts_available"); - GtkWidget *cbev = CWID ("xkb_variants_available"); - GtkTreeIter liter, viter; - gboolean enable_ok = - gtk_combo_box_get_active_iter (GTK_COMBO_BOX (cbel), &liter) - && gtk_combo_box_get_active_iter (GTK_COMBO_BOX (cbev), + GtkWidget *cbv = + CWID (gtk_notebook_get_current_page + (GTK_NOTEBOOK (CWID ("choosers_nb"))) ? + "xkb_language_variants_available" : + "xkb_country_variants_available"); + GtkTreeIter viter; + gboolean enable_ok = gtk_combo_box_get_active_iter (GTK_COMBO_BOX (cbv), &viter); gtk_dialog_set_response_sensitive (GTK_DIALOG - (CWID ("xkb_layout_chooser")), + (CWID + ("xkb_layout_chooser")), GTK_RESPONSE_OK, enable_ok); gtk_widget_set_sensitive (CWID ("btnPrint"), enable_ok); } @@ -124,33 +194,53 @@ xkb_layout_chooser_available_variant_changed (GladeXML * chooser_dialog) } static void -xkb_layout_chooser_available_layout_changed (GladeXML * chooser_dialog) +xkb_layout_chooser_available_language_changed (GladeXML * chooser_dialog) +{ + xkb_layout_chooser_available_language_variants_fill + (chooser_dialog); + xkb_layout_chooser_available_variant_changed (chooser_dialog); +} + +static void +xkb_layout_chooser_available_country_changed (GladeXML * chooser_dialog) +{ + xkb_layout_chooser_available_country_variants_fill + (chooser_dialog); + xkb_layout_chooser_available_variant_changed (chooser_dialog); +} + +static void +xkb_layout_chooser_page_changed (GtkWidget* notebook, GtkWidget * page, gint page_num, GladeXML * chooser_dialog) { - xkb_layout_chooser_available_variants_fill (chooser_dialog); xkb_layout_chooser_available_variant_changed (chooser_dialog); } static gint -xkb_layout_chooser_variant_compare_func (GtkTreeModel * model, - GtkTreeIter * a, - GtkTreeIter * b, - gpointer user_data) +xkb_layout_chooser_language_compare_func (GtkTreeModel * model, + GtkTreeIter * a, + GtkTreeIter * b, + gpointer user_data) { gchar *desc_a = NULL, *desc_b = NULL; - gboolean a_is_default, b_is_default; + gint a_cnt = 0, b_cnt = 0; gint retval; gtk_tree_model_get (model, a, - COMBO_BOX_MODEL_COL_DESCRIPTION, &desc_a, - COMBO_BOX_MODEL_COL_IS_DEFAULT, &a_is_default, - -1); + COMBO_BOX_MODEL_COL_DESCRIPTION, + &desc_a, + COMBO_BOX_MODEL_COL_COUNTER, &a_cnt, -1); gtk_tree_model_get (model, b, - COMBO_BOX_MODEL_COL_DESCRIPTION, &desc_b, - COMBO_BOX_MODEL_COL_IS_DEFAULT, &b_is_default, - -1); - - if (a_is_default || b_is_default) - retval = b_is_default - a_is_default; + COMBO_BOX_MODEL_COL_DESCRIPTION, + &desc_b, + COMBO_BOX_MODEL_COL_COUNTER, &b_cnt, -1); + /* Compare languages, using scopes 0-5, 6-15, 16-... */ + if ((a_cnt > LANG_THRESHOLD_1 && b_cnt <= LANG_THRESHOLD_1) + || (a_cnt > LANG_THRESHOLD_2 && b_cnt <= LANG_THRESHOLD_2)) + retval = -1; + else if ((a_cnt <= LANG_THRESHOLD_1 && b_cnt > LANG_THRESHOLD_1) + || (a_cnt <= LANG_THRESHOLD_2 + && b_cnt > LANG_THRESHOLD_2)) + retval = 1; else if (desc_a != NULL && desc_b != NULL) retval = g_utf8_collate (desc_a, desc_b); else if (desc_a != NULL) @@ -168,136 +258,194 @@ xkb_layout_chooser_variant_compare_func (GtkTreeModel * model, return retval; } -static gboolean -xkl_layout_chooser_separate_default_variant (GtkTreeModel * model, - GtkTreeIter * iter, - GladeXML * chooser_dialog) +static gint +xkb_layout_chooser_variant_compare_func (GtkTreeModel * model, + GtkTreeIter * a, + GtkTreeIter * b, + gpointer user_data) { - gchar *id; + gchar *desc_a = NULL, *desc_b = NULL; + gint retval; - /* Rows with COMBO_BOX_MODEL_COL_DESCRIPTION value NULL are separators */ - gtk_tree_model_get (model, iter, COMBO_BOX_MODEL_COL_DESCRIPTION, - &id, -1); - g_free (id); + gtk_tree_model_get (model, a, + COMBO_BOX_MODEL_COL_DESCRIPTION, &desc_a, -1); + gtk_tree_model_get (model, b, + COMBO_BOX_MODEL_COL_DESCRIPTION, &desc_b, -1); - return id == NULL; + if (desc_a != NULL && desc_b != NULL) + retval = g_utf8_collate (desc_a, desc_b); + else if (desc_a != NULL) + /* desc_b == NULL hence b is the separator, and a is not the default => b < a */ + retval = 1; + else if (desc_b != NULL) + /* desc_a == NULL hence a is the separator, and b is not the default => a < b */ + retval = -1; + else + retval = 0; + + g_free (desc_a); + g_free (desc_b); + + return retval; } static void -xkb_layout_chooser_available_variants_fill (GladeXML * chooser_dialog) +xkb_layout_chooser_available_language_variants_fill (GladeXML * + chooser_dialog) { - GtkWidget *cbel = CWID ("xkb_layouts_available"); - GtkWidget *cbev = CWID ("xkb_variants_available"); - GtkTreeModel *model = - gtk_combo_box_get_model (GTK_COMBO_BOX (cbev)); - GtkTreeIter liter, vdefault_iter; - gboolean set_default = FALSE; + GtkWidget *cbl = CWID ("xkb_languages_available"); + GtkWidget *cbv = CWID ("xkb_language_variants_available"); + GtkListStore *list_store; + GtkTreeIter liter; - model = GTK_TREE_MODEL (gtk_list_store_new - (3, G_TYPE_STRING, G_TYPE_STRING, - G_TYPE_BOOLEAN)); + list_store = gtk_list_store_new + (4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT); - if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (cbel), &liter)) { + if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (cbl), &liter)) { GtkTreeModel *lm = - gtk_combo_box_get_model (GTK_COMBO_BOX (cbel)); - GtkTreeIter viter; - gchar *value; - AddVariantData data = { GTK_LIST_STORE (model), 0 }; + gtk_combo_box_get_model (GTK_COMBO_BOX (cbl)); + gchar *lang_id; + AddVariantData data = { list_store, 0 }; - /* The 'Default' row */ - gtk_list_store_insert_with_values (GTK_LIST_STORE (model), - &vdefault_iter, -1, - COMBO_BOX_MODEL_COL_DESCRIPTION, - _("Default"), - COMBO_BOX_MODEL_COL_ID, - DEFAULT_VARIANT_ID, - COMBO_BOX_MODEL_COL_IS_DEFAULT, - TRUE, -1); - set_default = TRUE; - - /* Now the variants of the selected lang */ + /* Now the variants of the selected layout */ gtk_tree_model_get (lm, &liter, - COMBO_BOX_MODEL_COL_ID, &value, -1); - g_assert (value != NULL); + COMBO_BOX_MODEL_COL_REAL_ID, + &lang_id, -1); + data.lang_id = lang_id; - xkl_config_registry_foreach_layout_variant - (config_registry, value, (ConfigItemProcessFunc) - xkb_layout_chooser_add_variant_to_available_variants, + xkl_config_registry_foreach_language_variant + (config_registry, lang_id, (TwoConfigItemsProcessFunc) + xkb_layout_chooser_add_variant_to_available_language_variants, &data); - g_free (value); - - /* Add a separator row, but only if we have any non-default items */ - if (data.n_items > 0) - gtk_list_store_insert_with_values (GTK_LIST_STORE - (model), &viter, - -1, - COMBO_BOX_MODEL_COL_DESCRIPTION, - NULL, - COMBO_BOX_MODEL_COL_ID, - NULL, - COMBO_BOX_MODEL_COL_IS_DEFAULT, - FALSE, -1); + g_free (lang_id); } /* Turn on sorting after filling the store, since that's faster */ - gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (model), + gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (list_store), COMBO_BOX_MODEL_COL_DESCRIPTION, (GtkTreeIterCompareFunc) xkb_layout_chooser_variant_compare_func, NULL, NULL); - gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model), + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE + (list_store), COMBO_BOX_MODEL_COL_DESCRIPTION, GTK_SORT_ASCENDING); - gtk_combo_box_set_model (GTK_COMBO_BOX (cbev), model); + gtk_combo_box_set_model (GTK_COMBO_BOX (cbv), + GTK_TREE_MODEL (list_store)); + + /* Select the default variant */ + /* TODO + if (set_default) { + gtk_combo_box_set_active_iter (GTK_COMBO_BOX + (cbev), &vdefault_iter); + } + */ +} + +static void +xkb_layout_chooser_available_country_variants_fill (GladeXML * + chooser_dialog) +{ + GtkWidget *cbl = CWID ("xkb_countries_available"); + GtkWidget *cbv = CWID ("xkb_country_variants_available"); + GtkListStore *list_store; + GtkTreeIter liter, vdefault_iter; + gboolean set_default = FALSE; + + list_store = gtk_list_store_new + (4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT); + + if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (cbl), &liter)) { + GtkTreeModel *lm = + gtk_combo_box_get_model (GTK_COMBO_BOX (cbl)); + gchar *country_id; + AddVariantData data = { list_store, 0 }; + + /* Now the variants of the selected layout */ + gtk_tree_model_get (lm, &liter, + COMBO_BOX_MODEL_COL_REAL_ID, + &country_id, -1); + xkl_config_registry_foreach_country_variant + (config_registry, country_id, + (TwoConfigItemsProcessFunc) + xkb_layout_chooser_add_variant_to_available_country_variants, + &data); + g_free (country_id); + } + + /* Turn on sorting after filling the store, since that's faster */ + gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (list_store), + COMBO_BOX_MODEL_COL_DESCRIPTION, + (GtkTreeIterCompareFunc) + xkb_layout_chooser_variant_compare_func, + NULL, NULL); + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE + (list_store), + COMBO_BOX_MODEL_COL_DESCRIPTION, + GTK_SORT_ASCENDING); + + gtk_combo_box_set_model (GTK_COMBO_BOX (cbv), + GTK_TREE_MODEL (list_store)); /* Select the default variant */ if (set_default) { - gtk_combo_box_set_active_iter (GTK_COMBO_BOX (cbev), - &vdefault_iter); + gtk_combo_box_set_active_iter (GTK_COMBO_BOX + (cbv), &vdefault_iter); } } static void -xkb_layout_chooser_available_layouts_fill (GladeXML * chooser_dialog) +xkb_layout_chooser_available_layouts_fill (GladeXML * + chooser_dialog, + const gchar cblid[], + const gchar cbvid[], + LayoutIterFunc layout_iterator, + ConfigItemProcessFunc + layout_handler, + gint sort_column_id, + GtkTreeIterCompareFunc + sort_func, + GCallback combo_changed_notify) { - GtkWidget *cbe = CWID ("xkb_layouts_available"); - GtkWidget *cbev = CWID ("xkb_variants_available"); + GtkWidget *cbl = CWID (cblid); + GtkWidget *cbev = CWID (cbvid); GtkCellRenderer *renderer; - GtkTreeModel *model = - GTK_TREE_MODEL (gtk_list_store_new - (2, G_TYPE_STRING, G_TYPE_STRING)); + GtkListStore *list_store = + gtk_list_store_new (4, G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_INT); - gtk_combo_box_set_model (GTK_COMBO_BOX (cbe), model); + gtk_combo_box_set_model (GTK_COMBO_BOX (cbl), + GTK_TREE_MODEL (list_store)); renderer = gtk_cell_renderer_text_new (); - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (cbe), renderer, TRUE); - gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (cbe), renderer, - "text", + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (cbl), renderer, TRUE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (cbl), + renderer, "markup", COMBO_BOX_MODEL_COL_DESCRIPTION, NULL); - xkl_config_registry_foreach_layout (config_registry, - (ConfigItemProcessFunc) - xkb_layout_chooser_add_layout_to_available_layouts, - model); + layout_iterator (config_registry, layout_handler, list_store); /* Turn on sorting after filling the model since that's faster */ - gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model), - COMBO_BOX_MODEL_COL_DESCRIPTION, + if (sort_func) + gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE + (list_store), + sort_column_id, sort_func, + NULL, NULL); + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE + (list_store), sort_column_id, GTK_SORT_ASCENDING); - g_signal_connect_swapped (G_OBJECT (cbe), "changed", - G_CALLBACK - (xkb_layout_chooser_available_layout_changed), - chooser_dialog); + g_signal_connect_swapped (G_OBJECT (cbl), "changed", + combo_changed_notify, chooser_dialog); /* Setup the variants combo */ renderer = gtk_cell_renderer_text_new (); - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (cbev), renderer, - TRUE); - gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (cbev), renderer, - "text", + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (cbev), + renderer, TRUE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (cbev), + renderer, "markup", COMBO_BOX_MODEL_COL_DESCRIPTION, NULL); @@ -305,10 +453,6 @@ xkb_layout_chooser_available_layouts_fill (GladeXML * chooser_dialog) G_CALLBACK (xkb_layout_chooser_available_variant_changed), chooser_dialog); - gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (cbev), - (GtkTreeViewRowSeparatorFunc) - xkl_layout_chooser_separate_default_variant, - chooser_dialog, NULL); } void @@ -364,7 +508,8 @@ xkb_layout_chooser_print (GladeXML * chooser_dialog) const char *id = xkb_layout_chooser_get_selected_id (chooser_dialog); char *descr = xkb_layout_description_utf8 (id); - gkbd_keyboard_drawing_print (GKBD_KEYBOARD_DRAWING (kbdraw), + gkbd_keyboard_drawing_print (GKBD_KEYBOARD_DRAWING + (kbdraw), GTK_WINDOW (CWID ("xkb_layout_chooser")), descr); @@ -424,20 +569,47 @@ xkb_layout_choose (GladeXML * dialog) GTK_WINDOW (WID ("keyboard_dialog"))); - xkb_layout_chooser_available_layouts_fill (chooser_dialog); - xkb_layout_chooser_available_layout_changed (chooser_dialog); + xkb_layout_chooser_available_layouts_fill (chooser_dialog, + "xkb_countries_available", + "xkb_country_variants_available", + xkl_config_registry_foreach_country, + (ConfigItemProcessFunc) + xkb_layout_chooser_add_country_to_available_countries, + COMBO_BOX_MODEL_COL_DESCRIPTION, + NULL, + G_CALLBACK + (xkb_layout_chooser_available_country_changed)); + xkb_layout_chooser_available_layouts_fill (chooser_dialog, + "xkb_languages_available", + "xkb_language_variants_available", + xkl_config_registry_foreach_language, + (ConfigItemProcessFunc) + xkb_layout_chooser_add_language_to_available_languages, + COMBO_BOX_MODEL_COL_COUNTER, + xkb_layout_chooser_language_compare_func, + G_CALLBACK + (xkb_layout_chooser_available_language_changed)); + + g_signal_connect_after (G_OBJECT (CWID("choosers_nb")), "switch_page", + G_CALLBACK + (xkb_layout_chooser_page_changed), + chooser_dialog); + + xkb_layout_chooser_available_country_changed (chooser_dialog); + xkb_layout_chooser_available_language_changed (chooser_dialog); #ifdef HAVE_X11_EXTENSIONS_XKB_H if (!strcmp (xkl_engine_get_backend_name (engine), "XKB")) { kbdraw = xkb_layout_preview_create_widget (chooser_dialog); g_object_set_data (G_OBJECT (chooser), "kbdraw", kbdraw); - gtk_container_add (GTK_CONTAINER (CWID ("previewFrame")), - kbdraw); + gtk_container_add (GTK_CONTAINER + (CWID ("previewFrame")), kbdraw); gtk_widget_show_all (kbdraw); gtk_button_box_set_child_secondary (GTK_BUTTON_BOX - (CWID ("hbtnBox")), - CWID ("btnPrint"), - TRUE); + (CWID + ("hbtnBox")), + CWID + ("btnPrint"), TRUE); } else #endif { @@ -454,8 +626,8 @@ xkb_layout_choose (GladeXML * dialog) if (GTK_WIDGET_TOPLEVEL (toplevel)) { GdkRectangle *rect = gkbd_preview_load_position (); if (rect != NULL) { - gtk_window_move (GTK_WINDOW (toplevel), rect->x, - rect->y); + gtk_window_move (GTK_WINDOW (toplevel), + rect->x, rect->y); gtk_window_resize (GTK_WINDOW (toplevel), rect->width, rect->height); g_free (rect); @@ -469,34 +641,20 @@ xkb_layout_choose (GladeXML * dialog) gchar * xkb_layout_chooser_get_selected_id (GladeXML * chooser_dialog) { - GtkWidget *cbel = CWID ("xkb_layouts_available"); - GtkWidget *cbev = CWID ("xkb_variants_available"); - GtkTreeModel *lm = gtk_combo_box_get_model (GTK_COMBO_BOX (cbel)); - GtkTreeModel *vm = gtk_combo_box_get_model (GTK_COMBO_BOX (cbev)); - GtkTreeIter liter, viter; - gchar *lname, *vname; - gchar *retval; + GtkWidget *cbv = + CWID (gtk_notebook_get_current_page + (GTK_NOTEBOOK (CWID ("choosers_nb"))) ? + "xkb_language_variants_available" : + "xkb_country_variants_available"); + GtkTreeModel *vm = gtk_combo_box_get_model (GTK_COMBO_BOX (cbv)); + GtkTreeIter viter; + gchar *v_id; - if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (cbel), &liter) - || !gtk_combo_box_get_active_iter (GTK_COMBO_BOX (cbev), - &viter)) + if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (cbv), &viter)) return NULL; - gtk_tree_model_get (lm, &liter, - COMBO_BOX_MODEL_COL_ID, &lname, -1); - gtk_tree_model_get (vm, &viter, - COMBO_BOX_MODEL_COL_ID, &vname, -1); + COMBO_BOX_MODEL_COL_XKB_ID, &v_id, -1); - if (strcmp (vname, DEFAULT_VARIANT_ID)) - retval = - g_strdup (gkbd_keyboard_config_merge_items - (lname, vname)); - else - retval = g_strdup (lname); - - g_free (lname); - g_free (vname); - - return retval; + return v_id; } diff --git a/capplets/keyboard/gnome-keyboard-properties-xkbpv.c b/capplets/keyboard/gnome-keyboard-properties-xkbpv.c index 631b04b00..e243233c1 100644 --- a/capplets/keyboard/gnome-keyboard-properties-xkbpv.c +++ b/capplets/keyboard/gnome-keyboard-properties-xkbpv.c @@ -81,50 +81,59 @@ xkb_layout_preview_update (GladeXML * chooser_dialog) } void -xkb_layout_preview_set_drawing_layout (GtkWidget * kbdraw, const gchar * id) +xkb_layout_preview_set_drawing_layout (GtkWidget * kbdraw, + const gchar * id) { #ifdef HAVE_X11_EXTENSIONS_XKB_H - if (kbdraw != NULL && id != NULL) { - XklConfigRec *data; - char **p, *layout, *variant; - XkbComponentNamesRec component_names; + if (kbdraw != NULL) { + if (id != NULL) { + XklConfigRec *data; + char **p, *layout, *variant; + XkbComponentNamesRec component_names; - data = xkl_config_rec_new (); - if (xkl_config_rec_get_from_server (data, engine)) { - if ((p = data->layouts) != NULL) - g_strfreev (data->layouts); + data = xkl_config_rec_new (); + if (xkl_config_rec_get_from_server (data, engine)) { + if ((p = data->layouts) != NULL) + g_strfreev (data->layouts); - if ((p = data->variants) != NULL) - g_strfreev (data->variants); + if ((p = data->variants) != NULL) + g_strfreev (data->variants); - data->layouts = g_new0 (char *, 2); - data->variants = g_new0 (char *, 2); - if (gkbd_keyboard_config_split_items - (id, &layout, &variant) - && variant != NULL) { - data->layouts[0] = - (layout == - NULL) ? NULL : g_strdup (layout); - data->variants[0] = - (variant == - NULL) ? NULL : g_strdup (variant); - } else { - data->layouts[0] = - (id == NULL) ? NULL : g_strdup (id); - data->variants[0] = NULL; + data->layouts = g_new0 (char *, 2); + data->variants = g_new0 (char *, 2); + if (gkbd_keyboard_config_split_items + (id, &layout, &variant) + && variant != NULL) { + data->layouts[0] = + (layout == + NULL) ? NULL : + g_strdup (layout); + data->variants[0] = + (variant == + NULL) ? NULL : + g_strdup (variant); + } else { + data->layouts[0] = + (id == + NULL) ? NULL : g_strdup (id); + data->variants[0] = NULL; + } + + if (xkl_xkb_config_native_prepare + (engine, data, &component_names)) { + gkbd_keyboard_drawing_set_keyboard + (GKBD_KEYBOARD_DRAWING + (kbdraw), &component_names); + + xkl_xkb_config_native_cleanup + (engine, &component_names); + } } + g_object_unref (G_OBJECT (data)); + } else + gkbd_keyboard_drawing_set_keyboard + (GKBD_KEYBOARD_DRAWING (kbdraw), NULL); - if (xkl_xkb_config_native_prepare - (engine, data, &component_names)) { - gkbd_keyboard_drawing_set_keyboard - (GKBD_KEYBOARD_DRAWING (kbdraw), - &component_names); - - xkl_xkb_config_native_cleanup (engine, - &component_names); - } - } - g_object_unref (G_OBJECT (data)); } #endif } diff --git a/capplets/keyboard/gnome-keyboard-properties.glade b/capplets/keyboard/gnome-keyboard-properties.glade index e43677797..0cbd275b3 100644 --- a/capplets/keyboard/gnome-keyboard-properties.glade +++ b/capplets/keyboard/gnome-keyboard-properties.glade @@ -1714,67 +1714,179 @@ 5 6 - + True - 2 - 2 - 12 - 6 + True - + True - 0 - _Layouts: + 6 + 6 + 6 + 6 + + + True + 2 + 2 + 12 + 6 + + + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + + True + + + 1 + 2 + GTK_FILL + + + + + + True + 0 + _Variants: + True + xkb_country_variants_available + + + 1 + 2 + GTK_FILL + + + + + + True + 0 + _Country: + True + xkb_countries_available + + + GTK_FILL + + + + + + + + + + True + By _country True - xkb_layouts_available - GTK_FILL - + tab + False - + True - 0 - _Variants: + 6 + 6 + 6 + 6 + + + True + 2 + 2 + 12 + 6 + + + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + + True + + + 1 + 2 + GTK_FILL + + + + + + True + 0 + _Variants: + True + xkb_country_variants_available + + + 1 + 2 + GTK_FILL + + + + + + True + 0 + _Language: + True + xkb_countries_available + + + GTK_FILL + + + + + + + + 1 + + + + + True + By _language True - xkb_variants_available - 1 - 2 - GTK_FILL - - - - - - True - - - 1 - 2 - GTK_FILL - GTK_FILL - - - - - True - - - 1 - 2 - 1 - 2 - GTK_FILL - GTK_FILL + tab + 1 + False False + False