[gnome-characters/wip/dueno/local-scripts] categoryList: Deduce languages from input-sources
- From: Daiki Ueno <dueno src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-characters/wip/dueno/local-scripts] categoryList: Deduce languages from input-sources
- Date: Tue, 16 Jun 2015 09:15:27 +0000 (UTC)
commit 235720c9d3d06fa8732da19bb41d90224da1a4a0
Author: Daiki Ueno <dueno src gnome org>
Date: Tue Jun 16 17:56:55 2015 +0900
categoryList: Deduce languages from input-sources
It first reads the input-source settings and deduce the language list.
Then, for each language, deduce the script list from translations.
This requires a couple of API additions to gnome-desktop:
- gnome_xkb_info_get_languages_for_layout, which gets language codes
associated with an XKB layout
- gnome_normalize_language_code, which canonicalizes a 3-letter
language code to a 2-letter code, so we can build a valid locale
name
https://bugzilla.gnome.org/show_bug.cgi?id=743643
data/org.gnome.Characters.gschema.xml | 8 ++--
lib/gc.c | 90 +++++++++++++++++++++++++++++++
lib/gc.h | 6 ++
src/categoryList.js | 95 ++++++++++++++++++++++++++-------
src/characterList.js | 5 ++
src/window.js | 18 +++---
6 files changed, 190 insertions(+), 32 deletions(-)
---
diff --git a/data/org.gnome.Characters.gschema.xml b/data/org.gnome.Characters.gschema.xml
index 09ae962..8053862 100644
--- a/data/org.gnome.Characters.gschema.xml
+++ b/data/org.gnome.Characters.gschema.xml
@@ -14,16 +14,16 @@
<default>100</default>
<summary>Maximum recent characters</summary>
</key>
- <key name="scripts" type="as">
+ <key name="local-scripts" type="as">
<!-- TRANSLATORS: list Unicode scripts used in your language.
For Latin languages, keep it empty. -->
- <default l10n="messages" context="scripts">[]</default>
+ <default l10n="messages" context="local-scripts">[]</default>
<summary>A list of Unicode scripts used in this locale.</summary>
</key>
- <key name="scripts-character" type="s">
+ <key name="local-scripts-character" type="s">
<!-- TRANSLATORS: put the most representative character in your language.
This will be used as a label of the 'Local scripts' tab. -->
- <default l10n="messages" context="scripts-character">'?'</default>
+ <default l10n="messages" context="local-scripts-character">'?'</default>
<summary>Character representing Unicode scripts used in this locale.</summary>
</key>
</schema>
diff --git a/lib/gc.c b/lib/gc.c
index a1efec5..8ea432a 100644
--- a/lib/gc.c
+++ b/lib/gc.c
@@ -2,6 +2,8 @@
#include "gc.h"
+#include <langinfo.h>
+#include <locale.h>
#include <stdlib.h>
#include <string.h>
#include <unicase.h>
@@ -917,3 +919,91 @@ gc_pango_context_font_has_glyph (PangoContext *context,
return retval == 0;
}
+
+/**
+ * gc_get_current_language:
+ *
+ * Returns: (transfer full): an ISO639 two-letter language code
+ */
+gchar *
+gc_get_current_language (void)
+{
+ const gchar *locale = setlocale (LC_MESSAGES, NULL);
+ size_t length;
+
+ if (!locale || !*locale)
+ return NULL;
+
+ length = strcspn (locale, "_.@");
+
+ return g_strndup (locale, length);
+}
+
+/**
+ * gc_get_scripts_for_locale:
+ * @locale: a locale name
+ *
+ * Returns: (transfer full) (element-type utf8): a list of script names.
+ */
+GList *
+gc_get_scripts_for_locale (const gchar *locale)
+{
+ gchar *old_locale;
+ GSettings *settings;
+ GVariant *value;
+ GList *result = NULL;
+
+ old_locale = g_strdup (setlocale (LC_MESSAGES, locale));
+ if (!old_locale)
+ return NULL;
+
+ settings = g_settings_new ("org.gnome.Characters");
+ value = g_settings_get_default_value (settings, "local-scripts");
+ if (value)
+ {
+ GVariantIter iter;
+ gchar *script;
+
+ g_variant_iter_init (&iter, value);
+ while (g_variant_iter_next (&iter, "s", &script))
+ result = g_list_append (result, script);
+ g_variant_unref (value);
+ }
+
+ setlocale (LC_MESSAGES, old_locale);
+ g_free (old_locale);
+
+ return result;
+}
+
+/**
+ * gc_get_character_for_locale:
+ * @locale: a locale name
+ *
+ * Returns: (nullable) (transfer full): a string
+ */
+gchar *
+gc_get_character_for_locale (const gchar *locale)
+{
+ gchar *old_locale;
+ GSettings *settings;
+ GVariant *value;
+ gchar *result = NULL;
+
+ old_locale = g_strdup (setlocale (LC_MESSAGES, locale));
+ if (!old_locale)
+ return g_strdup ("?");
+
+ settings = g_settings_new ("org.gnome.Characters");
+ value = g_settings_get_default_value (settings, "local-scripts-character");
+ setlocale (LC_MESSAGES, old_locale);
+ g_free (old_locale);
+
+ if (value)
+ {
+ result = g_variant_dup_string (value, NULL);
+ g_variant_unref (value);
+ }
+
+ return result;
+}
diff --git a/lib/gc.h b/lib/gc.h
index 6383cdd..53c4baa 100644
--- a/lib/gc.h
+++ b/lib/gc.h
@@ -78,6 +78,12 @@ gboolean gc_pango_context_font_has_glyph
PangoFont *font,
gunichar uc);
+gchar *gc_get_current_language (void);
+GList *gc_get_scripts_for_locale
+ (const gchar *locale);
+gchar *gc_get_character_for_locale
+ (const gchar *locale);
+
G_END_DECLS
#endif /* __GC_H__ */
diff --git a/src/categoryList.js b/src/categoryList.js
index c1f90cc..d87e506 100644
--- a/src/categoryList.js
+++ b/src/categoryList.js
@@ -21,14 +21,16 @@ const Params = imports.params;
const Cairo = imports.cairo;
const PangoCairo = imports.gi.PangoCairo;
const Pango = imports.gi.Pango;
+const GnomeDesktop = imports.gi.GnomeDesktop;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;
const Gettext = imports.gettext;
const Gc = imports.gi.Gc;
const Main = imports.main;
+const Util = imports.util;
-const Category = [
+const BaseCategoryList = [
{
name: 'recent',
category: Gc.Category.NONE,
@@ -82,11 +84,6 @@ const Category = [
category: Gc.Category.EMOTICON,
title: N_('Emoticons'),
icon_name: 'face-smile-symbolic'
- },
- {
- name: 'local',
- category: Gc.Category.NONE,
- title: N_('Local scripts')
}
];
@@ -107,8 +104,8 @@ const CategoryListRowWidget = new Lang.Class({
this.add(hbox);
let image;
- if (category.name == 'local') {
- image = this._createScriptsImage();
+ if ('scripts' in category) {
+ image = this._createCharacterImage(category.character);
} else {
let icon = new Gio.ThemedIcon({ name: category.icon_name });
image = Gtk.Image.new_from_gicon(icon, Gtk.IconSize.LARGE_TOOLBAR);
@@ -122,7 +119,7 @@ const CategoryListRowWidget = new Lang.Class({
hbox.pack_start(label, true, true, 0);
},
- _createScriptsImage: function() {
+ _createCharacterImage: function(uc) {
let surface = new Cairo.ImageSurface(Cairo.Format.ARGB32, 24, 24);
let cr = new CairoContext(surface);
let layout = PangoCairo.create_layout(cr);
@@ -133,15 +130,79 @@ const CategoryListRowWidget = new Lang.Class({
fontDescription.set_size(16 * Pango.SCALE);
layout.set_font_description(fontDescription);
- let [uc, length] =
- Main.settings.get_value('scripts-character').get_string();
- layout.set_text(uc, length);
+ layout.set_text(uc, -1);
PangoCairo.show_layout(cr, layout);
return Gtk.Image.new_from_surface(surface);
}
});
+let _categoryList = null;
+
+function getCategoryList() {
+ if (_categoryList == null) {
+ _categoryList = BaseCategoryList.slice();
+
+ // Deduce language list from input-source settings.
+ let allLanguages = {};
+ let settings = Util.getSettings('org.gnome.desktop.input-sources',
+ '/org/gnome/desktop/input-sources/');
+ let xkbInfo = new GnomeDesktop.XkbInfo();
+ if (settings && xkbInfo.get_languages_for_layout) {
+ let sources = settings.get_value('sources').deep_unpack();
+ for (let i in sources) {
+ let [type, id] = sources[i];
+ if (type != 'xkb')
+ continue;
+
+ let languages = xkbInfo.get_languages_for_layout(id);
+ for (let j in languages) {
+ let language_code =
+ GnomeDesktop.normalize_language_code(languages[j]);
+ if (!(languages in allLanguages)) {
+ allLanguages[language_code] =
+ GnomeDesktop.get_language_from_code(language_code,
+ null);
+ }
+ }
+ }
+ }
+
+ // Add current locale language to allLangs.
+ let language_code = Gc.get_current_language();
+ if (!(language_code in allLanguages)) {
+ allLanguages[language_code] =
+ GnomeDesktop.get_language_from_code(language_code, null);
+ }
+
+ let allLocales = GnomeDesktop.get_all_locales();
+ // Loop over allLangs and deduce Unicode scripts used in each language.
+ for (let language_code in allLanguages) {
+ let locales = allLocales.filter(function (value) {
+ return value == language_code ||
+ value.startsWith(language_code + '_');
+ });
+ for (let index in locales) {
+ let locale = locales[index];
+ let scripts = Gc.get_scripts_for_locale(locale);
+ let character = Gc.get_character_for_locale(locale);
+ if (scripts.length > 0) {
+ let category = {
+ name: language_code,
+ category: Gc.Category.NONE,
+ title: allLanguages[language_code],
+ scripts: scripts,
+ character: character
+ }
+ _categoryList.push(category);
+ break;
+ }
+ }
+ }
+ }
+ return _categoryList;
+}
+
const CategoryListWidget = new Lang.Class({
Name: 'CategoryListWidget',
Extends: Gtk.ListBox,
@@ -153,13 +214,9 @@ const CategoryListWidget = new Lang.Class({
// Mimic GtkStackSidebar to take advantage of the standard theme.
this.get_style_context().add_class('sidebar');
- let scripts = Main.settings.get_value('scripts').get_strv();
- let scripts_visible = scripts.length > 0;
-
- for (let index in Category) {
- let category = Category[index];
- if (category.name == 'local' && !scripts_visible)
- continue;
+ let categories = getCategoryList();
+ for (let index in categories) {
+ let category = categories[index];
let rowWidget = new CategoryListRowWidget({}, category);
// Mimic GtkStackSidebar to take advantage of the standard theme.
rowWidget.get_style_context().add_class('sidebar-item');
diff --git a/src/characterList.js b/src/characterList.js
index 4d3ec08..2f79f43 100644
--- a/src/characterList.js
+++ b/src/characterList.js
@@ -344,6 +344,11 @@ const CharacterListView = new Lang.Class({
},
searchByCategory: function(category) {
+ if ('scripts' in category) {
+ this.searchByScripts(category.scripts);
+ return;
+ }
+
this._startSearch()
Gc.search_by_category(
category.category,
diff --git a/src/window.js b/src/window.js
index 59f39e4..aaaf681 100644
--- a/src/window.js
+++ b/src/window.js
@@ -199,8 +199,9 @@ const MainWindow = new Lang.Class({
// FIXME: we could use Gtk.Container.get_child to obtain the
// title, but it is not introspectable.
let category = null;
- for (let index in CategoryList.Category) {
- category = CategoryList.Category[index];
+ let categories = CategoryList.getCategoryList();
+ for (let index in categories) {
+ category = categories[index];
if (category.name == name)
break;
}
@@ -270,8 +271,9 @@ const MainView = new Lang.Class({
this._characterLists = {};
let characterList;
- for (let index in CategoryList.Category) {
- let category = CategoryList.Category[index];
+ let categories = CategoryList.getCategoryList();
+ for (let index in categories) {
+ let category = categories[index];
characterList = this._createCharacterList(
category.name, _('%s Character List').format(category.title));
// FIXME: Can't use GtkContainer.child_get_property.
@@ -330,13 +332,11 @@ const MainView = new Lang.Class({
characterList.setCharacters(this.recentCharacters);
characterList.updateCharacterList();
}
- } else if (name == 'local') {
- let scripts = Main.settings.get_value('scripts').get_strv();
- characterList.searchByScripts(scripts);
} else {
let category = null;
- for (let index in CategoryList.Category) {
- category = CategoryList.Category[index];
+ let categories = CategoryList.getCategoryList();
+ for (let index in categories) {
+ category = categories[index];
if (category.name == name)
break;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]