[evolution] Bug 561799 - Simplify language selection in message composer
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution] Bug 561799 - Simplify language selection in message composer
- Date: Tue, 30 Oct 2018 10:01:22 +0000 (UTC)
commit 6a0409a985978c5fa5e68e686eb04b36f1faf71c
Author: Milan Crha <mcrha redhat com>
Date: Tue Oct 30 11:01:23 2018 +0100
Bug 561799 - Simplify language selection in message composer
Closes https://bugzilla.gnome.org/show_bug.cgi?id=561799
data/org.gnome.evolution.mail.gschema.xml.in | 9 ++
src/e-util/e-html-editor-actions.c | 166 ++++++++++++++++++++++++++-
src/e-util/e-html-editor-manager.ui | 6 +-
src/e-util/e-html-editor-private.h | 1 +
src/e-util/e-misc-utils.c | 116 +++++++++++++------
src/e-util/e-misc-utils.h | 3 +
6 files changed, 261 insertions(+), 40 deletions(-)
---
diff --git a/data/org.gnome.evolution.mail.gschema.xml.in b/data/org.gnome.evolution.mail.gschema.xml.in
index a9e0e2c852..9c2504633c 100644
--- a/data/org.gnome.evolution.mail.gschema.xml.in
+++ b/data/org.gnome.evolution.mail.gschema.xml.in
@@ -125,6 +125,15 @@
<_summary>Spell checking languages</_summary>
<_description>List of dictionary language codes used for spell checking.</_description>
</key>
+ <key name="composer-spell-languages-recently-used" type="as">
+ <default>[]</default>
+ <_summary>List of recently used spell checking languages</_summary>
+ <_description>List of dictionary language codes used for spell checking, which had been used
recently.</_description>
+ </key>
+ <key name="composer-spell-languages-max-recently-used" type="i">
+ <default>5</default>
+ <_summary>How many recently used spell checking languages to remember</_summary>
+ </key>
<key name="composer-show-bcc" type="b">
<default>false</default>
<_summary>Show “Bcc” field when sending a mail message</_summary>
diff --git a/src/e-util/e-html-editor-actions.c b/src/e-util/e-html-editor-actions.c
index 8f7eeceed4..f2cd27636d 100644
--- a/src/e-util/e-html-editor-actions.c
+++ b/src/e-util/e-html-editor-actions.c
@@ -440,6 +440,10 @@ action_insert_text_file_cb (GtkAction *action,
gtk_widget_destroy (dialog);
}
+static gboolean
+editor_actions_add_to_recent_languages (EHTMLEditor *editor,
+ const gchar *language_code);
+
static void
action_language_cb (GtkToggleAction *toggle_action,
EHTMLEditor *editor)
@@ -468,6 +472,41 @@ action_language_cb (GtkToggleAction *toggle_action,
e_html_editor_update_spell_actions (editor);
g_signal_emit_by_name (editor, "spell-languages-changed");
+
+ if (active) {
+ GSettings *settings;
+ GPtrArray *array;
+ gchar **strv;
+ gint ii, max_items;
+
+ gtk_ui_manager_remove_ui (editor->priv->manager,
editor->priv->recent_spell_languages_merge_id);
+
+ settings = e_util_ref_settings ("org.gnome.evolution.mail");
+ strv = g_settings_get_strv (settings, "composer-spell-languages-recently-used");
+ max_items = g_settings_get_int (settings, "composer-spell-languages-max-recently-used");
+ if (max_items < 5)
+ max_items = 5;
+
+ array = g_ptr_array_sized_new (max_items + 1);
+ g_ptr_array_add (array, (gpointer) language_code);
+
+ editor_actions_add_to_recent_languages (editor, language_code);
+
+ for (ii = 0; strv && strv[ii] && array->len < max_items; ii++) {
+ if (g_strcmp0 (language_code, strv[ii]) != 0) {
+ g_ptr_array_add (array, strv[ii]);
+ editor_actions_add_to_recent_languages (editor, strv[ii]);
+ }
+ }
+
+ g_ptr_array_add (array, NULL);
+
+ g_settings_set_strv (settings, "composer-spell-languages-recently-used", (const gchar * const
*) array->pdata);
+
+ g_object_unref (settings);
+ g_ptr_array_free (array, TRUE);
+ g_strfreev (strv);
+ }
}
static gboolean
@@ -1606,6 +1645,49 @@ static GtkActionEntry spell_context_entries[] = {
NULL }
};
+static gboolean
+editor_actions_add_to_recent_languages (EHTMLEditor *editor,
+ const gchar *language_code)
+{
+ GtkAction *language_action;
+ gchar *name;
+
+ g_return_val_if_fail (E_IS_HTML_EDITOR (editor), FALSE);
+ g_return_val_if_fail (language_code != NULL, FALSE);
+
+ language_action = gtk_action_group_get_action (editor->priv->language_actions, language_code);
+ if (!language_action)
+ return FALSE;
+
+ name = g_strconcat ("recent-spell-language-", language_code, NULL);
+
+ if (!gtk_action_group_get_action (editor->priv->language_actions, name)) {
+ GtkToggleAction *toggle_action;
+
+ toggle_action = gtk_toggle_action_new (name,
+ gtk_action_get_label (language_action),
+ gtk_action_get_tooltip (language_action),
+ NULL);
+
+ e_binding_bind_property (language_action, "active",
+ toggle_action, "active",
+ G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+
+ gtk_action_group_add_action (editor->priv->language_actions, GTK_ACTION (toggle_action));
+
+ g_object_unref (toggle_action);
+ }
+
+ gtk_ui_manager_add_ui (
+ editor->priv->manager, editor->priv->recent_spell_languages_merge_id,
+ "/main-menu/edit-menu/language-menu/recent-languages",
+ name, name, GTK_UI_MANAGER_AUTO, FALSE);
+
+ g_free (name);
+
+ return TRUE;
+}
+
static void
editor_actions_setup_languages_menu (EHTMLEditor *editor)
{
@@ -1613,31 +1695,52 @@ editor_actions_setup_languages_menu (EHTMLEditor *editor)
EContentEditor *cnt_editor;
GtkUIManager *manager;
GtkActionGroup *action_group;
+ GHashTable *lang_parents; /* gchar *name ~> GtkAction * */
GList *list = NULL, *link;
+ GSettings *settings;
+ gchar **strv;
+ gint ii, added = 0, max_items;
guint merge_id;
+ lang_parents = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
manager = editor->priv->manager;
action_group = editor->priv->language_actions;
cnt_editor = e_html_editor_get_content_editor (editor);
spell_checker = e_content_editor_ref_spell_checker (cnt_editor);
merge_id = gtk_ui_manager_new_merge_id (manager);
+ editor->priv->recent_spell_languages_merge_id = gtk_ui_manager_new_merge_id (manager);
list = e_spell_checker_list_available_dicts (spell_checker);
for (link = list; link != NULL; link = g_list_next (link)) {
ESpellDictionary *dictionary = link->data;
+ GtkAction *parent_action;
GtkToggleAction *action;
- const gchar *language_name;
+ const gchar *dictionay_name;
+ gchar *language_name, *path;
GString *escaped_name = NULL;
gboolean active = FALSE;
- language_name = e_spell_dictionary_get_name (dictionary);
- if (language_name && strchr (language_name, '_') != NULL)
- escaped_name = e_str_replace_string (language_name, "_", "__");
+ if (!e_util_get_language_info (e_spell_dictionary_get_code (dictionary), &language_name,
NULL)) {
+ language_name = g_strdup (e_spell_dictionary_get_code (dictionary));
+ if (language_name) {
+ gchar *ptr;
+
+ ptr = strchr (language_name, '_');
+ if (ptr)
+ *ptr = '\0';
+ } else {
+ language_name = g_strdup ("");
+ }
+ }
+
+ dictionay_name = e_spell_dictionary_get_name (dictionary);
+ if (dictionay_name && strchr (dictionay_name, '_') != NULL)
+ escaped_name = e_str_replace_string (dictionay_name, "_", "__");
action = gtk_toggle_action_new (
e_spell_dictionary_get_code (dictionary),
- escaped_name ? escaped_name->str : language_name,
+ escaped_name ? escaped_name->str : dictionay_name,
NULL, NULL);
if (escaped_name)
@@ -1659,16 +1762,63 @@ editor_actions_setup_languages_menu (EHTMLEditor *editor)
g_object_unref (action);
+ parent_action = g_hash_table_lookup (lang_parents, language_name);
+ if (!parent_action) {
+ gchar *name, *tmp;
+
+ name = g_strdup (e_spell_dictionary_get_code (dictionary));
+ tmp = strchr (name, '_');
+ if (tmp)
+ *tmp = '\0';
+
+ tmp = g_strconcat ("language-parent-", name, NULL);
+ g_free (name);
+ name = tmp;
+
+ parent_action = gtk_action_new (name, language_name, NULL, NULL);
+
+ gtk_action_group_add_action (action_group, parent_action);
+
+ g_hash_table_insert (lang_parents, g_strdup (language_name), parent_action);
+
+ gtk_ui_manager_add_ui (
+ manager, merge_id,
+ "/main-menu/edit-menu/language-menu/all-languages",
+ name, name, GTK_UI_MANAGER_MENU, FALSE);
+
+ g_free (name);
+ }
+
+ path = g_strconcat ("/main-menu/edit-menu/language-menu/all-languages/", gtk_action_get_name
(parent_action), NULL);
+
gtk_ui_manager_add_ui (
manager, merge_id,
- "/main-menu/edit-menu/language-menu",
+ path,
e_spell_dictionary_get_code (dictionary),
e_spell_dictionary_get_code (dictionary),
GTK_UI_MANAGER_AUTO, FALSE);
+
+ g_free (language_name);
+ g_free (path);
}
g_list_free (list);
g_clear_object (&spell_checker);
+ g_hash_table_destroy (lang_parents);
+
+ settings = e_util_ref_settings ("org.gnome.evolution.mail");
+ strv = g_settings_get_strv (settings, "composer-spell-languages-recently-used");
+ max_items = g_settings_get_int (settings, "composer-spell-languages-max-recently-used");
+ if (max_items < 5)
+ max_items = 5;
+ g_object_unref (settings);
+
+ for (ii = 0; strv && strv[ii] && added < max_items; ii++) {
+ if (editor_actions_add_to_recent_languages (editor, strv[ii]))
+ added++;
+ }
+
+ g_strfreev (strv);
}
static void
@@ -2024,6 +2174,10 @@ editor_actions_update_spellcheck_languages_menu (EHTMLEditor *editor,
if (!GTK_IS_TOGGLE_ACTION (link->data))
continue;
+ if (gtk_action_get_name (link->data) &&
+ g_str_has_prefix (gtk_action_get_name (link->data), "recent-spell-language-"))
+ continue;
+
is_active = g_hash_table_contains (active, gtk_action_get_name (link->data));
toggle_action = GTK_TOGGLE_ACTION (link->data);
diff --git a/src/e-util/e-html-editor-manager.ui b/src/e-util/e-html-editor-manager.ui
index fa7bc0bbbf..487dce6be0 100644
--- a/src/e-util/e-html-editor-manager.ui
+++ b/src/e-util/e-html-editor-manager.ui
@@ -22,7 +22,11 @@
<separator/>
<placeholder name='pre-spell-check'/>
<menuitem action='spell-check'/>
- <menu action='language-menu'/>
+ <menu action='language-menu'>
+ <placeholder name='recent-languages'/>
+ <separator/>
+ <placeholder name='all-languages'/>
+ </menu>
</menu>
<placeholder name='pre-insert-menu'>
<menu action='view-menu'>
diff --git a/src/e-util/e-html-editor-private.h b/src/e-util/e-html-editor-private.h
index b652f0a538..ec068f4ae6 100644
--- a/src/e-util/e-html-editor-private.h
+++ b/src/e-util/e-html-editor-private.h
@@ -89,6 +89,7 @@ struct _EHTMLEditorPrivate {
gchar *filename;
guint spell_suggestions_merge_id;
+ guint recent_spell_languages_merge_id;
gint editor_layout_row;
diff --git a/src/e-util/e-misc-utils.c b/src/e-util/e-misc-utils.c
index 21896b470b..8c7e5c544d 100644
--- a/src/e-util/e-misc-utils.c
+++ b/src/e-util/e-misc-utils.c
@@ -4416,30 +4416,49 @@ iso_codes_parse (const GMarkupParser *parser,
#endif /* HAVE_ISO_CODES */
/**
- * e_util_get_language_name:
- * @language_tag: Language tag to get its name for
+ * e_util_get_language_info:
+ * @language_tag: Language tag to get its name for, like "en_US"
+ * @out_language_name: (out) (nullable) (transfer full): Return location for the language name, or %NULL
+ * @out_country_name: (out) (nullable) (transfer full): Return location for the country name, or %NULL
*
- * Returns: (transfer full): Newly allocated string with localized language name
+ * Splits language tag into a localized language name and country name (the variant).
+ * The @out_language_name is always filled when the function returns %TRUE, but
+ * the @out_countr_name can be %NULL. That's for cases when the @language_tag
+ * contains only the country part, like "en".
+ *
+ * The function returns %FALSE when it could not decode language name from
+ * the given @language_tag. When either of the @out_language_name and @out_country_name
+ * is non-NULL and the function returns %TRUE, then their respective values
+ * should be freed with g_free(), when no longer needed.
+ *
+ * Returns: %TRUE, when could get at least language name from the @language_tag,
+ * %FALSE otherwise.
*
* Since: 3.32
**/
-gchar *
-e_util_get_language_name (const gchar *language_tag)
+gboolean
+e_util_get_language_info (const gchar *language_tag,
+ gchar **out_language_name,
+ gchar **out_country_name)
{
const gchar *iso_639_name;
const gchar *iso_3166_name;
- gchar *language_name;
gchar *lowercase;
gchar **tokens;
- g_return_val_if_fail (language_tag != NULL, NULL);
+ g_return_val_if_fail (language_tag != NULL, FALSE);
+
+ if (out_language_name)
+ *out_language_name = NULL;
+ if (out_country_name)
+ *out_country_name = NULL;
/* Split language code into lowercase tokens. */
lowercase = g_ascii_strdown (language_tag, -1);
tokens = g_strsplit (lowercase, "_", -1);
g_free (lowercase);
- g_return_val_if_fail (tokens != NULL, NULL);
+ g_return_val_if_fail (tokens != NULL, FALSE);
if (!iso_639_table && !iso_3166_table) {
#if defined (ENABLE_NLS) && defined (HAVE_ISO_CODES)
@@ -4472,46 +4491,77 @@ e_util_get_language_name (const gchar *language_tag)
iso_639_name = g_hash_table_lookup (iso_639_table, tokens[0]);
- if (iso_639_name == NULL) {
- language_name = g_strdup_printf (
- /* Translators: %s is the language ISO code. */
- C_("language", "Unknown (%s)"), language_tag);
- goto exit;
+ if (!iso_639_name) {
+ g_strfreev (tokens);
+ return FALSE;
}
- if (g_strv_length (tokens) < 2) {
- language_name = g_strdup (iso_639_name);
+ if (out_language_name)
+ *out_language_name = g_strdup (iso_639_name);
+
+ if (g_strv_length (tokens) < 2)
goto exit;
- }
- iso_3166_name = g_hash_table_lookup (iso_3166_table, tokens[1]);
+ if (out_country_name) {
+ iso_3166_name = g_hash_table_lookup (iso_3166_table, tokens[1]);
- if (iso_3166_name != NULL)
- language_name = g_strdup_printf (
- /* Translators: The first %s is the language name, and the
- * second is the country name. Example: "French (France)" */
- C_("language", "%s (%s)"), iso_639_name, iso_3166_name);
- else
- language_name = g_strdup_printf (
- /* Translators: The first %s is the language name, and the
- * second is the country name. Example: "French (France)" */
- C_("language", "%s (%s)"), iso_639_name, tokens[1]);
+ if (iso_3166_name)
+ *out_country_name = g_strdup (iso_3166_name);
+ else
+ *out_country_name = g_strdup (tokens[1]);
+ }
exit:
- g_strfreev (tokens);
-
- if (language_name) {
+ if (out_country_name && *out_country_name) {
gchar *ptr;
- /* When the name has two or more ';' then strip the string at the second of them */
- ptr = strchr (language_name, ';');
+ /* When the country name has two or more ';' then strip the string at the second of them */
+ ptr = strchr (*out_country_name, ';');
if (ptr)
ptr = strchr (ptr + 1, ';');
if (ptr)
*ptr = '\0';
}
- return language_name;
+ g_strfreev (tokens);
+
+ return TRUE;
+}
+
+/**
+ * e_util_get_language_name:
+ * @language_tag: Language tag to get its name for, like "en_US"
+ *
+ * Returns: (transfer full): Newly allocated string with localized language name
+ *
+ * Since: 3.32
+ **/
+gchar *
+e_util_get_language_name (const gchar *language_tag)
+{
+ gchar *language_name = NULL, *country_name = NULL;
+ gchar *res;
+
+ g_return_val_if_fail (language_tag != NULL, NULL);
+
+ if (!e_util_get_language_info (language_tag, &language_name, &country_name)) {
+ return g_strdup_printf (
+ /* Translators: %s is the language ISO code. */
+ C_("language", "Unknown (%s)"), language_tag);
+ }
+
+ if (!country_name)
+ return language_name;
+
+ res = g_strdup_printf (
+ /* Translators: The first %s is the language name, and the
+ * second is the country name. Example: "French (France)" */
+ C_("language", "%s (%s)"), language_name, country_name);
+
+ g_free (language_name);
+ g_free (country_name);
+
+ return res;
}
/**
diff --git a/src/e-util/e-misc-utils.h b/src/e-util/e-misc-utils.h
index 3b8e976758..8c5551b246 100644
--- a/src/e-util/e-misc-utils.h
+++ b/src/e-util/e-misc-utils.h
@@ -348,6 +348,9 @@ gboolean e_util_query_ldap_root_dse_sync (const gchar *host,
GCancellable *cancellable,
GError **error);
gchar * e_util_get_language_name (const gchar *language_tag);
+gboolean e_util_get_language_info (const gchar *language_tag,
+ gchar **out_language_name,
+ gchar **out_country_name);
void e_misc_util_free_global_memory (void);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]