[gnome-desktop] gnome-xkb-info: Group layouts by country and language
- From: Rui Matos <rtcm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-desktop] gnome-xkb-info: Group layouts by country and language
- Date: Fri, 25 Jan 2013 14:51:54 +0000 (UTC)
commit 5e86bb46bc8f6ea43b7cb9f3c42af7c16e116684
Author: Rui Matos <tiagomatos gmail com>
Date: Fri Jun 29 17:57:15 2012 +0200
gnome-xkb-info: Group layouts by country and language
This will allow us to do better guesses at which layout should be the
default for a given locale.
https://bugzilla.gnome.org/show_bug.cgi?id=692413
libgnome-desktop/gnome-xkb-info.c | 157 ++++++++++++++++++++++++-------------
1 files changed, 104 insertions(+), 53 deletions(-)
---
diff --git a/libgnome-desktop/gnome-xkb-info.c b/libgnome-desktop/gnome-xkb-info.c
index 80729bb..41398ed 100644
--- a/libgnome-desktop/gnome-xkb-info.c
+++ b/libgnome-desktop/gnome-xkb-info.c
@@ -34,6 +34,7 @@
#define XKEYBOARD_CONFIG_(String) ((char *) g_dgettext ("xkeyboard-config", String))
#define GNOME_DESKTOP_USE_UNSTABLE_API
+#include "gnome-languages.h"
#include "gnome-xkb-info.h"
#ifndef XKB_RULES_FILE
@@ -76,8 +77,8 @@ struct _XkbOptionGroup
struct _GnomeXkbInfoPrivate
{
GHashTable *option_groups_table;
- GHashTable *layouts_by_short_desc;
- GHashTable *layouts_by_iso639;
+ GHashTable *layouts_by_country;
+ GHashTable *layouts_by_language;
GHashTable *layouts_table;
/* Only used while parsing */
@@ -86,6 +87,7 @@ struct _GnomeXkbInfoPrivate
Layout *current_parser_layout;
Layout *current_parser_variant;
gchar *current_parser_iso639Id;
+ gchar *current_parser_iso3166Id;
gchar **current_parser_text;
};
@@ -268,6 +270,10 @@ parse_start_element (GMarkupParseContext *context,
{
priv->current_parser_text = &priv->current_parser_iso639Id;
}
+ else if (strcmp (element_name, "iso3166Id") == 0)
+ {
+ priv->current_parser_text = &priv->current_parser_iso3166Id;
+ }
else if (strcmp (element_name, "layout") == 0)
{
if (priv->current_parser_layout)
@@ -341,25 +347,45 @@ parse_start_element (GMarkupParseContext *context,
}
}
-static gboolean
-maybe_replace (GHashTable *table,
- gchar *key,
- Layout *new_layout)
-{
- /* There might be multiple layouts for the same language. In that
- * case considering the "canonical" layout to be the one with the
- * shorter description seems to be good enough. */
- Layout *layout;
- gboolean exists;
- gboolean replace = TRUE;
-
- exists = g_hash_table_lookup_extended (table, key, NULL, (gpointer *)&layout);
- if (exists)
- replace = strlen (new_layout->description) < strlen (layout->description);
- if (replace)
- g_hash_table_replace (table, key, new_layout);
-
- return replace;
+static void
+add_layout_to_table (GHashTable *table,
+ const gchar *key,
+ Layout *layout)
+{
+ GSequence *seq;
+
+ seq = g_hash_table_lookup (table, key);
+ if (!seq)
+ {
+ seq = g_sequence_new (NULL);
+ g_hash_table_replace (table, g_strdup (key), seq);
+ }
+ g_sequence_append (seq, layout);
+}
+
+static gint
+layout_compare (Layout *a,
+ Layout *b,
+ gpointer data)
+{
+ return g_strcmp0 (a->id, b->id);
+}
+
+static void
+sort_sequence (gpointer key,
+ gpointer value,
+ gpointer data)
+{
+ g_sequence_sort ((GSequence *) value, (GCompareDataFunc) layout_compare, NULL);
+}
+
+static void
+sort_sequences (GnomeXkbInfo *self)
+{
+ GnomeXkbInfoPrivate *priv = self->priv;
+
+ g_hash_table_foreach (priv->layouts_by_country, sort_sequence, NULL);
+ g_hash_table_foreach (priv->layouts_by_language, sort_sequence, NULL);
}
static void
@@ -381,10 +407,6 @@ parse_end_element (GMarkupParseContext *context,
priv->current_parser_layout->id = g_strdup (priv->current_parser_layout->xkb_name);
- if (priv->current_parser_layout->short_desc)
- maybe_replace (priv->layouts_by_short_desc,
- priv->current_parser_layout->short_desc, priv->current_parser_layout);
-
g_hash_table_replace (priv->layouts_table,
priv->current_parser_layout->id,
priv->current_parser_layout);
@@ -404,10 +426,6 @@ parse_end_element (GMarkupParseContext *context,
priv->current_parser_variant->xkb_name,
NULL);
- if (priv->current_parser_variant->short_desc)
- maybe_replace (priv->layouts_by_short_desc,
- priv->current_parser_variant->short_desc, priv->current_parser_variant);
-
g_hash_table_replace (priv->layouts_table,
priv->current_parser_variant->id,
priv->current_parser_variant);
@@ -415,7 +433,7 @@ parse_end_element (GMarkupParseContext *context,
}
else if (strcmp (element_name, "iso639Id") == 0)
{
- gboolean replaced = FALSE;
+ gchar *language;
if (!priv->current_parser_iso639Id)
{
@@ -424,17 +442,42 @@ parse_end_element (GMarkupParseContext *context,
return;
}
- if (priv->current_parser_layout)
- replaced = maybe_replace (priv->layouts_by_iso639,
- priv->current_parser_iso639Id, priv->current_parser_layout);
- else if (priv->current_parser_variant)
- replaced = maybe_replace (priv->layouts_by_iso639,
- priv->current_parser_iso639Id, priv->current_parser_variant);
+ language = gnome_get_language_from_name (priv->current_parser_iso639Id, NULL);
+ if (language)
+ {
+ if (priv->current_parser_variant)
+ add_layout_to_table (priv->layouts_by_language, language, priv->current_parser_variant);
+ else if (priv->current_parser_layout)
+ add_layout_to_table (priv->layouts_by_language, language, priv->current_parser_layout);
+
+ g_free (language);
+ }
+
+ g_clear_pointer (&priv->current_parser_iso639Id, g_free);
+ }
+ else if (strcmp (element_name, "iso3166Id") == 0)
+ {
+ gchar *country;
- if (!replaced)
- g_free (priv->current_parser_iso639Id);
+ if (!priv->current_parser_iso3166Id)
+ {
+ g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
+ "'iso3166Id' elements must enclose text");
+ return;
+ }
+
+ country = gnome_get_region_from_name (priv->current_parser_iso3166Id, NULL);
+ if (country)
+ {
+ if (priv->current_parser_variant)
+ add_layout_to_table (priv->layouts_by_country, country, priv->current_parser_variant);
+ else if (priv->current_parser_layout)
+ add_layout_to_table (priv->layouts_by_country, country, priv->current_parser_layout);
+
+ g_free (country);
+ }
- priv->current_parser_iso639Id = NULL;
+ g_clear_pointer (&priv->current_parser_iso3166Id, g_free);
}
else if (strcmp (element_name, "group") == 0)
{
@@ -494,6 +537,7 @@ parse_error (GMarkupParseContext *context,
free_layout (priv->current_parser_layout);
free_layout (priv->current_parser_variant);
g_free (priv->current_parser_iso639Id);
+ g_free (priv->current_parser_iso3166Id);
}
static const GMarkupParser markup_parser = {
@@ -542,8 +586,16 @@ parse_rules (GnomeXkbInfo *self)
XkbOptionGroup structs. */
priv->option_groups_table = g_hash_table_new_full (g_str_hash, g_str_equal,
NULL, free_option_group);
- priv->layouts_by_short_desc = g_hash_table_new (g_str_hash, g_str_equal);
- priv->layouts_by_iso639 = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ /* Maps country strings to a GSequence which is a set of Layout
+ struct pointers into the Layout structs stored in
+ layouts_table. */
+ priv->layouts_by_country = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, (GDestroyNotify) g_sequence_free);
+ /* Maps language strings to a GSequence which is a set of Layout
+ struct pointers into the Layout structs stored in
+ layouts_table. */
+ priv->layouts_by_language = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, (GDestroyNotify) g_sequence_free);
/* Maps layout ids to Layout structs. Owns the Layout structs. */
priv->layouts_table = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, free_layout);
@@ -553,6 +605,8 @@ parse_rules (GnomeXkbInfo *self)
goto cleanup;
g_free (file_path);
+ sort_sequences (self);
+
settings = g_settings_new ("org.gnome.desktop.input-sources");
show_all_sources = g_settings_get_boolean (settings, "show-all-sources");
g_object_unref (settings);
@@ -566,6 +620,8 @@ parse_rules (GnomeXkbInfo *self)
goto cleanup;
g_free (file_path);
+ sort_sequences (self);
+
return;
cleanup:
@@ -573,8 +629,8 @@ parse_rules (GnomeXkbInfo *self)
g_clear_pointer (&error, g_error_free);
g_clear_pointer (&file_path, g_free);
g_clear_pointer (&priv->option_groups_table, g_hash_table_destroy);
- g_clear_pointer (&priv->layouts_by_short_desc, g_hash_table_destroy);
- g_clear_pointer (&priv->layouts_by_iso639, g_hash_table_destroy);
+ g_clear_pointer (&priv->layouts_by_country, g_hash_table_destroy);
+ g_clear_pointer (&priv->layouts_by_language, g_hash_table_destroy);
g_clear_pointer (&priv->layouts_table, g_hash_table_destroy);
}
@@ -602,10 +658,10 @@ gnome_xkb_info_finalize (GObject *self)
if (priv->option_groups_table)
g_hash_table_destroy (priv->option_groups_table);
- if (priv->layouts_by_short_desc)
- g_hash_table_destroy (priv->layouts_by_short_desc);
- if (priv->layouts_by_iso639)
- g_hash_table_destroy (priv->layouts_by_iso639);
+ if (priv->layouts_by_country)
+ g_hash_table_destroy (priv->layouts_by_country);
+ if (priv->layouts_by_language)
+ g_hash_table_destroy (priv->layouts_by_language);
if (priv->layouts_table)
g_hash_table_destroy (priv->layouts_table);
@@ -931,12 +987,7 @@ gnome_xkb_info_get_layout_info_for_language (GnomeXkbInfo *self,
if (!ensure_rules_are_parsed (self))
return FALSE;
- /* First look in the proper language codes index, if we can't find
- * it there try again on the (untranslated) short descriptions since
- * sometimes those will give us a good match. */
- if (!g_hash_table_lookup_extended (priv->layouts_by_iso639, language, NULL, (gpointer *)&layout))
- if (!g_hash_table_lookup_extended (priv->layouts_by_short_desc, language, NULL, (gpointer *)&layout))
- return FALSE;
+ return FALSE; /* FIXME */
if (id)
*id = layout->id;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]