Multilanguage searching for GtkEmojiChooser

This commit is contained in:
Sudip Shil 2024-02-22 17:09:23 +00:00 committed by Matthias Clasen
parent 2a0286c19c
commit 985d964a34
27 changed files with 96 additions and 63 deletions

Binary file not shown.

View File

@ -22,13 +22,15 @@
* language-specific data.raw.json as input
*/
/* The format of the generated data is: a(ausasu).
/* The format of the generated data is: a(aussasasu).
* Each member of the array has the following fields:
* au - sequence of unicode codepoints. If the
* sequence contains a 0, it marks the point
* where skin tone modifiers should be inserted
* s - name, e.g. "man worker"
* as - keywords, e.g. "man", "worker"
* s - name in english, e.g. "man worker"
* s - name in locale
* as - keywords in english, e.g. "man", "worker"
* as - keywords in locale
* u - the group that this item belongs to:
* 0: smileys-emotion
* 1: people-body
@ -77,90 +79,113 @@ main (int argc, char *argv[])
{
JsonParser *parser;
JsonNode *root;
JsonParser *parser_en;
JsonNode *root_en;
JsonObject *ro;
JsonArray *array;
JsonArray *array_en;
JsonNode *node;
const char *unicode;
JsonObjectIter iter;
GError *error = NULL;
guint length, i;
guint length, length_en, i;
GVariantBuilder builder;
GVariant *v;
GString *s;
GHashTable *names;
GString *name_key;
if (argc != 3)
if (argc != 4) //0 -> compiled file, 1 -> en/data.raw.json, 2 -> de/data.raw.json, 3 -> de.data
{
g_print ("Usage: emoji-convert INPUT OUTPUT\n");
g_print ("Usage: emoji-convert INPUT1 INPUT2 OUTPUT\nINPUT1 should be raw json data for English\nINPUT2 should be raw json data for the locale\n");
return 1;
}
parser = json_parser_new ();
parser_en = json_parser_new ();
if (!json_parser_load_from_file (parser, argv[1], &error))
if (!json_parser_load_from_file (parser_en, argv[1], &error))
{
g_error ("%s", error->message);
return 1;
}
if (!json_parser_load_from_file (parser, argv[2], &error))
{
g_error ("%s", error->message);
return 1;
}
root = json_parser_get_root (parser);
array = json_node_get_array (root);
length = json_array_get_length (array);
root_en = json_parser_get_root (parser_en);
array_en = json_node_get_array (root_en);
length_en = json_array_get_length (array_en);
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ausasu)"));
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(aussasasu)"));
for (i = 0; i < length; i++)
{
JsonObject *obj = json_array_get_object_element (array, i);
GVariantBuilder b1;
GVariantBuilder b2;
guint group;
const char *name;
char *code;
{
JsonObject *obj = json_array_get_object_element (array, i);
JsonObject *obj_en = json_array_get_object_element (array_en, i);
GVariantBuilder b1;
GVariantBuilder b2;
GVariantBuilder b3;
guint group;
const char *name;
const char *name_en;
char *code;
if (!json_object_has_member (obj, "group"))
continue;
if (!json_object_has_member (obj_en, "group"))
continue;
group = json_object_get_int_member (obj, "group");
name = json_object_get_string_member (obj, "label");
name_en = json_object_get_string_member (obj_en, "label");
if (json_object_has_member (obj, "skins") && json_object_has_member (obj_en, "skins"))
{
JsonArray *a2 = json_object_get_array_member (obj, "skins");
JsonNode *n2 = json_array_get_element (a2, 0);
JsonObject *o2 = json_node_get_object (n2);
code = g_strdup (json_object_get_string_member (o2, "hexcode"));
}
else
{
code = g_strdup (json_object_get_string_member (obj, "hexcode"));
}
g_variant_builder_init (&b1, G_VARIANT_TYPE ("au"));
if (!json_object_has_member (obj, "group"))
continue;
if (!parse_code (&b1, code))
return 1;
group = json_object_get_int_member (obj, "group");
name = json_object_get_string_member (obj, "label");
if (json_object_has_member (obj, "skins"))
g_variant_builder_init (&b2, G_VARIANT_TYPE ("as"));
if (json_object_has_member (obj_en, "tags"))
{
JsonArray *tags_en = json_object_get_array_member (obj_en, "tags");
for (int j = 0; j < json_array_get_length (tags_en); j++)
{
JsonArray *a2 = json_object_get_array_member (obj, "skins");
JsonNode *n2 = json_array_get_element (a2, 0);
JsonObject *o2 = json_node_get_object (n2);
code = g_strdup (json_object_get_string_member (o2, "hexcode"));
g_variant_builder_add (&b2, "s", json_array_get_string_element (tags_en, j));
}
else
}
g_variant_builder_init (&b3, G_VARIANT_TYPE ("as"));
if (json_object_has_member (obj, "tags"))
{
JsonArray *tags = json_object_get_array_member (obj, "tags");
for (int j = 0; j < json_array_get_length (tags); j++)
{
code = g_strdup (json_object_get_string_member (obj, "hexcode"));
g_variant_builder_add (&b3, "s", json_array_get_string_element (tags, j));
}
g_variant_builder_init (&b1, G_VARIANT_TYPE ("au"));
if (!parse_code (&b1, code))
return 1;
g_variant_builder_init (&b2, G_VARIANT_TYPE ("as"));
if (json_object_has_member (obj, "tags"))
{
JsonArray *tags = json_object_get_array_member (obj, "tags");
for (int j = 0; j < json_array_get_length (tags); j++)
g_variant_builder_add (&b2, "s", json_array_get_string_element (tags, j));
}
g_variant_builder_add (&builder, "(ausasu)", &b1, name, &b2, group);
}
}
g_variant_builder_add (&builder, "(aussasasu)", &b1, name_en, name, &b2, &b3, group);
}
v = g_variant_builder_end (&builder);
if (g_str_has_suffix (argv[2], ".json"))
if (g_str_has_suffix (argv[3], ".json"))
{
JsonNode *node;
char *out;
node = json_gvariant_serialize (v);
out = json_to_string (node, TRUE);
if (!g_file_set_contents (argv[2], out, -1, &error))
if (!g_file_set_contents (argv[3], out, -1, &error))
{
g_error ("%s", error->message);
return 1;
@ -171,7 +196,7 @@ main (int argc, char *argv[])
GBytes *bytes;
bytes = g_variant_get_data_as_bytes (v);
if (!g_file_set_contents (argv[2], g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes), &error))
if (!g_file_set_contents (argv[3], g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes), &error))
{
g_error ("%s", error->message);
return 1;

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -321,7 +321,7 @@ populate_recent_section (GtkEmojiChooser *chooser)
GVariantIter iter;
gboolean empty = TRUE;
variant = g_settings_get_value (chooser->settings, "recent-emoji");
variant = g_settings_get_value (chooser->settings, "recently-used-emoji");
g_variant_iter_init (&iter, variant);
while ((item = g_variant_iter_next_value (&iter)))
{
@ -354,8 +354,8 @@ add_recent_item (GtkEmojiChooser *chooser,
g_variant_ref (item);
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a((ausasu)u)"));
g_variant_builder_add (&builder, "(@(ausasu)u)", item, modifier);
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a((aussasasu)u)"));
g_variant_builder_add (&builder, "(@(aussasasu)u)", item, modifier);
children = NULL;
for (child = gtk_widget_get_last_child (chooser->recent.box);
@ -380,7 +380,7 @@ add_recent_item (GtkEmojiChooser *chooser,
continue;
}
g_variant_builder_add (&builder, "(@(ausasu)u)", item2, modifier2);
g_variant_builder_add (&builder, "(@(aussasasu)u)", item2, modifier2);
}
g_list_free (children);
@ -390,7 +390,7 @@ add_recent_item (GtkEmojiChooser *chooser,
gtk_widget_set_visible (chooser->recent.box, TRUE);
gtk_widget_set_sensitive (chooser->recent.button, TRUE);
g_settings_set_value (chooser->settings, "recent-emoji", g_variant_builder_end (&builder));
g_settings_set_value (chooser->settings, "recently-used-emoji", g_variant_builder_end (&builder));
g_variant_unref (item);
}
@ -720,7 +720,7 @@ populate_emoji_chooser (gpointer data)
bytes = get_emoji_data ();
chooser->data = g_variant_ref_sink (g_variant_new_from_bytes (G_VARIANT_TYPE ("a(ausasu)"), bytes, TRUE));
chooser->data = g_variant_ref_sink (g_variant_new_from_bytes (G_VARIANT_TYPE ("a(aussasasu)"), bytes, TRUE));
g_bytes_unref (bytes);
}
@ -734,7 +734,7 @@ populate_emoji_chooser (gpointer data)
{
guint group;
g_variant_get_child (item, 3, "u", &group);
g_variant_get_child (item, 5, "u", &group);
if (group == chooser->people.group)
chooser->box = chooser->people.box;
@ -866,9 +866,12 @@ filter_func (GtkFlowBoxChild *child,
GtkEmojiChooser *chooser;
GVariant *emoji_data;
const char *text;
const char *name_en;
const char *name;
const char **keywords_en;
const char **keywords;
char **term_tokens;
char **name_tokens_en;
char **name_tokens;
gboolean res;
@ -885,16 +888,21 @@ filter_func (GtkFlowBoxChild *child,
goto out;
term_tokens = g_str_tokenize_and_fold (text, "en", NULL);
g_variant_get_child (emoji_data, 1, "&s", &name);
name_tokens = g_str_tokenize_and_fold (name, "en", NULL);
g_variant_get_child (emoji_data, 2, "^a&s", &keywords);
g_variant_get_child (emoji_data, 1, "&s", &name_en);
name_tokens = g_str_tokenize_and_fold (name_en, "en", NULL);
g_variant_get_child (emoji_data, 2, "&s", &name);
name_tokens_en = g_str_tokenize_and_fold (name, "en", NULL);
g_variant_get_child (emoji_data, 3, "^a&s", &keywords_en);
g_variant_get_child (emoji_data, 4, "^a&s", &keywords);
res = match_tokens ((const char **)term_tokens, (const char **)name_tokens) ||
match_tokens ((const char **)term_tokens, keywords);
match_tokens ((const char **)term_tokens, (const char **)name_tokens_en) ||
match_tokens ((const char **)term_tokens, keywords) ||
match_tokens ((const char **)term_tokens, keywords_en);
g_strfreev (term_tokens);
g_strfreev (name_tokens);
g_strfreev (name_tokens_en);
out:
if (res)

View File

@ -2,7 +2,7 @@
<schemalist>
<schema id='org.gtk.gtk4.Settings.EmojiChooser' path='/org/gtk/gtk4/settings/emoji-chooser/'>
<key name='recent-emoji' type='a((ausasu)u)'>
<key name='recently-used-emoji' type='a((aussasasu)u)'>
<default>[]</default>
<summary>Recently used Emoji</summary>
<description>