From 26e03eb5ff87e6148a7a316c9538e94e6587cfe3 Mon Sep 17 00:00:00 2001 From: Vitaly Minko Date: Fri, 15 Oct 2010 11:18:56 +0200 Subject: [PATCH] Separate spelling suggestions in one sub-menu per language (#532832) --- libempathy-gtk/empathy-chat.c | 90 +++++++++++++++++++++++++-------- libempathy-gtk/empathy-spell.c | 91 ++++++++++++++++++++-------------- libempathy-gtk/empathy-spell.h | 4 +- src/empathy-preferences.c | 35 ++++++------- 4 files changed, 138 insertions(+), 82 deletions(-) diff --git a/libempathy-gtk/empathy-chat.c b/libempathy-gtk/empathy-chat.c index 295ee6af..fb8d538e 100644 --- a/libempathy-gtk/empathy-chat.c +++ b/libempathy-gtk/empathy-chat.c @@ -1763,33 +1763,79 @@ chat_spelling_menu_activate_cb (GtkMenuItem *menu_item, gtk_menu_item_get_label (menu_item)); } + +static GtkWidget * +chat_spelling_build_suggestions_menu (const gchar *code, + EmpathyChatSpell *chat_spell) +{ + GList *suggestions, *l; + GtkWidget *menu, *menu_item; + + suggestions = empathy_spell_get_suggestions (code, chat_spell->word); + if (suggestions == NULL) + return NULL; + + menu = gtk_menu_new (); + for (l = suggestions; l; l = l->next) { + menu_item = gtk_menu_item_new_with_label (l->data); + g_signal_connect (G_OBJECT (menu_item), "activate", + G_CALLBACK (chat_spelling_menu_activate_cb), + chat_spell); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); + } + empathy_spell_free_suggestions (suggestions); + + gtk_widget_show_all (menu); + + return menu; +} + static GtkWidget * chat_spelling_build_menu (EmpathyChatSpell *chat_spell) { - GtkWidget *menu, *menu_item; - GList *suggestions, *l; - - menu = gtk_menu_new (); - suggestions = empathy_spell_get_suggestions (chat_spell->word); - if (suggestions == NULL) { - menu_item = gtk_menu_item_new_with_label (_("(No Suggestions)")); - gtk_widget_set_sensitive (menu_item, FALSE); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); - } else { - for (l = suggestions; l; l = l->next) { - menu_item = gtk_menu_item_new_with_label (l->data); - g_signal_connect (G_OBJECT (menu_item), - "activate", - G_CALLBACK (chat_spelling_menu_activate_cb), - chat_spell); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); - } - } - empathy_spell_free_suggestions (suggestions); + GtkWidget *menu, *submenu, *item; + GList *codes, *l; - gtk_widget_show_all (menu); + codes = empathy_spell_get_enabled_language_codes (); + g_assert (codes != NULL); - return menu; + if (g_list_length (codes) > 1) { + menu = gtk_menu_new (); + + for (l = codes; l; l = l->next) { + const gchar *code, *name; + + code = l->data; + name = empathy_spell_get_language_name (code); + if (!name) + continue; + + item = gtk_image_menu_item_new_with_label (name); + + submenu = chat_spelling_build_suggestions_menu ( + code, chat_spell); + if (submenu == NULL) + gtk_widget_set_sensitive (item, FALSE); + else + gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), + submenu); + gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item); + } + } else { + menu = chat_spelling_build_suggestions_menu (codes->data, + chat_spell); + if (menu == NULL) { + menu = gtk_menu_new (); + item = gtk_menu_item_new_with_label (_("(No Suggestions)")); + gtk_widget_set_sensitive (item, FALSE); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + } + } + g_list_free (codes); + + gtk_widget_show_all (menu); + + return menu; } static void diff --git a/libempathy-gtk/empathy-spell.c b/libempathy-gtk/empathy-spell.c index ff94bb05..b9abcd5f 100644 --- a/libempathy-gtk/empathy-spell.c +++ b/libempathy-gtk/empathy-spell.c @@ -48,8 +48,11 @@ typedef struct { #define ISO_CODES_DATADIR ISO_CODES_PREFIX "/share/xml/iso-codes" #define ISO_CODES_LOCALESDIR ISO_CODES_PREFIX "/share/locale" +/* Language code (gchar *) -> language name (gchar *) */ static GHashTable *iso_code_names = NULL; -static GList *languages = NULL; +/* Contains only _enabled_ languages + * Language code (gchar *) -> language (SpellLanguage *) */ +static GHashTable *languages = NULL; static void spell_iso_codes_parse_start_tag (GMarkupParseContext *ctx, @@ -162,24 +165,22 @@ spell_notify_languages_cb (GSettings *gsettings, const gchar *key, gpointer user_data) { - GList *l; - DEBUG ("Resetting languages due to config change"); /* We just reset the languages list. */ - for (l = languages; l; l = l->next) { - SpellLanguage *lang; - - lang = l->data; - - enchant_broker_free_dict (lang->config, lang->speller); - enchant_broker_free (lang->config); - - g_slice_free (SpellLanguage, lang); + if (languages != NULL) { + g_hash_table_destroy (languages); + languages = NULL; } +} + +static void +empathy_spell_free_language (SpellLanguage *lang) +{ + enchant_broker_free_dict (lang->config, lang->speller); + enchant_broker_free (lang->config); - g_list_free (languages); - languages = NULL; + g_slice_free (SpellLanguage, lang); } static void @@ -201,6 +202,9 @@ spell_setup_languages (void) return; } + languages = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, (GDestroyNotify) empathy_spell_free_language); + str = g_settings_get_string (gsettings, EMPATHY_PREFS_CHAT_SPELL_CHECKER_LANGUAGES); @@ -224,7 +228,9 @@ spell_setup_languages (void) if (lang->speller == NULL) { DEBUG ("language '%s' has no valid dict", strv[i]); } else { - languages = g_list_append (languages, lang); + g_hash_table_insert (languages, + g_strdup (strv[i]), + lang); } i++; @@ -294,6 +300,13 @@ empathy_spell_get_language_codes (void) return list_langs; } +GList * +empathy_spell_get_enabled_language_codes (void) +{ + spell_setup_languages (); + return g_hash_table_get_keys (languages); +} + void empathy_spell_free_language_codes (GList *codes) { @@ -309,7 +322,8 @@ empathy_spell_check (const gchar *word) gboolean digit; gunichar c; gint len; - GList *l; + GHashTableIter iter; + SpellLanguage *lang; g_return_val_if_fail (word != NULL, FALSE); @@ -332,11 +346,8 @@ empathy_spell_check (const gchar *word) } len = strlen (word); - for (l = languages; l; l = l->next) { - SpellLanguage *lang; - - lang = l->data; - + g_hash_table_iter_init (&iter, languages); + while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &lang)) { enchant_result = enchant_dict_check (lang->speller, word, len); if (enchant_result == 0) { @@ -348,36 +359,40 @@ empathy_spell_check (const gchar *word) } GList * -empathy_spell_get_suggestions (const gchar *word) +empathy_spell_get_suggestions (const gchar *code, const gchar *word) { gint len; - GList *l1; GList *suggestion_list = NULL; + SpellLanguage *lang; + gchar **suggestions; + gsize i, number_of_suggestions; + g_return_val_if_fail (code != NULL, NULL); g_return_val_if_fail (word != NULL, NULL); spell_setup_languages (); - len = strlen (word); + if (!languages) { + return NULL; + } - for (l1 = languages; l1; l1 = l1->next) { - SpellLanguage *lang; - gchar **suggestions; - gsize i, number_of_suggestions; + len = strlen (word); - lang = l1->data; + lang = g_hash_table_lookup (languages, code); + if (!lang) { + return NULL; + } - suggestions = enchant_dict_suggest (lang->speller, word, len, - &number_of_suggestions); + suggestions = enchant_dict_suggest (lang->speller, word, len, + &number_of_suggestions); - for (i = 0; i < number_of_suggestions; i++) { - suggestion_list = g_list_append (suggestion_list, - g_strdup (suggestions[i])); - } + for (i = 0; i < number_of_suggestions; i++) { + suggestion_list = g_list_append (suggestion_list, + g_strdup (suggestions[i])); + } - if (suggestions) { - enchant_dict_free_string_list (lang->speller, suggestions); - } + if (suggestions) { + enchant_dict_free_string_list (lang->speller, suggestions); } return suggestion_list; diff --git a/libempathy-gtk/empathy-spell.h b/libempathy-gtk/empathy-spell.h index 65dbb131..aa2a3e51 100644 --- a/libempathy-gtk/empathy-spell.h +++ b/libempathy-gtk/empathy-spell.h @@ -31,9 +31,11 @@ G_BEGIN_DECLS gboolean empathy_spell_supported (void); const gchar *empathy_spell_get_language_name (const gchar *code); GList *empathy_spell_get_language_codes (void); +GList *empathy_spell_get_enabled_language_codes (void); void empathy_spell_free_language_codes (GList *codes); gboolean empathy_spell_check (const gchar *word); -GList * empathy_spell_get_suggestions (const gchar *word); +GList * empathy_spell_get_suggestions (const gchar *code, + const gchar *word); void empathy_spell_free_suggestions (GList *suggestions); G_END_DECLS diff --git a/src/empathy-preferences.c b/src/empathy-preferences.c index 89133edb..813637dc 100644 --- a/src/empathy-preferences.c +++ b/src/empathy-preferences.c @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -101,7 +102,7 @@ static void preferences_languages_load (EmpathyPreferences static gboolean preferences_languages_load_foreach (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, - gchar **languages); + GList *languages); static void preferences_languages_cell_toggled_cb (GtkCellRendererToggle *cell, gchar *path_string, EmpathyPreferences *preferences); @@ -471,9 +472,6 @@ preferences_languages_add (EmpathyPreferences *preferences) codes = empathy_spell_get_language_codes (); - g_settings_set_boolean (priv->gsettings_chat, - EMPATHY_PREFS_CHAT_SPELL_CHECKER_ENABLED, - codes != NULL); if (!codes) { gtk_widget_set_sensitive (priv->treeview_spell_checker, FALSE); } @@ -569,37 +567,34 @@ preferences_languages_load (EmpathyPreferences *preferences) EmpathyPreferencesPriv *priv = GET_PRIV (preferences); GtkTreeView *view; GtkTreeModel *model; - gchar *value; - gchar **vlanguages; + GList *enabled_codes; - value = g_settings_get_string (priv->gsettings_chat, - EMPATHY_PREFS_CHAT_SPELL_CHECKER_LANGUAGES); + enabled_codes = empathy_spell_get_enabled_language_codes (); - if (value == NULL) - return; + g_settings_set_boolean (priv->gsettings_chat, + EMPATHY_PREFS_CHAT_SPELL_CHECKER_ENABLED, + enabled_codes != NULL); - vlanguages = g_strsplit (value, ",", -1); - g_free (value); + if (enabled_codes == NULL) + return; view = GTK_TREE_VIEW (priv->treeview_spell_checker); model = gtk_tree_view_get_model (view); gtk_tree_model_foreach (model, (GtkTreeModelForeachFunc) preferences_languages_load_foreach, - vlanguages); + enabled_codes); - g_strfreev (vlanguages); + g_list_free (enabled_codes); } static gboolean preferences_languages_load_foreach (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, - gchar **languages) + GList *languages) { gchar *code; - gchar *lang; - gint i; gboolean found = FALSE; if (!languages) { @@ -611,10 +606,8 @@ preferences_languages_load_foreach (GtkTreeModel *model, return FALSE; } - for (i = 0, lang = languages[i]; lang; lang = languages[++i]) { - if (!tp_strdiff (lang, code)) { - found = TRUE; - } + if (g_list_find_custom (languages, code, (GCompareFunc) strcmp)) { + found = TRUE; } g_free (code); -- 2.39.2