[gnome-builder/wip/gtk4-port: 1654/1774] plugins/spellcheck: import changes from Text Editor
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/gtk4-port: 1654/1774] plugins/spellcheck: import changes from Text Editor
- Date: Mon, 11 Jul 2022 22:31:53 +0000 (UTC)
commit 0f4c8b1ed122d198ce0c258519fe7a60508c02be
Author: Christian Hergert <chergert redhat com>
Date: Fri Jun 24 14:38:26 2022 -0700
plugins/spellcheck: import changes from Text Editor
.../spellcheck/editor-enchant-spell-provider.c | 60 ++++++++++++----
.../spellcheck/editor-spell-language-info.c | 30 +++++++-
.../spellcheck/editor-spell-language-info.h | 10 +--
src/plugins/spellcheck/editor-spell-menu.c | 80 +++++++++++++++++++---
4 files changed, 150 insertions(+), 30 deletions(-)
---
diff --git a/src/plugins/spellcheck/editor-enchant-spell-provider.c
b/src/plugins/spellcheck/editor-enchant-spell-provider.c
index fb722c57b..1949013ce 100644
--- a/src/plugins/spellcheck/editor-enchant-spell-provider.c
+++ b/src/plugins/spellcheck/editor-enchant-spell-provider.c
@@ -50,6 +50,31 @@ get_broker (void)
return broker;
}
+static char *
+_icu_uchar_to_char (const UChar *input,
+ gsize max_input_len)
+{
+ GString *str;
+
+ g_assert (input != NULL);
+ g_assert (max_input_len > 0);
+
+ if (input[0] == 0)
+ return NULL;
+
+ str = g_string_new (NULL);
+
+ for (gsize i = 0; i < max_input_len; i++)
+ {
+ if (input[i] == 0)
+ break;
+
+ g_string_append_unichar (str, input[i]);
+ }
+
+ return g_string_free (str, FALSE);
+}
+
static char *
get_display_name (const char *code)
{
@@ -59,20 +84,26 @@ get_display_name (const char *code)
{
UChar ret[256];
UErrorCode status = U_ZERO_ERROR;
-
- ret[0] = 0;
uloc_getDisplayName (code, names[i], ret, G_N_ELEMENTS (ret), &status);
- ret[G_N_ELEMENTS (ret)-1] = 0;
+ if (status == U_ZERO_ERROR)
+ return _icu_uchar_to_char (ret, G_N_ELEMENTS (ret));
+ }
- if (status == U_ZERO_ERROR && ret[0] != 0)
- {
- GString *str = g_string_new (NULL);
+ return NULL;
+}
- for (guint j = 0; ret[j]; j++)
- g_string_append_unichar (str, ret[j]);
+static char *
+get_display_language (const char *code)
+{
+ const char * const *names = g_get_language_names ();
- return g_string_free (str, FALSE);
- }
+ for (guint i = 0; names[i]; i++)
+ {
+ UChar ret[256];
+ UErrorCode status = U_ZERO_ERROR;
+ uloc_getDisplayLanguage (code, names[i], ret, G_N_ELEMENTS (ret), &status);
+ if (status == U_ZERO_ERROR)
+ return _icu_uchar_to_char (ret, G_N_ELEMENTS (ret));
}
return NULL;
@@ -112,12 +143,13 @@ list_languages_cb (const char * const lang_tag,
{
GPtrArray *ar = user_data;
char *name = get_display_name (lang_tag);
+ char *group = get_display_language (lang_tag);
if (name != NULL)
- {
- g_ptr_array_add (ar, editor_spell_language_info_new (name, lang_tag));
- g_free (name);
- }
+ g_ptr_array_add (ar, editor_spell_language_info_new (name, lang_tag, group));
+
+ g_free (name);
+ g_free (group);
}
static GPtrArray *
diff --git a/src/plugins/spellcheck/editor-spell-language-info.c
b/src/plugins/spellcheck/editor-spell-language-info.c
index 8bc4ceb21..7d4095c6d 100644
--- a/src/plugins/spellcheck/editor-spell-language-info.c
+++ b/src/plugins/spellcheck/editor-spell-language-info.c
@@ -27,6 +27,7 @@ struct _EditorSpellLanguageInfo
GObject parent_instance;
char *name;
char *code;
+ char *group;
};
G_DEFINE_TYPE (EditorSpellLanguageInfo, editor_spell_language_info, G_TYPE_OBJECT)
@@ -34,6 +35,7 @@ G_DEFINE_TYPE (EditorSpellLanguageInfo, editor_spell_language_info, G_TYPE_OBJEC
enum {
PROP_0,
PROP_CODE,
+ PROP_GROUP,
PROP_NAME,
N_PROPS
};
@@ -49,11 +51,13 @@ static GParamSpec *properties [N_PROPS];
*/
EditorSpellLanguageInfo *
editor_spell_language_info_new (const char *name,
- const char *code)
+ const char *code,
+ const char *group)
{
return g_object_new (EDITOR_TYPE_SPELL_LANGUAGE_INFO,
"name", name,
"code", code,
+ "group", group,
NULL);
}
@@ -64,6 +68,7 @@ editor_spell_language_info_finalize (GObject *object)
g_clear_pointer (&self->name, g_free);
g_clear_pointer (&self->code, g_free);
+ g_clear_pointer (&self->group, g_free);
G_OBJECT_CLASS (editor_spell_language_info_parent_class)->finalize (object);
}
@@ -86,6 +91,10 @@ editor_spell_language_info_get_property (GObject *object,
g_value_set_string (value, editor_spell_language_info_get_code (self));
break;
+ case PROP_GROUP:
+ g_value_set_string (value, editor_spell_language_info_get_group (self));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -109,6 +118,10 @@ editor_spell_language_info_set_property (GObject *object,
self->code = g_value_dup_string (value);
break;
+ case PROP_GROUP:
+ self->group = g_value_dup_string (value);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -137,6 +150,13 @@ editor_spell_language_info_class_init (EditorSpellLanguageInfoClass *klass)
NULL,
(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ properties [PROP_GROUP] =
+ g_param_spec_string ("group",
+ "Group",
+ "A group for sorting, usually the country name",
+ NULL,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
g_object_class_install_properties (object_class, N_PROPS, properties);
}
@@ -160,3 +180,11 @@ editor_spell_language_info_get_code (EditorSpellLanguageInfo *self)
return self->code;
}
+
+const char *
+editor_spell_language_info_get_group (EditorSpellLanguageInfo *self)
+{
+ g_return_val_if_fail (EDITOR_IS_SPELL_LANGUAGE_INFO (self), NULL);
+
+ return self->group;
+}
diff --git a/src/plugins/spellcheck/editor-spell-language-info.h
b/src/plugins/spellcheck/editor-spell-language-info.h
index a84426168..ede69b8cd 100644
--- a/src/plugins/spellcheck/editor-spell-language-info.h
+++ b/src/plugins/spellcheck/editor-spell-language-info.h
@@ -28,9 +28,11 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (EditorSpellLanguageInfo, editor_spell_language_info, EDITOR, SPELL_LANGUAGE_INFO,
GObject)
-EditorSpellLanguageInfo *editor_spell_language_info_new (const char *name,
- const char *code);
-const char *editor_spell_language_info_get_name (EditorSpellLanguageInfo *self);
-const char *editor_spell_language_info_get_code (EditorSpellLanguageInfo *self);
+EditorSpellLanguageInfo *editor_spell_language_info_new (const char *name,
+ const char *code,
+ const char *group);
+const char *editor_spell_language_info_get_group (EditorSpellLanguageInfo *self);
+const char *editor_spell_language_info_get_name (EditorSpellLanguageInfo *self);
+const char *editor_spell_language_info_get_code (EditorSpellLanguageInfo *self);
G_END_DECLS
diff --git a/src/plugins/spellcheck/editor-spell-menu.c b/src/plugins/spellcheck/editor-spell-menu.c
index 5baadc97a..c1ee5a5ad 100644
--- a/src/plugins/spellcheck/editor-spell-menu.c
+++ b/src/plugins/spellcheck/editor-spell-menu.c
@@ -161,38 +161,103 @@ editor_spell_corrections_new (void)
return g_object_new (EDITOR_TYPE_SPELL_CORRECTIONS, NULL);
}
+static int
+count_groups (GPtrArray *infos)
+{
+ g_autoptr(GHashTable) groups = g_hash_table_new (g_str_hash, g_str_equal);
+
+ g_assert (infos != NULL);
+
+ for (guint i = 0; i < infos->len; i++)
+ {
+ EditorSpellLanguageInfo *info = g_ptr_array_index (infos, i);
+ const char *group = editor_spell_language_info_get_group (info);
+
+ if (group != NULL && group[0] != 0 && !g_hash_table_contains (groups, group))
+ g_hash_table_insert (groups, (char *)group, NULL);
+ }
+
+ return g_hash_table_size (groups);
+}
+
static void
populate_languages (GMenu *menu)
{
EditorSpellProvider *provider = editor_spell_provider_get_default ();
g_autoptr(GPtrArray) infos = editor_spell_provider_list_languages (provider);
+ g_autoptr(GHashTable) groups = NULL;
if (infos == NULL)
return;
+ groups = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+
+ /* First setup our groups. We do that up front so we can avoid
+ * checking below, but also so we can hoist a single group up
+ * into the parent menu if necessary.
+ */
+ if (count_groups (infos) > 1)
+ {
+ for (guint i = 0; i < infos->len; i++)
+ {
+ EditorSpellLanguageInfo *info = g_ptr_array_index (infos, i);
+ const char *group = editor_spell_language_info_get_group (info);
+ GMenu *group_menu;
+
+ if (group == NULL || group[0] == 0)
+ continue;
+
+ if (!g_hash_table_contains (groups, group))
+ {
+ group_menu = g_menu_new ();
+ g_menu_append_submenu (menu, group, G_MENU_MODEL (group_menu));
+ g_hash_table_insert (groups,
+ g_strdup (group),
+ g_steal_pointer (&group_menu));
+ }
+ }
+ }
+
for (guint i = 0; i < infos->len; i++)
{
EditorSpellLanguageInfo *info = g_ptr_array_index (infos, i);
const char *name = editor_spell_language_info_get_name (info);
+ const char *group = editor_spell_language_info_get_group (info);
const char *code = editor_spell_language_info_get_code (info);
- g_autoptr(GMenuItem) item = g_menu_item_new (name, NULL);
+ g_autoptr(GMenuItem) item = NULL;
+ GMenu *group_menu;
+
+ if (group == NULL || !(group_menu = g_hash_table_lookup (groups, group)))
+ group_menu = menu;
+ g_assert (G_IS_MENU (group_menu));
+
+ item = g_menu_item_new (name, NULL);
g_menu_item_set_action_and_target (item, "spelling.language", "s", code);
- g_menu_append_item (menu, item);
+ g_menu_append_item (group_menu, item);
}
}
GMenuModel *
editor_spell_menu_new (void)
{
+ static GMenu *languages_menu;
+ static GMenuItem *languages_item;
g_autoptr(GMenu) menu = g_menu_new ();
g_autoptr(GMenuModel) corrections_menu = editor_spell_corrections_new ();
- g_autoptr(GMenu) languages_menu = g_menu_new ();
- g_autoptr(GMenuItem) languages_item = g_menu_item_new_submenu (_("Languages"), G_MENU_MODEL
(languages_menu));
g_autoptr(GMenuItem) add_item = g_menu_item_new (_("Add to Dictionary"), "spelling.add");
g_autoptr(GMenuItem) ignore_item = g_menu_item_new (_("Ignore"), "spelling.ignore");
g_autoptr(GMenuItem) check_item = g_menu_item_new (_("Check Spelling"), "spelling.enabled");
+ if (languages_menu == NULL)
+ {
+ languages_menu = g_menu_new ();
+ populate_languages (languages_menu);
+ }
+
+ if (languages_item == NULL)
+ languages_item = g_menu_item_new_submenu (_("Languages"), G_MENU_MODEL (languages_menu));
+
g_menu_item_set_attribute (add_item, "hidden-when", "s", "action-disabled");
g_menu_item_set_attribute (ignore_item, "hidden-when", "s", "action-disabled");
g_menu_item_set_attribute (check_item, "role", "s", "check");
@@ -204,13 +269,6 @@ editor_spell_menu_new (void)
g_menu_append_item (menu, check_item);
g_menu_append_item (menu, languages_item);
- populate_languages (languages_menu);
-
- g_object_set_data_full (G_OBJECT (menu),
- "LANGUAGES_MENU",
- g_object_ref (languages_menu),
- g_object_unref);
-
g_object_set_data_full (G_OBJECT (menu),
"CORRECTIONS_MENU",
g_object_ref (corrections_menu),
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]