[gnome-characters] categoryList: Support non-Latin scripts
- From: Daiki Ueno <dueno src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-characters] categoryList: Support non-Latin scripts
- Date: Thu, 2 Jul 2015 07:15:41 +0000 (UTC)
commit 5e086c9ed36a5d23bbeb4390422b0eeab4634f00
Author: Daiki Ueno <dueno src gnome org>
Date: Wed Jul 1 10:57:01 2015 +0900
categoryList: Support non-Latin scripts
This patch renames the "Latin" page to "Letters" and add user's
local characters into that page. The local characters are deduced from
input-source settings.
https://bugzilla.gnome.org/show_bug.cgi?id=743643
src/categoryList.js | 154 ++++++++++++++++++++++++++++++++++++++++++++++++--
src/characterList.js | 21 +++++++
src/window.js | 37 ++++---------
3 files changed, 181 insertions(+), 31 deletions(-)
---
diff --git a/src/categoryList.js b/src/categoryList.js
index 82beff7..3ed789e 100644
--- a/src/categoryList.js
+++ b/src/categoryList.js
@@ -18,13 +18,15 @@
const Lang = imports.lang;
const Params = imports.params;
+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 Util = imports.util;
-const Category = [
+const BaseCategoryList = [
{
name: 'recent',
category: Gc.Category.NONE,
@@ -68,9 +70,9 @@ const Category = [
icon_name: 'characters-math-symbolic'
},
{
- name: 'latin',
+ name: 'letters',
category: Gc.Category.LATIN,
- title: N_('Latin'),
+ title: N_('Letters'),
icon_name: 'characters-latin-symbolic'
},
{
@@ -120,8 +122,10 @@ const CategoryListWidget = new Lang.Class({
// Mimic GtkStackSidebar to take advantage of the standard theme.
this.get_style_context().add_class('sidebar');
- for (let index in Category) {
- let category = Category[index];
+ this._ensureCategoryList();
+
+ for (let index in this._categoryList) {
+ let category = this._categoryList[index];
let rowWidget = new CategoryListRowWidget({}, category);
// Mimic GtkStackSidebar to take advantage of the standard theme.
rowWidget.get_style_context().add_class('sidebar-item');
@@ -136,4 +140,144 @@ const CategoryListWidget = new Lang.Class({
category.activate(new GLib.Variant('s', row.category.name));
}
},
+
+ _finishListEngines: function(sources, bus, res) {
+ try {
+ let engines = bus.list_engines_async_finish(res);
+ if (engines) {
+ for (let j in engines) {
+ let engine = engines[j];
+ let language = engine.get_language();
+ if (language != null)
+ this._ibusLanguageList[engine.get_name()] = language;
+ }
+ }
+ } catch (e) {
+ log("Failed to list engines: " + e);
+ }
+ this._finishBuiltScriptList(sources);
+ },
+
+ _ensureIBusLanguageList: function(sources) {
+ if (this._ibusLanguageList != null)
+ return;
+
+ this._ibusLanguageList = {};
+
+ // Don't assume IBus is always available.
+ let ibus;
+ try {
+ ibus = imports.gi.IBus;
+ } catch (e) {
+ this._finishBuiltScriptList(sources);
+ return;
+ }
+
+ ibus.init();
+ let bus = new ibus.Bus();
+ bus.list_engines_async(-1,
+ null,
+ Lang.bind(this, function (bus, res) {
+ this._finishListEngines(sources, bus, res);
+ }));
+ },
+
+ _finishBuiltScriptList: function(sources) {
+ let xkbInfo = new GnomeDesktop.XkbInfo();
+ let languages = [];
+ for (let i in sources) {
+ let [type, id] = sources[i];
+ switch (type) {
+ case 'xkb':
+ // FIXME: Remove this check once gnome-desktop gets the
+ // support for that.
+ if (xkbInfo.get_languages_for_layout) {
+ languages = languages.concat(
+ xkbInfo.get_languages_for_layout(id));
+ }
+ break;
+ case 'ibus':
+ if (id in this._ibusLanguageList)
+ languages.push(this._ibusLanguageList[id]);
+ break;
+ }
+ }
+
+ // Add current locale language to allLangs.
+ languages.push(Gc.get_current_language());
+
+ let allScripts = [];
+ for (let i in languages) {
+ let language = GnomeDesktop.normalize_locale(languages[i]);
+ if (language == null)
+ continue;
+ let scripts = Gc.get_scripts_for_language(languages[i]);
+ for (let j in scripts) {
+ let script = scripts[j];
+ // Latin is always added at top, and Han contains too
+ // many characters.
+ if (['Latin', 'Han'].indexOf(script) >= 0)
+ continue;
+ if (allScripts.indexOf(script) >= 0)
+ continue;
+ allScripts.push(script);
+ }
+ }
+
+ allScripts.unshift('Latin');
+ let category = this.getCategory('letters');
+ category.scripts = allScripts;
+ },
+
+ _buildScriptList: function() {
+ let settings =
+ Util.getSettings('org.gnome.desktop.input-sources',
+ '/org/gnome/desktop/input-sources/');
+ if (settings) {
+ let sources = settings.get_value('sources').deep_unpack();
+ let hasIBus = sources.some(function(current, index, array) {
+ return current[0] == 'ibus';
+ });
+ if (hasIBus)
+ this._ensureIBusLanguageList(sources);
+ else
+ this._finishBuiltScriptList(sources);
+ }
+ },
+
+ _ensureCategoryList: function() {
+ if (this._categoryList != null)
+ return;
+
+ this._categoryList = BaseCategoryList.slice();
+
+ // Populate the "scripts" element of the "Letter" category,
+ // based on the input-sources settings.
+ //
+ // This works asynchronously, in the following call flow:
+ //
+ // _buildScriptList()
+ // if an IBus input-source is configured:
+ // _ensureIBusLanguageList()
+ // ibus_bus_list_engines_async()
+ // _finishListEngines()
+ // _finishBuiltScriptList()
+ // else:
+ // _finishBuiltScriptList()
+ //
+ this._buildScriptList();
+ },
+
+ getCategoryList: function() {
+ return this._categoryList;
+ },
+
+ getCategory: function(name) {
+ for (let index in this._categoryList) {
+ let category = this._categoryList[index];
+ if (category.name == name)
+ return category;
+ }
+ return null;
+ }
});
diff --git a/src/characterList.js b/src/characterList.js
index 4dbdf59..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,
@@ -376,6 +381,22 @@ const CharacterListView = new Lang.Class({
}));
},
+ searchByScripts: function(scripts) {
+ this._startSearch()
+ Gc.search_by_scripts(
+ scripts,
+ -1,
+ this._cancellable,
+ Lang.bind(this, function(source_object, res, user_data) {
+ try {
+ let result = Gc.search_finish(res);
+ this._finishSearch(result);
+ } catch (e) {
+ log("Failed to search by scripts: " + e);
+ }
+ }));
+ },
+
cancelSearch: function() {
this._cancellable.cancel();
this._finishSearch([]);
diff --git a/src/window.js b/src/window.js
index 2ff8a73..4d4b8a9 100644
--- a/src/window.js
+++ b/src/window.js
@@ -104,7 +104,7 @@ const MainWindow = new Lang.Class({
scroll.add(this._categoryList);
this._sidebar_grid.add(scroll);
- this._mainView = new MainView();
+ this._mainView = new MainView({ categoryList: this._categoryList });
if (this._mainView.recentCharacters.length == 0) {
let row = this._categoryList.get_row_at_index(1);
@@ -196,17 +196,10 @@ const MainWindow = new Lang.Class({
let [name, length] = v.get_string()
- // 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];
- if (category.name == name)
- break;
- }
+ let category = this._categoryList.getCategory(name);
Util.assertNotEqual(category, null);
- this._mainView.setPage(category.name);
+ this._mainView.setPage(category);
this._updateTitle(category.title);
},
@@ -260,6 +253,7 @@ const MainView = new Lang.Class({
},
_init: function(params) {
+ let filtered = Params.filter(params, { categoryList: null });
params = Params.fill(params, {
hexpand: true, vexpand: true,
transition_type: Gtk.StackTransitionType.CROSSFADE
@@ -268,10 +262,12 @@ const MainView = new Lang.Class({
this._filterFontFamily = null;
this._characterLists = {};
+ this._categoryList = filtered.categoryList;
let characterList;
- for (let index in CategoryList.Category) {
- let category = CategoryList.Category[index];
+ let categories = this._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.
@@ -316,14 +312,11 @@ const MainView = new Lang.Class({
this.visible_child.cancelSearch();
},
- setPage: function(name) {
- if (!(name in this._characterLists))
- return;
-
- let characterList = this.get_child_by_name(name);
+ setPage: function(category) {
+ let characterList = this.get_child_by_name(category.name);
characterList.setFilterFont(this._filterFontFamily);
- if (name == 'recent') {
+ if (category.name == 'recent') {
if (this.recentCharacters.length == 0)
characterList.visible_child_name = 'empty-recent';
else {
@@ -331,14 +324,6 @@ const MainView = new Lang.Class({
characterList.updateCharacterList();
}
} else {
- let category = null;
- for (let index in CategoryList.Category) {
- category = CategoryList.Category[index];
- if (category.name == name)
- break;
- }
-
- Util.assertNotEqual(category, null);
characterList.searchByCategory(category);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]