[epiphany] Add spell checker support to context menu



commit c398d645a0c9587ea17a31cfde7b33308977ec24
Author: Jan-Michael Brummer <jan brummer tabos org>
Date:   Sat Jun 1 16:58:50 2019 +0200

    Add spell checker support to context menu
    
    Fixes: https://gitlab.gnome.org/GNOME/epiphany/issues/181

 data/org.gnome.epiphany.gschema.xml |  5 +++
 embed/ephy-embed-prefs.c            | 49 ++++++-----------------
 lib/ephy-langs.c                    | 59 +++++++++++++++++++++++++++
 lib/ephy-langs.h                    | 12 ++++--
 lib/ephy-prefs.h                    |  2 +
 src/ephy-window.c                   | 80 +++++++++++++++++++++++++++++++++----
 src/prefs-dialog.c                  | 36 +----------------
 src/window-commands.c               | 15 +++++++
 src/window-commands.h               |  3 ++
 9 files changed, 181 insertions(+), 80 deletions(-)
---
diff --git a/data/org.gnome.epiphany.gschema.xml b/data/org.gnome.epiphany.gschema.xml
index ee8dc6c1a..4c805e148 100644
--- a/data/org.gnome.epiphany.gschema.xml
+++ b/data/org.gnome.epiphany.gschema.xml
@@ -140,6 +140,11 @@
                        <summary>Enable spell checking</summary>
                        <description>Spell check any text typed in editable areas.</description>
                </key>
+               <key type="s" name="spell-checker-language">
+                       <default>''</default>
+                       <summary>Spell checking language</summary>
+                       <description>Language which is used by Spell checker in locale format (e.g. en_US, 
de_DE).</description>
+               </key>
                <key type="s" name="default-encoding">
                        <default>'iso-8859-1'</default>
                        <summary>Default encoding</summary>
diff --git a/embed/ephy-embed-prefs.c b/embed/ephy-embed-prefs.c
index a3158fcd8..02e0c0747 100644
--- a/embed/ephy-embed-prefs.c
+++ b/embed/ephy-embed-prefs.c
@@ -218,32 +218,6 @@ webkit_pref_callback_font_family (GSettings  *settings,
   g_free (value);
 }
 
-static char **
-normalize_languages (char **languages)
-{
-  int i;
-  GPtrArray *langs;
-
-  langs = g_ptr_array_new ();
-
-  for (i = 0; languages && languages[i]; i++) {
-    if (!strcmp (languages[i], "system")) {
-      char **sys_langs = ephy_langs_get_languages ();
-      int j;
-
-      for (j = 0; sys_langs && sys_langs[j]; j++)
-        g_ptr_array_add (langs, g_strdelimit (g_strdup (sys_langs[i]), "-", '_'));
-
-      g_strfreev (sys_langs);
-    } else
-      g_ptr_array_add (langs, g_strdelimit (g_strdup (languages[i]), "-", '_'));
-  }
-
-  g_ptr_array_add (langs, NULL);
-
-  return (char **)g_ptr_array_free (langs, FALSE);
-}
-
 /* Based on Christian Persch's code from gecko backend of epiphany
    (old transform_accept_languages_list() function) */
 static void
@@ -279,12 +253,6 @@ webkit_pref_callback_accept_languages (GSettings  *settings,
                           g_strdupv ((char **)(void *)array->data),
                           (GDestroyNotify)g_strfreev);
 
-  if (g_settings_get_boolean (EPHY_SETTINGS_WEB, EPHY_PREFS_WEB_ENABLE_SPELL_CHECKING)) {
-    char **normalized = normalize_languages ((char **)(void *)array->data);
-    webkit_web_context_set_spell_checking_languages (web_context, (const char * const *)normalized);
-    g_strfreev (normalized);
-  }
-
   for (i = 0; i < array->len; i++)
     g_free (g_array_index (array, char *, i));
   g_array_free (array, TRUE);
@@ -371,17 +339,26 @@ webkit_pref_callback_enable_spell_checking (GSettings  *settings,
   EphyEmbedShell *shell = ephy_embed_shell_get_default ();
 
   web_context = ephy_embed_shell_get_web_context (shell);
-  value = g_settings_get_boolean (settings, key);
 
+  value = g_settings_get_boolean (settings, key);
   webkit_web_context_set_spell_checking_enabled (web_context, value);
 
   if (value) {
-    char **languages = g_settings_get_strv (settings, EPHY_PREFS_WEB_LANGUAGE);
-    char **normalized = normalize_languages (languages);
+    g_autoptr(GArray) array = g_array_new (TRUE, FALSE, sizeof (char *));
+    g_autofree gchar *language = g_settings_get_string (EPHY_SETTINGS_WEB, 
EPHY_PREFS_WEB_SPELL_CHECKER_LANGUAGE);
+    char **normalized;
+
+    if (strlen (language) == 0) {
+      ephy_langs_append_languages (array);
+    } else {
+      char *str = g_strdup (language);
+
+      g_array_append_val (array, str);
+    }
 
+    normalized = ephy_langs_normalize_languages ((char **)(void *)array->data);
     webkit_web_context_set_spell_checking_languages (web_context, (const char * const *)normalized);
 
-    g_strfreev (languages);
     g_strfreev (normalized);
   }
 }
diff --git a/lib/ephy-langs.c b/lib/ephy-langs.c
index 3b2978c64..d68db8274 100644
--- a/lib/ephy-langs.c
+++ b/lib/ephy-langs.c
@@ -20,6 +20,7 @@
 
 #include "config.h"
 #include "ephy-langs.h"
+#include "gnome-languages.h"
 
 #include <string.h>
 
@@ -128,3 +129,61 @@ ephy_langs_get_languages (void)
 
   return (char **)(void *)g_array_free (array, FALSE);
 }
+
+char **
+ephy_langs_normalize_languages (char **languages)
+{
+  int i;
+  GPtrArray *langs;
+
+  langs = g_ptr_array_new ();
+
+  for (i = 0; languages && languages[i]; i++) {
+    if (!strcmp (languages[i], "system")) {
+      char **sys_langs = ephy_langs_get_languages ();
+      int j;
+
+      for (j = 0; sys_langs && sys_langs[j]; j++)
+        g_ptr_array_add (langs, g_strdelimit (g_strdup (sys_langs[i]), "-", '_'));
+
+      g_strfreev (sys_langs);
+    } else
+      g_ptr_array_add (langs, g_strdelimit (g_strdup (languages[i]), "-", '_'));
+  }
+
+  g_ptr_array_add (langs, NULL);
+
+  return (char **)g_ptr_array_free (langs, FALSE);
+}
+
+char *
+ephy_langs_normalize_locale (const char *locale)
+{
+  char *result = g_strdup (locale);
+
+  /* The result we store in prefs looks like es-ES or en-US. We don't
+   * store codeset (not used in Accept-Langs) and we store with hyphen
+   * instead of underscore (ditto). So here we just uppercase the
+   * country code, converting e.g. es-es to es-ES. We have to do this
+   * because older versions of Epiphany stored locales as entirely
+   * lowercase.
+   */
+  for (char *p = strchr (result, '-'); p != NULL && *p != '\0'; p++)
+    *p = g_ascii_toupper (*p);
+
+  return result;
+}
+
+char *
+ephy_langs_language_for_locale (const char *locale)
+{
+  g_autoptr(GString) string = g_string_new (locale);
+
+  /* Before calling gnome_get_language_from_locale() we have to convert
+   * from web locales (e.g. es-ES) to UNIX (e.g. es_ES.UTF-8).
+   */
+  g_strdelimit (string->str, "-", '_');
+  g_string_append (string, ".UTF-8");
+
+  return gnome_get_language_from_locale (string->str, string->str);
+}
diff --git a/lib/ephy-langs.h b/lib/ephy-langs.h
index d40cc93ba..9dd23931a 100644
--- a/lib/ephy-langs.h
+++ b/lib/ephy-langs.h
@@ -25,10 +25,16 @@
 
 G_BEGIN_DECLS
 
-void                        ephy_langs_append_languages (GArray *array);
+void   ephy_langs_append_languages    (GArray *array);
 
-void                        ephy_langs_sanitise               (GArray *array);
+void   ephy_langs_sanitise            (GArray *array);
 
-char                      **ephy_langs_get_languages      (void);
+char **ephy_langs_get_languages       (void);
+
+char **ephy_langs_normalize_languages (char **languages);
+
+char  *ephy_langs_normalize_locale    (const char *locale);
+
+char  *ephy_langs_language_for_locale (const char *locale);
 
 G_END_DECLS
diff --git a/lib/ephy-prefs.h b/lib/ephy-prefs.h
index b23098051..1e39ecbc3 100644
--- a/lib/ephy-prefs.h
+++ b/lib/ephy-prefs.h
@@ -127,6 +127,7 @@ static const char * const ephy_prefs_state_schema[] = {
 #define EPHY_PREFS_WEB_LAST_DOWNLOAD_DIRECTORY      "last-download-directory"
 #define EPHY_PREFS_WEB_HARDWARE_ACCELERATION_POLICY "hardware-acceleration-policy"
 #define EPHY_PREFS_WEB_ASK_ON_DOWNLOAD              "ask-on-download"
+#define EPHY_PREFS_WEB_SPELL_CHECKER_LANGUAGE       "spell-checker-language"
 
 static const char * const ephy_prefs_web_schema[] = {
   EPHY_PREFS_WEB_FONT_MIN_SIZE,
@@ -159,6 +160,7 @@ static const char * const ephy_prefs_web_schema[] = {
   EPHY_PREFS_WEB_LAST_DOWNLOAD_DIRECTORY,
   EPHY_PREFS_WEB_HARDWARE_ACCELERATION_POLICY,
   EPHY_PREFS_WEB_ASK_ON_DOWNLOAD,
+  EPHY_PREFS_WEB_SPELL_CHECKER_LANGUAGE,
 };
 
 #define EPHY_PREFS_SCHEMA                             "org.gnome.Epiphany"
diff --git a/src/ephy-window.c b/src/ephy-window.c
index a5e59cf77..d3c138529 100644
--- a/src/ephy-window.c
+++ b/src/ephy-window.c
@@ -38,6 +38,7 @@
 #include "ephy-gsb-utils.h"
 #include "ephy-gui.h"
 #include "ephy-header-bar.h"
+#include "ephy-langs.h"
 #include "ephy-link.h"
 #include "ephy-location-entry.h"
 #include "ephy-mouse-gesture-controller.h"
@@ -850,7 +851,9 @@ static const GActionEntry window_entries [] =
   /* Toggle actions */
   { "browse-with-caret", NULL, NULL, "false", window_cmd_change_browse_with_caret_state },
   { "fullscreen", NULL, NULL, "false", window_cmd_change_fullscreen_state },
-  { "allow-popup-windows", NULL, NULL, "true", ephy_window_change_allow_popup_windows_state }
+  { "allow-popup-windows", NULL, NULL, "true", ephy_window_change_allow_popup_windows_state },
+
+  { "set-spell-checker", window_cmd_set_spell_checker, "s" }
 };
 
 static const GActionEntry tab_entries [] = {
@@ -1472,6 +1475,68 @@ parse_context_menu_user_data (WebKitContextMenu *context_menu,
   g_variant_dict_lookup (&dict, "SelectedText", "&s", selected_text);
 }
 
+static void
+add_language_menu (WebKitContextMenu *context_menu,
+                   GActionGroup      *window_action_group)
+{
+  WebKitContextMenuItem *item;
+  WebKitContextMenu *menu;
+  GAction *action;
+  GVariant *target;
+  GArray *array;
+  gchar **languages = NULL;
+  const gchar * const *active_languages;
+
+  languages = g_settings_get_strv (EPHY_SETTINGS_WEB, EPHY_PREFS_WEB_LANGUAGE);
+  if (g_strv_length (languages) == 0)
+    return;
+
+  array = g_array_new (TRUE, FALSE, sizeof (char *));
+
+  for (int i = 0; languages[i]; i++) {
+    if (!g_strcmp0 (languages[i], "system")) {
+      ephy_langs_append_languages (array);
+    } else if (languages[i][0] != '\0') {
+      char *str = g_strdup (languages[i]);
+      g_array_append_val (array, str);
+    }
+  }
+  g_strfreev (languages);
+
+  ephy_langs_sanitise (array);
+
+  languages = ephy_langs_normalize_languages ((char **)(void *)array->data);
+  active_languages = webkit_web_context_get_spell_checking_languages (webkit_web_context_get_default ());
+
+  menu = webkit_context_menu_new ();
+  action = g_action_map_lookup_action (G_ACTION_MAP (window_action_group), "set-spell-checker");
+
+  for (int i = 0; languages[i]; i++) {
+    const char *code = languages[i];
+    g_autofree char *normalized_locale = ephy_langs_normalize_locale (code);
+
+    if (normalized_locale != NULL) {
+      g_autofree char *language_name = ephy_langs_language_for_locale (normalized_locale);
+
+      if (language_name == NULL)
+        continue;
+
+      target = g_variant_new_string (normalized_locale);
+      if (active_languages && g_strv_contains (active_languages, code)) {
+        language_name = g_strdup_printf ("✓ %s", language_name);
+      }
+
+      item = webkit_context_menu_item_new_from_gaction (action, language_name, target);
+      webkit_context_menu_append (menu, item);
+    }
+  }
+
+  item = webkit_context_menu_item_new_with_submenu (_("Languages"), menu);
+  webkit_context_menu_append (context_menu, item);
+
+  g_strfreev (languages);
+}
+
 static gboolean
 populate_context_menu (WebKitWebView       *web_view,
                        WebKitContextMenu   *context_menu,
@@ -1612,10 +1677,6 @@ populate_context_menu (WebKitWebView       *web_view,
     GList *l;
     gboolean has_guesses = FALSE;
 
-    /* FIXME: Add a Spelling Suggestions... submenu. Utilize
-     * WEBKIT_CONTEXT_MENU_ACTION_NO_GUESSES_FOUND,
-     * WEBKIT_CONTEXT_MENU_ACTION_IGNORE_SPELLING, and
-     * WEBKIT_CONTEXT_MENU_ACTION_LEARN_SPELLING. */
     for (l = spelling_guess_items; l; l = g_list_next (l)) {
       WebKitContextMenuItem *item = WEBKIT_CONTEXT_MENU_ITEM (l->data);
 
@@ -1625,10 +1686,9 @@ populate_context_menu (WebKitWebView       *web_view,
     }
     g_list_free (spelling_guess_items);
 
-    if (has_guesses) {
+    if (has_guesses)
       webkit_context_menu_append (context_menu,
                                   webkit_context_menu_item_new_separator ());
-    }
 
     update_edit_actions_sensitivity (window, FALSE);
 
@@ -1658,6 +1718,12 @@ populate_context_menu (WebKitWebView       *web_view,
                                   webkit_context_menu_item_new_separator ());
     add_item_to_context_menu (context_menu, input_methods_item);
     add_item_to_context_menu (context_menu, unicode_item);
+
+    add_language_menu (context_menu, window_action_group);
+
+    webkit_context_menu_append (context_menu,
+                                webkit_context_menu_item_new_separator ());
+
   } else {
     is_document = TRUE;
 
diff --git a/src/prefs-dialog.c b/src/prefs-dialog.c
index 03a554b2f..9f2a1c652 100644
--- a/src/prefs-dialog.c
+++ b/src/prefs-dialog.c
@@ -1491,38 +1491,6 @@ language_editor_selection_changed_cb (GtkTreeSelection *selection,
   language_editor_update_buttons (dialog);
 }
 
-static char *
-normalize_locale (const char *locale)
-{
-  char *result = g_strdup (locale);
-
-  /* The result we store in prefs looks like es-ES or en-US. We don't
-   * store codeset (not used in Accept-Langs) and we store with hyphen
-   * instead of underscore (ditto). So here we just uppercase the
-   * country code, converting e.g. es-es to es-ES. We have to do this
-   * because older versions of Epiphany stored locales as entirely
-   * lowercase.
-   */
-  for (char *p = strchr (result, '-'); p != NULL && *p != '\0'; p++)
-    *p = g_ascii_toupper (*p);
-
-  return result;
-}
-
-static char *
-language_for_locale (const char *locale)
-{
-  g_autoptr(GString) string = g_string_new (locale);
-
-  /* Before calling gnome_get_language_from_locale() we have to convert
-   * from web locales (e.g. es-ES) to UNIX (e.g. es_ES.UTF-8).
-   */
-  g_strdelimit (string->str, "-", '_');
-  g_string_append (string, ".UTF-8");
-
-  return gnome_get_language_from_locale (string->str, string->str);
-}
-
 static void
 create_language_section (PrefsDialog *dialog)
 {
@@ -1583,9 +1551,9 @@ create_language_section (PrefsDialog *dialog)
     if (strcmp (code, "system") == 0) {
       add_system_language_entry (store);
     } else if (code[0] != '\0') {
-      g_autofree char *normalized_locale = normalize_locale (code);
+      g_autofree char *normalized_locale = ephy_langs_normalize_locale (code);
       if (normalized_locale != NULL) {
-        g_autofree char *language_name = language_for_locale (normalized_locale);
+        g_autofree char *language_name = ephy_langs_language_for_locale (normalized_locale);
         if (language_name == NULL)
           language_name = g_strdup (normalized_locale);
         language_editor_add (dialog, normalized_locale, language_name);
diff --git a/src/window-commands.c b/src/window-commands.c
index 4ed1ac0bb..081f7f9d4 100644
--- a/src/window-commands.c
+++ b/src/window-commands.c
@@ -2842,3 +2842,18 @@ window_cmd_tabs_unpin (GSimpleAction *action,
 
   ephy_notebook_tab_set_pinned (notebook, GTK_WIDGET (embed), FALSE);
 }
+
+void
+window_cmd_set_spell_checker (GSimpleAction *action,
+                              GVariant      *parameter,
+                              gpointer       user_data)
+{
+  WebKitWebContext *context = webkit_web_context_get_default ();
+  g_autoptr(GPtrArray) languages = g_ptr_array_new ();
+  const gchar *lang = g_variant_get_string (parameter, NULL);
+
+  g_ptr_array_add (languages, (gchar *)lang);
+
+  webkit_web_context_set_spell_checking_languages (context, (const char * const *) languages->pdata);
+  g_settings_set_string (EPHY_SETTINGS_WEB, EPHY_PREFS_WEB_SPELL_CHECKER_LANGUAGE, lang);
+}
diff --git a/src/window-commands.h b/src/window-commands.h
index 7cc0f230b..66c49c88f 100644
--- a/src/window-commands.h
+++ b/src/window-commands.h
@@ -233,5 +233,8 @@ void window_cmd_tabs_pin                        (GSimpleAction *action,
 void window_cmd_tabs_unpin                      (GSimpleAction *action,
                                                  GVariant      *parameter,
                                                  gpointer       user_data);
+void window_cmd_set_spell_checker               (GSimpleAction *action,
+                                                 GVariant      *parameter,
+                                                 gpointer       user_data);
 
 G_END_DECLS


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]