summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfujiwarat <takao.fujiwara1@gmail.com>2014-01-30 17:33:33 +0900
committerfujiwarat <takao.fujiwara1@gmail.com>2014-01-30 17:33:33 +0900
commit2e8e2bef7a7943ed351278c2f6c601339abd4d54 (patch)
tree702155a2687952da2b18d029e5154ea829643877
parent85330465240ba6a028c92290d74ef05dcb5d7cb9 (diff)
downloadibus-anthy-2e8e2bef7a7943ed351278c2f6c601339abd4d54.tar.gz
Added python3.
The default is to use 'python' and --with-python option can change it. ./configure --with-python=python3
-rw-r--r--configure.ac107
-rw-r--r--engine/Makefile.am130
-rw-r--r--engine/python2/Makefile.am144
-rw-r--r--engine/python2/_config.py.in (renamed from engine/_config.py.in)0
-rw-r--r--engine/python2/anthy.i (renamed from engine/anthy.i)0
-rw-r--r--engine/python2/anthy.xml.in.in (renamed from engine/anthy.xml.in.in)0
-rw-r--r--engine/python2/default.xml.in.in (renamed from engine/default.xml.in.in)0
-rw-r--r--engine/python2/engine.py (renamed from engine/engine.py)4
-rw-r--r--engine/python2/factory.py (renamed from engine/factory.py)0
-rw-r--r--engine/python2/ibus-engine-anthy.in (renamed from engine/ibus-engine-anthy.in)0
-rw-r--r--engine/python2/jastring.py (renamed from engine/jastring.py)0
-rw-r--r--engine/python2/kana.py (renamed from engine/kana.py)0
-rw-r--r--engine/python2/main.py (renamed from engine/main.py)0
-rw-r--r--engine/python2/romaji.py (renamed from engine/romaji.py)0
-rw-r--r--engine/python2/segment.py (renamed from engine/segment.py)0
-rw-r--r--engine/python2/tables.py (renamed from engine/tables.py)0
-rw-r--r--engine/python2/test.py (renamed from engine/test.py)0
-rw-r--r--engine/python2/thumb.py (renamed from engine/thumb.py)0
-rw-r--r--engine/python3/Makefile.am144
-rw-r--r--engine/python3/_config.py.in30
-rw-r--r--engine/python3/anthy.i125
-rw-r--r--engine/python3/anthy.xml.in.in19
-rw-r--r--engine/python3/default.xml.in.in19
-rw-r--r--engine/python3/engine.py2780
-rw-r--r--engine/python3/factory.py80
-rw-r--r--engine/python3/ibus-engine-anthy.in33
-rw-r--r--engine/python3/jastring.py304
-rw-r--r--engine/python3/kana.py170
-rw-r--r--engine/python3/main.py188
-rw-r--r--engine/python3/romaji.py263
-rw-r--r--engine/python3/segment.py95
-rw-r--r--engine/python3/tables.py731
-rw-r--r--engine/python3/test.py21
-rw-r--r--engine/python3/thumb.py657
-rw-r--r--setup/Makefile.am104
l---------setup/_config.py.in1
-rw-r--r--setup/python2/Makefile.am116
l---------setup/python2/_config.py.in1
-rw-r--r--setup/python2/anthyprefs.py.in (renamed from setup/anthyprefs.py.in)0
-rw-r--r--setup/python2/ibus-setup-anthy.desktop.in.in (renamed from setup/ibus-setup-anthy.desktop.in.in)0
-rw-r--r--setup/python2/ibus-setup-anthy.in (renamed from setup/ibus-setup-anthy.in)0
-rw-r--r--setup/python2/main.py (renamed from setup/main.py)0
-rw-r--r--setup/python2/prefs.py (renamed from setup/prefs.py)0
-rw-r--r--setup/python2/setup.ui (renamed from setup/setup.ui)0
-rw-r--r--setup/python3/Makefile.am116
l---------setup/python3/_config.py.in1
-rw-r--r--setup/python3/anthyprefs.py.in1329
-rw-r--r--setup/python3/ibus-setup-anthy.desktop.in.in8
-rw-r--r--setup/python3/ibus-setup-anthy.in28
-rw-r--r--setup/python3/main.py1729
-rw-r--r--setup/python3/prefs.py273
-rw-r--r--setup/python3/setup.ui2813
52 files changed, 12288 insertions, 275 deletions
diff --git a/configure.ac b/configure.ac
index 2ab29d3..fbabf0d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -110,57 +110,44 @@ dnl - check env
AC_PATH_PROG(ENV_IBUS_TEST, env)
AC_SUBST(ENV_IBUS_TEST)
-dnl - check python
-dnl ibus-anthy and pygobject3 uses python2
-dnl but AM_PATH_PYTHON does not check if python3 is used
-dnl so I created IBUS_PYTHON_CHECK_VERSION2 from AM_PYTHON_CHECK_VERSION
-dnl to check both the python minimum version and 3.
-
-dnl from python.m4
-IBUS_PYTHON_MIN_VERSION=2.5
-IBUS_PYTHON_CHECK_VERSION2() {
- ARGS="import sys
-# split strings by '.' and convert to numeric. Append some zeros
-# because we need at least 4 digits for the hex conversion.
-# map returns an iterator in Python 3.0 and a list in 2.x
-minver = list(map(int, '$2'.split('.')))
-if [len](minver) < 4:
- for i in list(range(0, 4 - [len](minver))): minver.append(0)
-minverhex = 0
-# xrange is not present in Python 3.0 and range returns an iterator
-for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]]
-threever = [[3, 0, 0, 0]]
-threeverhex = 0
-for i in list(range(0, 4)): threeverhex = (threeverhex << 8) + threever[[i]]
-sys.exit(not (sys.hexversion >= minverhex and \\
- sys.hexversion < threeverhex))"
- PROG="$1"
- PYTHON_VERSION2=`"$PROG" -c "import sys; sys.stdout.write(sys.version[[:3]])"`
- "$PROG" -c "$ARGS"
- return $?
-}
-
-AC_MSG_CHECKING([whether you have python2])
-HAS_PYTHON2=no
-IBUS_PYTHON_INTERPRETER_LIST='
-python python2 python2.7 python2.6 pythhon2.5
-'
-for PYTHON2 in $IBUS_PYTHON_INTERPRETER_LIST ; do
- IBUS_PYTHON_CHECK_VERSION2 $PYTHON2 $IBUS_PYTHON_MIN_VERSION
- if test $? -eq 0 ; then
- HAS_PYTHON2=yes
- break
- fi
-done
-AC_MSG_RESULT($HAS_PYTHON2)
-
-if test x"$HAS_PYTHON2" = xyes; then
- AC_PATH_PROG(PYTHON, $PYTHON2)
- PYTHON_VERSION=$PYTHON_VERSION2
-fi
+dnl - define python version
+AC_ARG_WITH(python,
+ AS_HELP_STRING([--with-python[=PATH]],
+ [Select python2 or python3]),
+ [PYTHON=$with_python], []
+)
dnl export $pyexecdir using existent $PYTHON
-AM_PATH_PYTHON([$IBUS_PYTHON_MIN_VERSION])
+AM_PATH_PYTHON([2.5])
+
+dnl Decided to separate python3 directory from python2 directory here
+dnl because engine/table.py includes unicode array so it's better to
+dnl use __future__.unicode_literals.
+dnl python3 string are always str.
+dnl In case __future__.unicode_literals is imported, all the literal
+dnl 'a' is treated as unicode and u'a' is not needed in python2.
+dnl But str is not unicode so we need to convert str to unicode in
+dnl python2 for all non-literal variables likes return values of
+dnl gettext, IBusConfig.get_value, get methods in GTK+ and so on.
+dnl It would causes to complicate python2 codes if merge python2 and
+dnl python3 in the same file.
+dnl if sys.version < '3':
+dnl return unicode(gettext(a), 'utf-8')
+dnl else:
+dnl return gettext(a)
+case "$PYTHON_VERSION" in
+3.*)
+ enable_python3=yes
+ enable_python2=no
+ ;;
+*)
+ enable_python3=no
+ enable_python2=yes
+ ;;
+esac
+
+AM_CONDITIONAL([ENABLE_PYTHON2], [test x"$enable_python2" = x"yes"])
+AM_CONDITIONAL([ENABLE_PYTHON3], [test x"$enable_python3" = x"yes"])
dnl - check the supported ibus version
AC_MSG_CHECKING([if your ibus version is supported])
@@ -173,9 +160,9 @@ from gi.repository import IBus
retval = _ibus_check_version (ibus_major_version,
ibus_minor_version)
if not retval:
- print 'your ibus version %d.%d.%d is old against %d.%d.%d' \
+ print ('your ibus version %d.%d.%d is old against %d.%d.%d' \
% ( IBus.MAJOR_VERSION, IBus.MINOR_VERSION, IBus.MICRO_VERSION, \
- ibus_major_version, ibus_minor_version, ibus_micro_version )
+ ibus_major_version, ibus_minor_version, ibus_micro_version ))
exit (-1)
exit(0)
"
@@ -424,11 +411,19 @@ ibus-anthy.spec
data/Makefile
gir/Makefile
engine/Makefile
-engine/ibus-engine-anthy
-engine/anthy.xml.in
-engine/default.xml.in
+engine/python2/Makefile
+engine/python2/ibus-engine-anthy
+engine/python2/anthy.xml.in
+engine/python2/default.xml.in
+engine/python3/Makefile
+engine/python3/ibus-engine-anthy
+engine/python3/anthy.xml.in
+engine/python3/default.xml.in
setup/Makefile
-setup/ibus-setup-anthy
+setup/python2/Makefile
+setup/python2/ibus-setup-anthy
+setup/python3/Makefile
+setup/python3/ibus-setup-anthy
icons/Makefile
m4/Makefile
])
@@ -446,6 +441,8 @@ LT_VERSION_INFO $LT_VERSION_INFO
ENV_IBUS_ENGINE $ENV_IBUS_ENGINE
HAVE_PYGTK2_ANTHY $enable_pygtk2_anthy
python $PYTHON
+Enable python2 $enable_python2
+Enable python3 $enable_python3
python-config $PYTHON_CONFIG
PYTHON_CFLAGS $PYTHON_CFLAGS
PYTHON_LIBS $PYTHON_LIBS
diff --git a/engine/Makefile.am b/engine/Makefile.am
index a96f831..3c64425 100644
--- a/engine/Makefile.am
+++ b/engine/Makefile.am
@@ -2,9 +2,8 @@
#
# ibus-anthy - The Anthy engine for IBus
#
-# Copyright (c) 2007-2008 Peng Huang <shawn.p.huang@gmail.com>
-# Copyright (c) 2010-2013 Takao Fujiwara <takao.fujiwara1@gmail.com>
-# Copyright (c) 2007-2013 Red Hat, Inc.
+# Copyright (c) 2014 Takao Fujiwara <takao.fujiwara1@gmail.com>
+# Copyright (c) 2014 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -20,125 +19,12 @@
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-BUILT_SOURCES = _config.py
+SUBDIRS =
-engine_anthy_PYTHON = \
- _config.py \
- engine.py \
- factory.py \
- jastring.py \
- kana.py \
- main.py \
- romaji.py \
- segment.py \
- tables.py \
- thumb.py \
- $(NULL)
-engine_anthydir = $(pkgdatadir)/engine
-engine_anthy_built_files = $(BUILT_SOURCES)
-engine_anthy_built_in_files = $(addsuffix .in, $(engine_anthy_built_files))
-
-PYGTK2_ANTHY_RAW = anthy.i
-PYGTK2_ANTHY_GEN = anthy.py anthy_wrap.c
-
-if HAVE_PYGTK2_ANTHY
-anthy_DATA = \
- anthy.py \
- $(NULL)
-anthy_LTLIBRARIES = _anthy.la
-anthydir = @pyexecdir@
-
-_anthy_la_SOURCES = \
- $(NULL)
-
-nodist__anthy_la_SOURCES = \
- anthy_wrap.c \
- $(NULL)
-
-_anthy_la_CFLAGS = \
- @ANTHY_CFLAGS@ \
- @PYTHON_CFLAGS@ \
- $(NULL)
-
-_anthy_la_LDFLAGS = \
- @ANTHY_LIBS@ \
- @PYTHON_LIBS@ \
- -avoid-version \
- -module \
- $(NULL)
-
-anthy.py anthy_wrap.c: anthy.i
- $(SWIG) -python $(ANTHY_CFLAGS) -I/usr/include -o anthy_wrap.c $(srcdir)/anthy.i
+if ENABLE_PYTHON2
+SUBDIRS += python2
endif
-libexec_SCRIPTS = ibus-engine-anthy
-component_DATA = anthy.xml
-componentdir = $(datadir)/ibus/component
-engine_DATA = default.xml
-enginedir = $(pkgdatadir)/engine
-
-anthy.xml: anthy.xml.in
- ( \
- libexecdir=${libexecdir}; \
- pkgdatadir=${pkgdatadir}; \
- s=`cat $<`; \
- eval "echo \"$${s}\""; \
- ) > $@
-
-default.xml: default.xml.in
- ( \
- libexecdir=${libexecdir}; \
- pkgdatadir=${pkgdatadir}; \
- s=`cat $<`; \
- eval "echo \"$${s}\""; \
- ) > $@
-
-_config.py: _config.py.in
- ( \
- PKGDATADIR=$(pkgdatadir); \
- LIBEXECDIR=$(libexecdir); \
- DATADIR=$(datadir); \
- LAYOUT=$(LAYOUT); \
- SYMBOL_CHAR_INT=$(SYMBOL_CHAR_INT); \
- ICON_PREFERENCE=$(ICON_PREFERENCE); \
- s=`cat $<`; \
- eval "echo \"$${s}\""; \
- ) > $@
-
-test:
- $(ENV_IBUS_TEST) \
- DBUS_DEBUG=true \
- IBUS_ANTHY_PKGDATADIR=$(abs_top_srcdir) \
- PYTHONPATH=$(builddir)/.libs:@pyexecdir@ \
- $(PYTHON) \
- $(srcdir)/main.py
-
-EXTRA_DIST = \
- $(engine_anthy_built_in_files) \
- $(PYGTK2_ANTHY_RAW) \
- anthy.xml.in.in \
- default.xml.in.in \
- ibus-engine-anthy.in \
- $(NULL)
-
-CLEANFILES = \
- $(BUILT_SOURCES) \
- $(PYGTK2_ANTHY_GEN) \
- anthy.xml \
- default.xml \
- *.pyc \
- $(NULL)
-
-DISTCLEANFILES = \
- $(NULL)
-
-# Need a time lag between .py and .py.in files to build .py files
-# because *_PYTHON valuables are installed in the tarball.
-dist-hook:
- @sleep 1; \
- for in_file in $(engine_anthy_built_in_files) ; do \
- if [ -f $(distdir)/$(srcdir)/$$in_file ] ; then \
- touch $(distdir)/$(srcdir)/$$in_file; \
- fi; \
- done;
-
+if ENABLE_PYTHON3
+SUBDIRS += python3
+endif
diff --git a/engine/python2/Makefile.am b/engine/python2/Makefile.am
new file mode 100644
index 0000000..a96f831
--- /dev/null
+++ b/engine/python2/Makefile.am
@@ -0,0 +1,144 @@
+# vim:set noet ts=4:
+#
+# ibus-anthy - The Anthy engine for IBus
+#
+# Copyright (c) 2007-2008 Peng Huang <shawn.p.huang@gmail.com>
+# Copyright (c) 2010-2013 Takao Fujiwara <takao.fujiwara1@gmail.com>
+# Copyright (c) 2007-2013 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+BUILT_SOURCES = _config.py
+
+engine_anthy_PYTHON = \
+ _config.py \
+ engine.py \
+ factory.py \
+ jastring.py \
+ kana.py \
+ main.py \
+ romaji.py \
+ segment.py \
+ tables.py \
+ thumb.py \
+ $(NULL)
+engine_anthydir = $(pkgdatadir)/engine
+engine_anthy_built_files = $(BUILT_SOURCES)
+engine_anthy_built_in_files = $(addsuffix .in, $(engine_anthy_built_files))
+
+PYGTK2_ANTHY_RAW = anthy.i
+PYGTK2_ANTHY_GEN = anthy.py anthy_wrap.c
+
+if HAVE_PYGTK2_ANTHY
+anthy_DATA = \
+ anthy.py \
+ $(NULL)
+anthy_LTLIBRARIES = _anthy.la
+anthydir = @pyexecdir@
+
+_anthy_la_SOURCES = \
+ $(NULL)
+
+nodist__anthy_la_SOURCES = \
+ anthy_wrap.c \
+ $(NULL)
+
+_anthy_la_CFLAGS = \
+ @ANTHY_CFLAGS@ \
+ @PYTHON_CFLAGS@ \
+ $(NULL)
+
+_anthy_la_LDFLAGS = \
+ @ANTHY_LIBS@ \
+ @PYTHON_LIBS@ \
+ -avoid-version \
+ -module \
+ $(NULL)
+
+anthy.py anthy_wrap.c: anthy.i
+ $(SWIG) -python $(ANTHY_CFLAGS) -I/usr/include -o anthy_wrap.c $(srcdir)/anthy.i
+endif
+
+libexec_SCRIPTS = ibus-engine-anthy
+component_DATA = anthy.xml
+componentdir = $(datadir)/ibus/component
+engine_DATA = default.xml
+enginedir = $(pkgdatadir)/engine
+
+anthy.xml: anthy.xml.in
+ ( \
+ libexecdir=${libexecdir}; \
+ pkgdatadir=${pkgdatadir}; \
+ s=`cat $<`; \
+ eval "echo \"$${s}\""; \
+ ) > $@
+
+default.xml: default.xml.in
+ ( \
+ libexecdir=${libexecdir}; \
+ pkgdatadir=${pkgdatadir}; \
+ s=`cat $<`; \
+ eval "echo \"$${s}\""; \
+ ) > $@
+
+_config.py: _config.py.in
+ ( \
+ PKGDATADIR=$(pkgdatadir); \
+ LIBEXECDIR=$(libexecdir); \
+ DATADIR=$(datadir); \
+ LAYOUT=$(LAYOUT); \
+ SYMBOL_CHAR_INT=$(SYMBOL_CHAR_INT); \
+ ICON_PREFERENCE=$(ICON_PREFERENCE); \
+ s=`cat $<`; \
+ eval "echo \"$${s}\""; \
+ ) > $@
+
+test:
+ $(ENV_IBUS_TEST) \
+ DBUS_DEBUG=true \
+ IBUS_ANTHY_PKGDATADIR=$(abs_top_srcdir) \
+ PYTHONPATH=$(builddir)/.libs:@pyexecdir@ \
+ $(PYTHON) \
+ $(srcdir)/main.py
+
+EXTRA_DIST = \
+ $(engine_anthy_built_in_files) \
+ $(PYGTK2_ANTHY_RAW) \
+ anthy.xml.in.in \
+ default.xml.in.in \
+ ibus-engine-anthy.in \
+ $(NULL)
+
+CLEANFILES = \
+ $(BUILT_SOURCES) \
+ $(PYGTK2_ANTHY_GEN) \
+ anthy.xml \
+ default.xml \
+ *.pyc \
+ $(NULL)
+
+DISTCLEANFILES = \
+ $(NULL)
+
+# Need a time lag between .py and .py.in files to build .py files
+# because *_PYTHON valuables are installed in the tarball.
+dist-hook:
+ @sleep 1; \
+ for in_file in $(engine_anthy_built_in_files) ; do \
+ if [ -f $(distdir)/$(srcdir)/$$in_file ] ; then \
+ touch $(distdir)/$(srcdir)/$$in_file; \
+ fi; \
+ done;
+
diff --git a/engine/_config.py.in b/engine/python2/_config.py.in
index 4d5738b..4d5738b 100644
--- a/engine/_config.py.in
+++ b/engine/python2/_config.py.in
diff --git a/engine/anthy.i b/engine/python2/anthy.i
index 68a3aa9..68a3aa9 100644
--- a/engine/anthy.i
+++ b/engine/python2/anthy.i
diff --git a/engine/anthy.xml.in.in b/engine/python2/anthy.xml.in.in
index 9a93744..9a93744 100644
--- a/engine/anthy.xml.in.in
+++ b/engine/python2/anthy.xml.in.in
diff --git a/engine/default.xml.in.in b/engine/python2/default.xml.in.in
index 27e3c82..27e3c82 100644
--- a/engine/default.xml.in.in
+++ b/engine/python2/default.xml.in.in
diff --git a/engine/engine.py b/engine/python2/engine.py
index f38ebcf..be91802 100644
--- a/engine/engine.py
+++ b/engine/python2/engine.py
@@ -2350,7 +2350,7 @@ class Engine(IBus.EngineSimple):
self.__convert_chars = UN(clipboard_text)
for i in xrange(0, len(self.__convert_chars)):
keyval = self.__convert_chars[i]
- self.__preedit_ja_string.insert(unichr(ord (keyval)))
+ self.__preedit_ja_string.insert(unichr(ord(keyval)))
self.__context.set_string(self.__convert_chars.encode('utf-8'))
nr_segments = self.__context.get_nr_segments()
@@ -2484,7 +2484,7 @@ class Engine(IBus.EngineSimple):
self.__cursor_pos = 0
text, cursor = self.__get_preedit()
self.__convert_chars = text
- self.__context.set_string(text.encode ('utf-8'))
+ self.__context.set_string(text.encode('utf-8'))
self.__lookup_table.clear()
self.__lookup_table.set_cursor_visible(False)
diff --git a/engine/factory.py b/engine/python2/factory.py
index d4aa075..d4aa075 100644
--- a/engine/factory.py
+++ b/engine/python2/factory.py
diff --git a/engine/ibus-engine-anthy.in b/engine/python2/ibus-engine-anthy.in
index c54b10a..c54b10a 100644
--- a/engine/ibus-engine-anthy.in
+++ b/engine/python2/ibus-engine-anthy.in
diff --git a/engine/jastring.py b/engine/python2/jastring.py
index aeb7e6e..aeb7e6e 100644
--- a/engine/jastring.py
+++ b/engine/python2/jastring.py
diff --git a/engine/kana.py b/engine/python2/kana.py
index c85a199..c85a199 100644
--- a/engine/kana.py
+++ b/engine/python2/kana.py
diff --git a/engine/main.py b/engine/python2/main.py
index b899681..b899681 100644
--- a/engine/main.py
+++ b/engine/python2/main.py
diff --git a/engine/romaji.py b/engine/python2/romaji.py
index 48167c6..48167c6 100644
--- a/engine/romaji.py
+++ b/engine/python2/romaji.py
diff --git a/engine/segment.py b/engine/python2/segment.py
index d423f19..d423f19 100644
--- a/engine/segment.py
+++ b/engine/python2/segment.py
diff --git a/engine/tables.py b/engine/python2/tables.py
index 2e41366..2e41366 100644
--- a/engine/tables.py
+++ b/engine/python2/tables.py
diff --git a/engine/test.py b/engine/python2/test.py
index cd67997..cd67997 100644
--- a/engine/test.py
+++ b/engine/python2/test.py
diff --git a/engine/thumb.py b/engine/python2/thumb.py
index 6a7e3d2..6a7e3d2 100644
--- a/engine/thumb.py
+++ b/engine/python2/thumb.py
diff --git a/engine/python3/Makefile.am b/engine/python3/Makefile.am
new file mode 100644
index 0000000..a96f831
--- /dev/null
+++ b/engine/python3/Makefile.am
@@ -0,0 +1,144 @@
+# vim:set noet ts=4:
+#
+# ibus-anthy - The Anthy engine for IBus
+#
+# Copyright (c) 2007-2008 Peng Huang <shawn.p.huang@gmail.com>
+# Copyright (c) 2010-2013 Takao Fujiwara <takao.fujiwara1@gmail.com>
+# Copyright (c) 2007-2013 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+BUILT_SOURCES = _config.py
+
+engine_anthy_PYTHON = \
+ _config.py \
+ engine.py \
+ factory.py \
+ jastring.py \
+ kana.py \
+ main.py \
+ romaji.py \
+ segment.py \
+ tables.py \
+ thumb.py \
+ $(NULL)
+engine_anthydir = $(pkgdatadir)/engine
+engine_anthy_built_files = $(BUILT_SOURCES)
+engine_anthy_built_in_files = $(addsuffix .in, $(engine_anthy_built_files))
+
+PYGTK2_ANTHY_RAW = anthy.i
+PYGTK2_ANTHY_GEN = anthy.py anthy_wrap.c
+
+if HAVE_PYGTK2_ANTHY
+anthy_DATA = \
+ anthy.py \
+ $(NULL)
+anthy_LTLIBRARIES = _anthy.la
+anthydir = @pyexecdir@
+
+_anthy_la_SOURCES = \
+ $(NULL)
+
+nodist__anthy_la_SOURCES = \
+ anthy_wrap.c \
+ $(NULL)
+
+_anthy_la_CFLAGS = \
+ @ANTHY_CFLAGS@ \
+ @PYTHON_CFLAGS@ \
+ $(NULL)
+
+_anthy_la_LDFLAGS = \
+ @ANTHY_LIBS@ \
+ @PYTHON_LIBS@ \
+ -avoid-version \
+ -module \
+ $(NULL)
+
+anthy.py anthy_wrap.c: anthy.i
+ $(SWIG) -python $(ANTHY_CFLAGS) -I/usr/include -o anthy_wrap.c $(srcdir)/anthy.i
+endif
+
+libexec_SCRIPTS = ibus-engine-anthy
+component_DATA = anthy.xml
+componentdir = $(datadir)/ibus/component
+engine_DATA = default.xml
+enginedir = $(pkgdatadir)/engine
+
+anthy.xml: anthy.xml.in
+ ( \
+ libexecdir=${libexecdir}; \
+ pkgdatadir=${pkgdatadir}; \
+ s=`cat $<`; \
+ eval "echo \"$${s}\""; \
+ ) > $@
+
+default.xml: default.xml.in
+ ( \
+ libexecdir=${libexecdir}; \
+ pkgdatadir=${pkgdatadir}; \
+ s=`cat $<`; \
+ eval "echo \"$${s}\""; \
+ ) > $@
+
+_config.py: _config.py.in
+ ( \
+ PKGDATADIR=$(pkgdatadir); \
+ LIBEXECDIR=$(libexecdir); \
+ DATADIR=$(datadir); \
+ LAYOUT=$(LAYOUT); \
+ SYMBOL_CHAR_INT=$(SYMBOL_CHAR_INT); \
+ ICON_PREFERENCE=$(ICON_PREFERENCE); \
+ s=`cat $<`; \
+ eval "echo \"$${s}\""; \
+ ) > $@
+
+test:
+ $(ENV_IBUS_TEST) \
+ DBUS_DEBUG=true \
+ IBUS_ANTHY_PKGDATADIR=$(abs_top_srcdir) \
+ PYTHONPATH=$(builddir)/.libs:@pyexecdir@ \
+ $(PYTHON) \
+ $(srcdir)/main.py
+
+EXTRA_DIST = \
+ $(engine_anthy_built_in_files) \
+ $(PYGTK2_ANTHY_RAW) \
+ anthy.xml.in.in \
+ default.xml.in.in \
+ ibus-engine-anthy.in \
+ $(NULL)
+
+CLEANFILES = \
+ $(BUILT_SOURCES) \
+ $(PYGTK2_ANTHY_GEN) \
+ anthy.xml \
+ default.xml \
+ *.pyc \
+ $(NULL)
+
+DISTCLEANFILES = \
+ $(NULL)
+
+# Need a time lag between .py and .py.in files to build .py files
+# because *_PYTHON valuables are installed in the tarball.
+dist-hook:
+ @sleep 1; \
+ for in_file in $(engine_anthy_built_in_files) ; do \
+ if [ -f $(distdir)/$(srcdir)/$$in_file ] ; then \
+ touch $(distdir)/$(srcdir)/$$in_file; \
+ fi; \
+ done;
+
diff --git a/engine/python3/_config.py.in b/engine/python3/_config.py.in
new file mode 100644
index 0000000..f68b50a
--- /dev/null
+++ b/engine/python3/_config.py.in
@@ -0,0 +1,30 @@
+# vim:set et sts=4 sw=4:
+# -*- coding: utf-8 -*-
+#
+# ibus-anthy - The Anthy engine for IBus
+#
+# Copyright (c) 2007-2008 Peng Huang <shawn.p.huang@gmail.com>
+# Copyright (c) 2010-2014 Takao Fujiwara <takao.fujiwara1@gmail.com>
+# Copyright (c) 2007-2014 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+PKGDATADIR = '${PKGDATADIR}'
+LIBEXECDIR = '${LIBEXECDIR}'
+LOCALEDIR = '${DATADIR}/locale'
+LAYOUT = '${LAYOUT}'
+SYMBOL_CHAR = chr(${SYMBOL_CHAR_INT})
+ICON_PREFERENCE = '${ICON_PREFERENCE}'
+DEBUG = False
diff --git a/engine/python3/anthy.i b/engine/python3/anthy.i
new file mode 100644
index 0000000..68a3aa9
--- /dev/null
+++ b/engine/python3/anthy.i
@@ -0,0 +1,125 @@
+/* vim:set et ts=4: */
+/*
+ * ibus-anthy - The Anthy engine for IBus
+ *
+ * Copyright (c) 2007-2008 Peng Huang <shawn.p.huang@gmail.com>
+ * Copyright (c) 2010-2013 Takao Fujiwara <takao.fujiwara1@gmail.com>
+ * Copyright (c) 2007-2013 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+%module anthy
+%{
+ /* Put header files here or function declarations like below */
+#include <anthy/anthy.h>
+%}
+
+%init %{
+ anthy_init ();
+%}
+
+/* anthy_context_t */
+%include anthy/anthy.h
+struct anthy_context {};
+%extend anthy_context {
+ anthy_context () {
+ return anthy_create_context ();
+ }
+
+ void reset () {
+ anthy_reset_context (self);
+ }
+
+ int set_string (char *str) {
+ return anthy_set_string (self, str);
+ }
+
+ void resize_segment (int a1, int a2) {
+ anthy_resize_segment (self, a1, a2);
+ }
+
+ int get_stat (struct anthy_conv_stat *a1) {
+ return anthy_get_stat (self, a1);
+ }
+
+ int get_segment_stat (int a1, struct anthy_segment_stat *a2) {
+ return anthy_get_segment_stat (self, a1, a2);
+ }
+
+ char *get_segment (int a1, int a2) {
+ int len;
+ static char temp[512];
+
+ len = anthy_get_segment (self, a1, a2, temp, sizeof (temp));
+ if (len >= 0)
+ return temp;
+ else
+ return NULL;
+ }
+
+ int commit_segment (int a1, int a2) {
+ return anthy_commit_segment (self, a1, a2);
+ }
+
+ int set_prediction_string (const char *a1) {
+ return anthy_set_prediction_string (self, a1);
+ }
+
+ int get_prediction_stat (struct anthy_prediction_stat *a1) {
+ return anthy_get_prediction_stat (self, a1);
+ }
+
+ char *get_prediction (int a1) {
+ int len;
+ static char temp[512];
+
+ len = anthy_get_prediction (self, a1, temp, sizeof (temp));
+
+ if (len >= 0)
+ return temp;
+ else
+ return NULL;
+ }
+
+ int commit_prediction (int a1) {
+ return anthy_commit_prediction(self, a1);
+ }
+
+ void _print () {
+ anthy_print_context (self);
+ }
+
+ int _set_encoding (int encoding) {
+ return anthy_context_set_encoding (self, encoding);
+ }
+
+ int set_reconversion_mode (int mode) {
+ return anthy_set_reconversion_mode (self, mode);
+ }
+
+ int init_personality (void) {
+ return anthy_init_personality ();
+ }
+
+ int do_set_personality (const char *id) {
+ return anthy_do_set_personality (id);
+ }
+
+ ~anthy_context () {
+ anthy_release_context (self);
+ }
+};
+
diff --git a/engine/python3/anthy.xml.in.in b/engine/python3/anthy.xml.in.in
new file mode 100644
index 0000000..9a93744
--- /dev/null
+++ b/engine/python3/anthy.xml.in.in
@@ -0,0 +1,19 @@
+<?xml version=\"1.0\" encoding=\"utf-8\"?>
+<!-- filename: anthy.xml -->
+<component>
+ <name>org.freedesktop.IBus.Anthy</name>
+ <description>Anthy Component</description>
+ <exec>${libexecdir}/ibus-engine-anthy --ibus</exec>
+ <version>@VERSION@</version>
+ <author>Peng Huang &lt;shawn.p.huang@gmail.com&gt;</author>
+ <license>GPL</license>
+ <homepage>http://code.google.com/p/ibus</homepage>
+ <textdomain>ibus-anthy</textdomain>
+
+ <!-- for engines -->
+ <observed-paths>
+ <path>~/.config/ibus-anthy/engines.xml</path>
+ <path>${pkgdatadir}/engine/default.xml</path>
+ </observed-paths>
+ <engines exec=\"${libexecdir}/ibus-engine-anthy --xml\" />
+</component>
diff --git a/engine/python3/default.xml.in.in b/engine/python3/default.xml.in.in
new file mode 100644
index 0000000..27e3c82
--- /dev/null
+++ b/engine/python3/default.xml.in.in
@@ -0,0 +1,19 @@
+<?xml version=\"1.0\" encoding=\"utf-8\"?>
+<engines>
+ <engine>
+ <name>anthy</name>
+ <language>ja</language>
+ <license>GPL</license>
+ <author>Peng Huang &lt;shawn.p.huang@gmail.com&gt;</author>
+ <icon>ibus-anthy</icon>
+ @LAYOUT_XML@
+ <layout_variant></layout_variant>
+ <layout_option></layout_option>
+ <longname>Anthy</longname>
+ <description>Anthy Input Method</description>
+ <rank>99</rank>
+ @HOTKEYS_XML@
+ @SYMBOL_XML@
+ <version>@PACKAGE_VERSION@</version>
+ </engine>
+</engines>
diff --git a/engine/python3/engine.py b/engine/python3/engine.py
new file mode 100644
index 0000000..2119c39
--- /dev/null
+++ b/engine/python3/engine.py
@@ -0,0 +1,2780 @@
+# vim:set et sts=4 sw=4:
+# -*- coding: utf-8 -*-
+#
+# ibus-anthy - The Anthy engine for IBus
+#
+# Copyright (c) 2007-2008 Peng Huang <shawn.p.huang@gmail.com>
+# Copyright (c) 2010-2014 Takao Fujiwara <takao.fujiwara1@gmail.com>
+# Copyright (c) 2007-2014 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+import binascii
+import os
+from os import environ, path
+import signal
+import sys
+from gettext import dgettext
+
+from main import get_userhome
+
+try:
+ from locale import getpreferredencoding
+except:
+ pass
+
+from gi.repository import GLib
+from gi.repository import IBus
+
+from gi.repository import Anthy
+NTH_UNCONVERTED_CANDIDATE = Anthy.NTH_UNCONVERTED_CANDIDATE
+NTH_KATAKANA_CANDIDATE = Anthy.NTH_KATAKANA_CANDIDATE
+NTH_HIRAGANA_CANDIDATE = Anthy.NTH_HIRAGANA_CANDIDATE
+NTH_HALFKANA_CANDIDATE = Anthy.NTH_HALFKANA_CANDIDATE
+
+import _config as config
+from tables import *
+import jastring
+from segment import unichar_half_to_full
+
+sys.path.append(path.join(config.PKGDATADIR, 'setup'))
+from anthyprefs import AnthyPrefs
+
+_ = lambda a : dgettext('ibus-anthy', a)
+N_ = lambda a : a
+UN = lambda a : unicode(a, 'utf-8')
+
+printerr = AnthyPrefs.printerr
+
+INPUT_MODE_HIRAGANA, \
+INPUT_MODE_KATAKANA, \
+INPUT_MODE_HALF_WIDTH_KATAKANA, \
+INPUT_MODE_LATIN, \
+INPUT_MODE_WIDE_LATIN = list(range(5))
+
+CONV_MODE_OFF, \
+CONV_MODE_ANTHY, \
+CONV_MODE_HIRAGANA, \
+CONV_MODE_KATAKANA, \
+CONV_MODE_HALF_WIDTH_KATAKANA, \
+CONV_MODE_LATIN_0, \
+CONV_MODE_LATIN_1, \
+CONV_MODE_LATIN_2, \
+CONV_MODE_LATIN_3, \
+CONV_MODE_WIDE_LATIN_0, \
+CONV_MODE_WIDE_LATIN_1, \
+CONV_MODE_WIDE_LATIN_2, \
+CONV_MODE_WIDE_LATIN_3, \
+CONV_MODE_PREDICTION = list(range(14))
+
+SEGMENT_DEFAULT = 0
+SEGMENT_SINGLE = 1 << 0
+SEGMENT_IMMEDIATE = 1 << 1
+
+CLIPBOARD_RECONVERT = list(range(1))
+
+LINK_DICT_EMBEDDED, \
+LINK_DICT_SINGLE = list(range(2))
+
+IMPORTED_EMBEDDED_DICT_DIR = 'imported_words_default.d'
+IMPORTED_EMBEDDED_DICT_PREFIX = 'ibus__'
+IMPORTED_SINGLE_DICT_PREFIX = 'imported_words_ibus__'
+
+KP_Table = {}
+for s in dir(IBus):
+ if s.startswith('KEY_KP_'):
+ v = IBus.keyval_from_name(s[7:])
+ if v:
+ KP_Table[IBus.keyval_from_name(s[4:])] = v
+for k, v in zip(['KEY_KP_Add', 'KEY_KP_Decimal', 'KEY_KP_Divide', 'KEY_KP_Enter',
+ 'KEY_KP_Equal', 'KEY_KP_Multiply', 'KEY_KP_Separator',
+ 'KEY_KP_Space', 'KEY_KP_Subtract'],
+ ['KEY_plus', 'KEY_period', 'KEY_slash', 'KEY_Return',
+ 'KEY_equal', 'KEY_asterisk', 'KEY_comma',
+ 'KEY_space', 'KEY_minus']):
+ KP_Table[getattr(IBus, k)] = getattr(IBus, v)
+
+class Engine(IBus.EngineSimple):
+ __input_mode = None
+ __typing_mode = None
+ __segment_mode = None
+ __dict_mode = None
+
+ __setup_pid = 0
+ __prefs = None
+ __keybind = {}
+ __thumb = None
+ __latin_with_shift = True
+
+ def __init__(self, bus, object_path):
+ super(Engine, self).__init__(engine_name="anthy",
+ connection=bus.get_connection(),
+ object_path=object_path)
+
+ # create anthy context
+ self.__context = Anthy.GContext()
+ self.__context.set_encoding(Anthy.UTF8_ENCODING)
+
+ # init state
+ self.__idle_id = 0
+ self.__prop_dict = {}
+ self.__input_purpose = 0
+ self.__has_input_purpose = False
+ if hasattr(IBus, 'InputPurpose'):
+ self.__has_input_purpose = True
+ try:
+ self.__is_utf8 = (getpreferredencoding().lower() == 'utf-8')
+ except:
+ self.__is_utf8 = False
+ self.__ibus_version = 0.0
+
+# self.__lookup_table = ibus.LookupTable.new(page_size=9,
+# cursor_pos=0,
+# cursor_visible=True,
+# round=True)
+ size = self.__prefs.get_value('common', 'page_size')
+ self.__lookup_table = IBus.LookupTable.new(page_size=size,
+ cursor_pos=0,
+ cursor_visible=True,
+ round=True)
+ self.__prop_list = self.__init_props()
+
+ # Do not use self.do_process_key_event to work ISO 14755
+ # with Ctrl+Shift+u .
+ # The super (parent) method of do_process_key_event is called
+ # loop infinitely if this class overrides it.
+ # self.process_key_event is not accessible too.
+ self.connect('process-key-event', self.__process_key_event)
+ self.connect('destroy', self.__destroy)
+
+ self.__init_signal()
+ # use reset to init values
+ self.__reset()
+
+ ibus_config = bus.get_config()
+ if ibus_config != None:
+ ibus_config.connect('value-changed',
+ self.__config_value_changed_cb)
+
+ def __get_ibus_version(self):
+ if self.__ibus_version == 0.0:
+ self.__ibus_version = \
+ IBus.MAJOR_VERSION + IBus.MINOR_VERSION / 1000.0 + \
+ IBus.MICRO_VERSION / 1000000.0
+ return self.__ibus_version
+
+ # reset values of engine
+ def __reset(self):
+ self.__preedit_ja_string = jastring.JaString(Engine.__typing_mode,
+ self.__latin_with_shift)
+ self.__convert_chars = ''
+ self.__cursor_pos = 0
+ self.__convert_mode = CONV_MODE_OFF
+ self.__segments = list()
+ self.__lookup_table.clear()
+ self.__lookup_table_visible = False
+ self._MM = 0
+ self._SS = 0
+ self._H = 0
+ self._RMM = 0
+ self._RSS = 0
+ if self.__idle_id != 0:
+ GLib.source_remove(self.__idle_id)
+ self.__idle_id = 0
+
+ def __init_props(self):
+ anthy_props = IBus.PropList()
+
+ self.__set_input_mode_props(anthy_props)
+ self.__set_typing_method_props(anthy_props)
+ self.__set_segment_mode_props(anthy_props)
+ self.__set_dict_mode_props(anthy_props)
+ self.__set_dict_config_props(anthy_props)
+
+ if not self.__prefs.get_value('common', 'show-preferences'):
+ return anthy_props
+
+ anthy_props.append(IBus.Property(key='setup',
+ label=IBus.Text.new_from_string(_("Preferences - Anthy")),
+ icon=config.ICON_PREFERENCE,
+ tooltip=IBus.Text.new_from_string(_("Configure Anthy")),
+ sensitive=True,
+ visible=True))
+
+ return anthy_props
+
+ def __init_signal(self):
+ signal.signal(signal.SIGHUP, self.__signal_cb)
+ signal.signal(signal.SIGINT, self.__signal_cb)
+ signal.signal(signal.SIGQUIT, self.__signal_cb)
+ signal.signal(signal.SIGABRT, self.__signal_cb)
+ signal.signal(signal.SIGTERM, self.__signal_cb)
+
+ def __signal_cb(self, signum, object):
+ self.__remove_dict_files()
+ signal.signal(signum, signal.SIG_DFL)
+ os.kill(os.getpid(), signum)
+
+ def __set_input_mode_props(self, anthy_props):
+ # The class method is kept even if the engine is switched.
+ if Engine.__input_mode == None:
+ # The config value is readonly for initial engine and
+ # the engine keeps the class method in the memory.
+ Engine.__input_mode = INPUT_MODE_HIRAGANA
+ Engine.__input_mode = self.__prefs.get_value('common',
+ 'input_mode')
+
+ if not self.__prefs.get_value('common', 'show-input-mode'):
+ return
+
+ # init input mode properties
+ symbol = 'あ'
+ '''
+ Need to split _() by line for intltool to detect them.
+ '''
+ # Translators: Specify the order of %s with your translation.
+ # It will be "Input Mode (A)" for example.
+ label = _("%(description)s (%(symbol)s)") % \
+ { 'description' : _("Input mode"), 'symbol' : symbol }
+ input_mode_prop = IBus.Property(key='InputMode',
+ prop_type=IBus.PropType.MENU,
+ label=IBus.Text.new_from_string(label),
+ symbol=IBus.Text.new_from_string(symbol),
+ icon='',
+ tooltip=IBus.Text.new_from_string(_("Switch input mode")),
+ sensitive=True,
+ visible=True,
+ state=IBus.PropState.UNCHECKED,
+ sub_props=None)
+ self.__prop_dict['InputMode'] = input_mode_prop
+
+ props = IBus.PropList()
+ props.append(IBus.Property(key='InputMode.Hiragana',
+ prop_type=IBus.PropType.RADIO,
+ label=IBus.Text.new_from_string(_("Hiragana")),
+ icon=None,
+ tooltip=None,
+ sensitive=True,
+ visible=True,
+ state=IBus.PropState.UNCHECKED,
+ sub_props=None))
+ props.append(IBus.Property(key='InputMode.Katakana',
+ prop_type=IBus.PropType.RADIO,
+ label=IBus.Text.new_from_string(_("Katakana")),
+ icon=None,
+ tooltip=None,
+ sensitive=True,
+ visible=True,
+ state=IBus.PropState.UNCHECKED,
+ sub_props=None))
+ props.append(IBus.Property(key='InputMode.HalfWidthKatakana',
+ prop_type=IBus.PropType.RADIO,
+ label=IBus.Text.new_from_string(_("Halfwidth Katakana")),
+ icon=None,
+ tooltip=None,
+ sensitive=True,
+ visible=True,
+ state=IBus.PropState.UNCHECKED,
+ sub_props=None))
+ props.append(IBus.Property(key='InputMode.Latin',
+ prop_type=IBus.PropType.RADIO,
+ label=IBus.Text.new_from_string(_("Latin")),
+ icon=None,
+ tooltip=None,
+ sensitive=True,
+ visible=True,
+ state=IBus.PropState.UNCHECKED,
+ sub_props=None))
+ props.append(IBus.Property(key='InputMode.WideLatin',
+ prop_type=IBus.PropType.RADIO,
+ label=IBus.Text.new_from_string(_("Wide Latin")),
+ icon=None,
+ tooltip=None,
+ sensitive=True,
+ visible=True,
+ state=IBus.PropState.UNCHECKED,
+ sub_props=None))
+
+ props.get(Engine.__input_mode).set_state(IBus.PropState.CHECKED)
+
+ i = 0
+ while props.get(i) != None:
+ prop = props.get(i)
+ self.__prop_dict[prop.get_key()] = prop
+ i += 1
+
+ input_mode_prop.set_sub_props(props)
+ anthy_props.append(input_mode_prop)
+
+ mode = Engine.__input_mode
+ mode = 'InputMode.' + ['Hiragana', 'Katakana', 'HalfWidthKatakana',
+ 'Latin', 'WideLatin'][mode]
+ self.__input_mode_activate(mode, IBus.PropState.CHECKED)
+
+ def __set_typing_method_props(self, anthy_props):
+ if Engine.__typing_mode == None:
+ Engine.__typing_mode = jastring.TYPING_MODE_ROMAJI
+ Engine.__typing_mode = self.__prefs.get_value('common',
+ 'typing_method')
+
+ if not self.__prefs.get_value('common', 'show-typing-method'):
+ return
+
+ # typing input mode properties
+ symbol = 'R'
+ label = _("%(description)s (%(symbol)s)") % \
+ { 'description' : _("Typing method"), 'symbol' : symbol }
+ typing_mode_prop = IBus.Property(key='TypingMode',
+ prop_type=IBus.PropType.MENU,
+ label=IBus.Text.new_from_string(label),
+ symbol=IBus.Text.new_from_string(symbol),
+ icon='',
+ tooltip=IBus.Text.new_from_string(_("Switch typing method")),
+ sensitive=True,
+ visible=True,
+ state=IBus.PropState.UNCHECKED,
+ sub_props=None)
+ self.__prop_dict['TypingMode'] = typing_mode_prop
+
+ props = IBus.PropList()
+ props.append(IBus.Property(key='TypingMode.Romaji',
+ prop_type=IBus.PropType.RADIO,
+ label=IBus.Text.new_from_string(_("Romaji")),
+ icon=None,
+ tooltip=None,
+ sensitive=True,
+ visible=True,
+ state=IBus.PropState.UNCHECKED,
+ sub_props=None))
+ props.append(IBus.Property(key='TypingMode.Kana',
+ prop_type=IBus.PropType.RADIO,
+ label=IBus.Text.new_from_string(_("Kana")),
+ icon=None,
+ tooltip=None,
+ sensitive=True,
+ visible=True,
+ state=IBus.PropState.UNCHECKED,
+ sub_props=None))
+ props.append(IBus.Property(key='TypingMode.ThumbShift',
+ prop_type=IBus.PropType.RADIO,
+ label=IBus.Text.new_from_string(_("Thumb shift")),
+ icon=None,
+ tooltip=None,
+ sensitive=True,
+ visible=True,
+ state=IBus.PropState.UNCHECKED,
+ sub_props=None))
+ props.get(Engine.__typing_mode).set_state(IBus.PropState.CHECKED)
+
+ i = 0
+ while props.get(i) != None:
+ prop = props.get(i)
+ self.__prop_dict[prop.get_key()] = prop
+ i += 1
+
+ typing_mode_prop.set_sub_props(props)
+ anthy_props.append(typing_mode_prop)
+
+ mode = Engine.__typing_mode
+ mode = 'TypingMode.' + ['Romaji', 'Kana', 'ThumbShift'][mode]
+ self.__typing_mode_activate(mode, IBus.PropState.CHECKED)
+
+ def __set_segment_mode_props(self, anthy_props):
+ if Engine.__segment_mode == None:
+ Engine.__segment_mode = SEGMENT_DEFAULT
+ Engine.__segment_mode = self.__prefs.get_value('common',
+ 'conversion_segment_mode')
+
+ if not self.__prefs.get_value('common', 'show-segment-mode'):
+ return
+
+ symbol = '連'
+ label = _("%(description)s (%(symbol)s)") % \
+ { 'description' : _("Segment mode"), 'symbol' : symbol }
+ segment_mode_prop = IBus.Property(key='SegmentMode',
+ prop_type=IBus.PropType.MENU,
+ label=IBus.Text.new_from_string(label),
+ symbol=IBus.Text.new_from_string(symbol),
+ icon=None,
+ tooltip=IBus.Text.new_from_string(_("Switch conversion mode")),
+ sensitive=True,
+ visible=True,
+ state=IBus.PropState.UNCHECKED,
+ sub_props=None)
+ self.__prop_dict['SegmentMode'] = segment_mode_prop
+
+ props = IBus.PropList()
+ props.append(IBus.Property(key='SegmentMode.Multi',
+ prop_type=IBus.PropType.RADIO,
+ label=IBus.Text.new_from_string(_("Multiple segment")),
+ icon=None,
+ tooltip=None,
+ sensitive=True,
+ visible=True,
+ state=IBus.PropState.UNCHECKED,
+ sub_props=None))
+ props.append(IBus.Property(key='SegmentMode.Single',
+ prop_type=IBus.PropType.RADIO,
+ label=IBus.Text.new_from_string(_("Single segment")),
+ icon=None,
+ tooltip=None,
+ sensitive=True,
+ visible=True,
+ state=IBus.PropState.UNCHECKED,
+ sub_props=None))
+ props.append(IBus.Property(key='SegmentMode.ImmediateMulti',
+ prop_type=IBus.PropType.RADIO,
+ label=IBus.Text.new_from_string(_("Immediate conversion (multiple segment)")),
+ icon=None,
+ tooltip=None,
+ sensitive=True,
+ visible=True,
+ state=IBus.PropState.UNCHECKED,
+ sub_props=None))
+ props.append(IBus.Property(key='SegmentMode.ImmediateSingle',
+ prop_type=IBus.PropType.RADIO,
+ label=IBus.Text.new_from_string(_("Immediate conversion (single segment)")),
+ icon=None,
+ tooltip=None,
+ sensitive=True,
+ visible=True,
+ state=IBus.PropState.UNCHECKED,
+ sub_props=None))
+ props.get(Engine.__segment_mode).set_state(IBus.PropState.CHECKED)
+
+ i = 0
+ while props.get(i) != None:
+ prop = props.get(i)
+ self.__prop_dict[prop.get_key()] = prop
+ i += 1
+
+ segment_mode_prop.set_sub_props(props)
+ anthy_props.append(segment_mode_prop)
+
+ mode = Engine.__segment_mode
+ mode = 'SegmentMode.' + ['Multi', 'Single',
+ 'ImmediateMulti', 'ImmediateSingle'][mode]
+ self.__segment_mode_activate(mode, IBus.PropState.CHECKED)
+
+ def __set_dict_mode_props(self, anthy_props, update_prop=False):
+ if Engine.__dict_mode == None:
+ Engine.__dict_mode = 0
+
+ if not self.__prefs.get_value('common', 'show-dict-mode'):
+ return
+
+ short_label = self.__prefs.get_value('dict/file/embedded',
+ 'short_label')
+ label = _("%(description)s (%(symbol)s)") % \
+ { 'description' : _("Dictionary mode"), 'symbol' : short_label }
+ dict_mode_prop = IBus.Property(key='DictMode',
+ prop_type=IBus.PropType.MENU,
+ label=IBus.Text.new_from_string(label),
+ symbol=IBus.Text.new_from_string(short_label),
+ icon=None,
+ tooltip=IBus.Text.new_from_string(_("Switch dictionary")),
+ sensitive=True,
+ visible=True,
+ state=IBus.PropState.UNCHECKED,
+ sub_props=None)
+ self.__prop_dict['DictMode'] = dict_mode_prop
+ props = IBus.PropList()
+
+ long_label = self.__prefs.get_value('dict/file/embedded',
+ 'long_label')
+ props.append(IBus.Property(key='DictMode.embedded',
+ prop_type=IBus.PropType.RADIO,
+ # if long_label is UTF-8
+ label=IBus.Text.new_from_string(_(long_label)),
+ icon=None,
+ tooltip=None,
+ sensitive=True,
+ visible=True,
+ state=IBus.PropState.UNCHECKED,
+ sub_props=None))
+ for file in self.__prefs.get_value('dict', 'files'):
+ if not self.__link_dict_file(file):
+ continue
+ id = self.__get_dict_id_from_file(file)
+ section = 'dict/file/' + id
+ if not self.__prefs.get_value(section, 'single'):
+ continue
+ key = 'DictMode.' + id
+ long_label = self.__prefs.get_value(section, 'long_label')
+
+ # ibus-config 'value-changed' signal updated dict/files but
+ # not dict/file/new yet.
+ if long_label == None:
+ continue
+
+ if 'is_system' in self.__prefs.keys(section) and \
+ self.__prefs.get_value(section, 'is_system'):
+ uni_long_label = _(long_label)
+ else:
+ uni_long_label = long_label
+ props.append(IBus.Property(key=key,
+ prop_type=IBus.PropType.RADIO,
+ label=IBus.Text.new_from_string(uni_long_label),
+ icon=None,
+ tooltip=None,
+ sensitive=True,
+ visible=True,
+ state=IBus.PropState.UNCHECKED,
+ sub_props=None))
+
+ props.get(Engine.__dict_mode).set_state(IBus.PropState.CHECKED)
+
+ i = 0
+ while props.get(i) != None:
+ prop = props.get(i)
+ self.__prop_dict[prop.get_key()] = prop
+ i += 1
+
+ dict_mode_prop.set_sub_props(props)
+
+ if update_prop:
+ # focus-in event will call register_properties().
+ # Need to switch another IME to update menus on GtkStatusIcon?
+ anthy_props.update_property(dict_mode_prop)
+ else:
+ anthy_props.append(dict_mode_prop)
+
+ prop_name = self.__dict_mode_get_prop_name(Engine.__dict_mode)
+ if prop_name == None:
+ return
+ self.__dict_mode_activate(prop_name,
+ IBus.PropState.CHECKED)
+
+ def __set_dict_config_props(self, anthy_props):
+ if not self.__prefs.get_value('common', 'show-dict-config'):
+ return
+
+ admin_command = self.__prefs.get_value('common', 'dict_admin_command')
+ icon_path = self.__prefs.get_value('common', 'dict_config_icon')
+
+ if not path.exists(admin_command[0]):
+ return
+ label = _("Dictionary - Anthy")
+ if icon_path and path.exists(icon_path):
+ icon = icon_path
+ else:
+ # Translators: "Dic" means 'dictionary', One kanji may be good.
+ label = _("Dic")
+ icon = ''
+
+ dict_prop = IBus.Property(key='setup-dict-kasumi',
+ prop_type=IBus.PropType.MENU,
+ label=IBus.Text.new_from_string(label),
+ icon=icon,
+ tooltip=IBus.Text.new_from_string(_("Configure dictionaries")),
+ sensitive=True,
+ visible=True,
+ state=IBus.PropState.UNCHECKED,
+ sub_props=None)
+ self.__prop_dict['setup-dict-kasumi'] = dict_prop
+
+ props = IBus.PropList()
+ props.append(IBus.Property(key='setup-dict-kasumi-admin',
+ prop_type=IBus.PropType.NORMAL,
+ label=IBus.Text.new_from_string(_("Edit dictionaries")),
+ icon=icon,
+ tooltip=IBus.Text.new_from_string(_("Launch the dictionary tool")),
+ sensitive=True,
+ visible=True,
+ state=IBus.PropState.UNCHECKED,
+ sub_props=None))
+ props.append(IBus.Property(key='setup-dict-kasumi-word',
+ prop_type=IBus.PropType.NORMAL,
+ label=IBus.Text.new_from_string(_("Add words")),
+ icon=icon,
+ tooltip=IBus.Text.new_from_string(_("Add words to the dictionary")),
+ sensitive=True,
+ visible=True,
+ state=IBus.PropState.UNCHECKED,
+ sub_props=None))
+
+ i = 0
+ while props.get(i) != None:
+ prop = props.get(i)
+ self.__prop_dict[prop.get_key()] = prop
+ i += 1
+
+ dict_prop.set_sub_props(props)
+ anthy_props.append(dict_prop)
+
+ def __get_clipboard(self, clipboard, text, data):
+ clipboard_text = clipboard.wait_for_text ()
+
+ if data == CLIPBOARD_RECONVERT:
+ self.__update_reconvert(clipboard_text)
+
+ return clipboard_text
+
+ def __get_single_dict_files(self):
+ files = self.__prefs.get_value('dict', 'files')
+ single_files = []
+ for file in files:
+ if not path.exists(file):
+ continue
+ id = self.__get_dict_id_from_file(file)
+ section = 'dict/file/' + id
+ if self.__prefs.get_value(section, 'single'):
+ single_files.append(file)
+ return single_files
+
+ def __remove_dict_files(self):
+ for file in self.__prefs.get_value('dict', 'files'):
+ self.__remove_dict_file(file)
+
+ def update_preedit(self, string, attrs, cursor_pos, visible):
+ text = IBus.Text.new_from_string(string)
+ i = 0
+ while attrs.get(i) != None:
+ attr = attrs.get(i)
+ text.append_attribute(attr.get_attr_type(),
+ attr.get_value(),
+ attr.get_start_index(),
+ attr.get_end_index())
+ i += 1
+ mode = self.__prefs.get_value('common', 'behavior_on_focus_out')
+ if self.__get_ibus_version() >= 1.003 and mode == 1:
+ self.update_preedit_text_with_mode(text,
+ cursor_pos, visible,
+ IBus.PreeditFocusMode.COMMIT)
+ else:
+ self.update_preedit_text(text,
+ cursor_pos, visible)
+
+ def update_aux_string(self, string, attrs, visible):
+ text = IBus.Text.new_from_string(string)
+ i = 0
+ while attrs.get(i) != None:
+ attr = attrs.get(i)
+ text.append_attribute(attr.get_attr_type(),
+ attr.get_value(),
+ attr.get_start_index(),
+ attr.get_end_index())
+ i += 1
+ self.update_auxiliary_text(text, visible)
+
+ def do_page_up(self):
+ # only process cursor down in convert mode
+ if self.__convert_mode != CONV_MODE_ANTHY:
+ return False
+
+ if not self.__lookup_table.page_up():
+ return False
+
+ index = self.__lookup_table.get_cursor_pos()
+ candidate = self.__lookup_table.get_candidate(index).get_text()
+ self.__segments[self.__cursor_pos] = index, candidate
+ self.__invalidate()
+ return True
+
+ def do_page_down(self):
+ # only process cursor down in convert mode
+ if self.__convert_mode != CONV_MODE_ANTHY:
+ return False
+
+ if not self.__lookup_table.page_down():
+ return False
+
+ index = self.__lookup_table.get_cursor_pos()
+ candidate = self.__lookup_table.get_candidate(index).get_text()
+ self.__segments[self.__cursor_pos] = index, candidate
+ self.__invalidate()
+ return True
+
+ def do_cursor_up(self):
+ # only process cursor down in convert mode
+ # if self.__convert_mode != CONV_MODE_ANTHY:
+ if self.__convert_mode != CONV_MODE_ANTHY and self.__convert_mode != CONV_MODE_PREDICTION:
+ return False
+
+ if not self.__lookup_table.cursor_up():
+ return False
+
+ index = self.__lookup_table.get_cursor_pos()
+ candidate = self.__lookup_table.get_candidate(index).get_text()
+ self.__segments[self.__cursor_pos] = index, candidate
+ self.__invalidate()
+ return True
+
+ def do_cursor_down(self):
+ # only process cursor down in convert mode
+ # if self.__convert_mode != CONV_MODE_ANTHY:
+ if self.__convert_mode != CONV_MODE_ANTHY and self.__convert_mode != CONV_MODE_PREDICTION:
+ return False
+
+ if not self.__lookup_table.cursor_down():
+ return False
+
+ index = self.__lookup_table.get_cursor_pos()
+ candidate = self.__lookup_table.get_candidate(index).get_text()
+ self.__segments[self.__cursor_pos] = index, candidate
+ self.__invalidate()
+ return True
+
+ def do_candidate_clicked(self, index, button, state):
+ if index == 9:
+ keyval = IBus.KEY_0
+ else:
+ keyval = IBus.KEY_1 + index
+ self.__on_key_number(keyval)
+
+ def __commit_string(self, text):
+ self.__reset()
+ self.commit_text(IBus.Text.new_from_string(text))
+ self.__invalidate()
+
+ def __shrink_segment(self, relative_size):
+ self.__context.resize_segment(self.__cursor_pos, relative_size)
+ nr_segments = self.__context.get_nr_segments()
+ del self.__segments[self.__cursor_pos:]
+ for i in range(self.__cursor_pos, nr_segments):
+ buf = self.__context.get_segment(i, 0)
+ text = buf
+ self.__segments.append((0, text))
+ self.__lookup_table_visible = False
+ self.__fill_lookup_table()
+ self.__invalidate()
+ return True
+
+ def do_property_activate(self, prop_name, state):
+
+ if state == IBus.PropState.CHECKED:
+ if prop_name == None:
+ return
+ elif prop_name.startswith('InputMode.'):
+ self.__input_mode_activate(prop_name, state)
+ return
+ elif prop_name.startswith('TypingMode.'):
+ self.__typing_mode_activate(prop_name, state)
+ return
+ elif prop_name.startswith('SegmentMode.'):
+ self.__segment_mode_activate(prop_name, state)
+ return
+ elif prop_name.startswith('DictMode.'):
+ self.__dict_mode_activate(prop_name, state)
+ return
+ else:
+ if prop_name == 'setup':
+ self.__start_setup()
+ elif prop_name == 'setup-dict-kasumi-admin':
+ self.__start_dict_admin()
+ elif prop_name == 'setup-dict-kasumi-word':
+ self.__start_add_word()
+ else:
+ self.__prop_dict[prop_name].set_state(state)
+ if prop_name == 'DictMode':
+ sub_name = self.__dict_mode_get_prop_name(self.__dict_mode)
+ if sub_name == None:
+ return
+ self.__dict_mode_activate(sub_name,
+ IBus.PropState.CHECKED)
+
+ def __input_mode_activate(self, prop_name, state):
+ input_modes = {
+ 'InputMode.Hiragana' : (INPUT_MODE_HIRAGANA, 'あ'),
+ 'InputMode.Katakana' : (INPUT_MODE_KATAKANA, 'ア'),
+ 'InputMode.HalfWidthKatakana' : (INPUT_MODE_HALF_WIDTH_KATAKANA, '_ア'),
+ 'InputMode.Latin' : (INPUT_MODE_LATIN, '_A'),
+ 'InputMode.WideLatin' : (INPUT_MODE_WIDE_LATIN, 'A'),
+ }
+
+ if prop_name not in input_modes:
+ printerr('Unknown prop_name = %s' % prop_name)
+ return
+ self.__prop_dict[prop_name].set_state(state)
+ self.update_property(self.__prop_dict[prop_name])
+
+ mode, symbol = input_modes[prop_name]
+
+ label = _("%(description)s (%(symbol)s)") % \
+ { 'description' : _("Input mode"), 'symbol' : symbol }
+ Engine.__input_mode = mode
+ prop = self.__prop_dict['InputMode']
+ prop.set_symbol(IBus.Text.new_from_string(symbol))
+ prop.set_label(IBus.Text.new_from_string(label))
+ self.update_property(prop)
+
+ self.__reset()
+ self.__invalidate()
+
+ def __typing_mode_activate(self, prop_name, state):
+ typing_modes = {
+ 'TypingMode.Romaji' : (jastring.TYPING_MODE_ROMAJI, 'R'),
+ 'TypingMode.Kana' : (jastring.TYPING_MODE_KANA, 'か'),
+ 'TypingMode.ThumbShift' : (jastring.TYPING_MODE_THUMB_SHIFT, '親'),
+ }
+
+ if prop_name not in typing_modes:
+ printerr('Unknown prop_name = %s' % prop_name)
+ return
+ self.__prop_dict[prop_name].set_state(state)
+ self.update_property(self.__prop_dict[prop_name])
+ if prop_name == 'TypingMode.ThumbShift':
+ self._reset_thumb()
+
+ mode, symbol = typing_modes[prop_name]
+
+ label = _("%(description)s (%(symbol)s)") % \
+ { 'description' : _("Typing method"), 'symbol' : symbol }
+ Engine.__typing_mode = mode
+ prop = self.__prop_dict['TypingMode']
+ prop.set_symbol(IBus.Text.new_from_string(symbol))
+ prop.set_label(IBus.Text.new_from_string(label))
+ self.update_property(prop)
+
+ self.__reset()
+ self.__invalidate()
+
+ def __refresh_typing_mode_property(self):
+ if 'TypingMode' not in self.__prop_dict:
+ return
+
+ prop = self.__prop_dict['TypingMode']
+ modes = {
+ jastring.TYPING_MODE_ROMAJI : ('TypingMode.Romaji', 'R'),
+ jastring.TYPING_MODE_KANA : ('TypingMode.Kana', 'か'),
+ jastring.TYPING_MODE_THUMB_SHIFT : ('TypingMode.ThumbShift', '親'),
+ }
+ prop_name, symbol = modes.get(Engine.__typing_mode, (None, None))
+ if prop_name == None or symbol == None:
+ return
+ label = _("%(description)s (%(symbol)s)") % \
+ { 'description' : _("Typing method"), 'symbol' : symbol }
+ _prop = self.__prop_dict[prop_name]
+ _prop.set_state(IBus.PropState.CHECKED)
+ self.update_property(_prop)
+ prop.set_symbol(IBus.Text.new_from_string(symbol))
+ prop.set_label(IBus.Text.new_from_string(label))
+ self.update_property(prop)
+
+ def __segment_mode_activate(self, prop_name, state):
+ segment_modes = {
+ 'SegmentMode.Multi' : (SEGMENT_DEFAULT, '連'),
+ 'SegmentMode.Single' : (SEGMENT_SINGLE, '単'),
+ 'SegmentMode.ImmediateMulti' : (SEGMENT_IMMEDIATE, '逐|連'),
+ 'SegmentMode.ImmediateSingle' :
+ (SEGMENT_IMMEDIATE | SEGMENT_SINGLE, '逐|単'),
+ }
+
+ if prop_name not in segment_modes:
+ printerr('Unknown prop_name = %s' % prop_name)
+ return
+ self.__prop_dict[prop_name].set_state(state)
+ self.update_property(self.__prop_dict[prop_name])
+
+ mode, symbol = segment_modes[prop_name]
+
+ label = _("%(description)s (%(symbol)s)") % \
+ { 'description' : _("Segment mode"), 'symbol' : symbol }
+ Engine.__segment_mode = mode
+ prop = self.__prop_dict['SegmentMode']
+ prop.set_symbol(IBus.Text.new_from_string(symbol))
+ prop.set_label(IBus.Text.new_from_string(label))
+ self.update_property(prop)
+
+ self.__reset()
+ self.__invalidate()
+
+ def __dict_mode_get_prop_name(self, mode):
+ if mode == 0:
+ id = 'embedded'
+ else:
+ single_files = self.__get_single_dict_files()
+ file = single_files[mode - 1]
+ id = self.__get_dict_id_from_file(file)
+ return 'DictMode.' + id
+
+ def __dict_mode_activate(self, prop_name, state):
+ if prop_name not in list(self.__prop_dict.keys()):
+ # The prop_name is added. Need to restart.
+ return
+ i = prop_name.find('.')
+ if i < 0:
+ return
+ # The id is already quoted.
+ id = prop_name[i + 1:]
+
+ file = None
+ single_files = self.__get_single_dict_files()
+
+ if id == 'embedded':
+ pass
+ else:
+ found = False
+ for file in single_files:
+ if id == self.__get_quoted_id(file):
+ found = True
+ break
+ if found == False:
+ return
+
+ if id == 'embedded':
+ dict_name = 'default'
+ Engine.__dict_mode = 0
+ else:
+ if file not in single_files:
+ printerr('Index error', file, single_files)
+ return
+ dict_name = 'ibus__' + id
+ Engine.__dict_mode = single_files.index(file) + 1
+ self.__prop_dict[prop_name].set_state(state)
+ self.update_property(self.__prop_dict[prop_name])
+ self.__context.init_personality()
+ # dict_name is unicode but the argument is str.
+ self.__context.do_set_personality(str(dict_name))
+
+ prop = self.__prop_dict['DictMode']
+ section = 'dict/file/' + id
+ symbol = self.__prefs.get_value(section, 'short_label')
+ label = _("%(description)s (%(symbol)s)") % \
+ { 'description' : _("Dictionary mode"), 'symbol' : symbol }
+ prop.set_symbol(IBus.Text.new_from_string(symbol))
+ prop.set_label(IBus.Text.new_from_string(label))
+ self.update_property(prop)
+
+ def __argb(self, a, r, g, b):
+ return ((a & 0xff)<<24) + ((r & 0xff) << 16) + ((g & 0xff) << 8) + (b & 0xff)
+
+ def __rgb(self, r, g, b):
+ return self.__argb(255, r, g, b)
+
+ def do_focus_in(self):
+ self.register_properties(self.__prop_list)
+ self.__refresh_typing_mode_property()
+ mode = self.__prefs.get_value('common', 'behavior_on_focus_out')
+ if mode == 2:
+ self.__update_input_chars()
+# self.__reset()
+# self.__invalidate()
+ size = self.__prefs.get_value('common', 'page_size')
+ if size != self.__lookup_table.get_page_size():
+ self.__lookup_table.set_page_size(size)
+
+ def do_focus_out(self):
+ if self.__has_input_purpose:
+ self.__input_purpose = 0
+ mode = self.__prefs.get_value('common', 'behavior_on_focus_out')
+ if mode == 0 or mode == 1:
+ self.__reset()
+ self.__invalidate()
+
+ def do_set_content_type(self, purpose, hints):
+ if self.__has_input_purpose:
+ self.__input_purpose = purpose
+
+ def do_disable(self):
+ self.__reset()
+ self.__invalidate()
+
+ def do_reset(self):
+ self.__reset()
+ self.__invalidate()
+
+ def __destroy(self, obj):
+ if self.__idle_id != 0:
+ GLib.source_remove(self.__idle_id)
+ self.__idle_id = 0
+ # It seems do_destroy() is called when launch_engine() is called.
+ #self.__remove_dict_files()
+ # It seems super.destroy() does not unref the engine.
+
+ def __join_all_segments(self):
+ while True:
+ nr_segments = self.__context.get_nr_segments()
+ seg = nr_segments - self.__cursor_pos
+
+ if seg > 1:
+ self.__context.resize_segment(self.__cursor_pos, 1)
+ else:
+ break
+
+ def __normalize_preedit(self, preedit):
+ if not self.__is_utf8:
+ return preedit
+ for key in list(romaji_normalize_rule.keys()):
+ if preedit.find(key) >= 0:
+ for value in romaji_normalize_rule[key]:
+ preedit = preedit.replace(key, value)
+ return preedit
+
+ # begine convert
+ def __begin_anthy_convert(self):
+ if Engine.__segment_mode & SEGMENT_IMMEDIATE:
+ self.__end_anthy_convert()
+ if self.__convert_mode == CONV_MODE_ANTHY:
+ return
+ self.__convert_mode = CONV_MODE_ANTHY
+
+# text, cursor = self.__preedit_ja_string.get_hiragana()
+ text, cursor = self.__preedit_ja_string.get_hiragana(True)
+
+ text = self.__normalize_preedit(text)
+ self.__context.set_string(text)
+ if Engine.__segment_mode & SEGMENT_SINGLE:
+ self.__join_all_segments()
+ nr_segments = self.__context.get_nr_segments()
+
+ for i in range(0, nr_segments):
+ buf = self.__context.get_segment(i, 0)
+ text = buf
+ self.__segments.append((0, text))
+
+ if Engine.__segment_mode & SEGMENT_IMMEDIATE:
+ self.__cursor_pos = nr_segments - 1
+ else:
+ self.__cursor_pos = 0
+ self.__fill_lookup_table()
+ self.__lookup_table_visible = False
+
+ def __end_anthy_convert(self):
+ if self.__convert_mode == CONV_MODE_OFF:
+ return
+
+ self.__convert_mode = CONV_MODE_OFF
+ self.__convert_chars = ''
+ self.__segments = list()
+ self.__cursor_pos = 0
+ self.__lookup_table.clear()
+ self.__lookup_table_visible = False
+
+ def __end_convert(self):
+ self.__end_anthy_convert()
+
+ # test case 'verudhi' can show U+3046 + U+309B and U+3094
+ def __candidate_cb(self, candidate):
+ if not self.__is_utf8:
+ return
+ for key in list(romaji_utf8_rule.keys()):
+ if candidate.find(key) >= 0:
+ for value in romaji_utf8_rule[key]:
+ candidate = candidate.replace(key, value)
+ self.__lookup_table.append_candidate(IBus.Text.new_from_string(candidate))
+
+ def __fill_lookup_table(self):
+ if self.__convert_mode == CONV_MODE_PREDICTION:
+ nr_predictions = self.__context.get_nr_predictions()
+
+ # fill lookup_table
+ self.__lookup_table.clear()
+ for i in range(0, seg_stat.nr_predictions):
+ buf = self.__context.get_prediction(i)
+ candidate = buf
+ self.__lookup_table.append_candidate(IBus.Text.new_from_string(candidate))
+ self.__candidate_cb(candidate)
+ return
+
+ # get segment stat
+ nr_candidates = self.__context.get_nr_candidates(self.__cursor_pos)
+
+ # fill lookup_table
+ self.__lookup_table.clear()
+ for i in range(0, nr_candidates):
+ buf = self.__context.get_segment(self.__cursor_pos, i)
+ candidate = buf
+ self.__lookup_table.append_candidate(IBus.Text.new_from_string(candidate))
+ self.__candidate_cb(candidate)
+
+
+ def __invalidate(self):
+ if self.__idle_id != 0:
+ return
+ self.__idle_id = GLib.idle_add(self.__update,
+ priority = GLib.PRIORITY_LOW)
+
+# def __get_preedit(self):
+ def __get_preedit(self, commit=False):
+ if Engine.__input_mode == INPUT_MODE_HIRAGANA:
+# text, cursor = self.__preedit_ja_string.get_hiragana()
+ text, cursor = self.__preedit_ja_string.get_hiragana(commit)
+ elif Engine.__input_mode == INPUT_MODE_KATAKANA:
+# text, cursor = self.__preedit_ja_string.get_katakana()
+ text, cursor = self.__preedit_ja_string.get_katakana(commit)
+ elif Engine.__input_mode == INPUT_MODE_HALF_WIDTH_KATAKANA:
+# text, cursor = self.__preedit_ja_string.get_half_width_katakana()
+ text, cursor = self.__preedit_ja_string.get_half_width_katakana(commit)
+ else:
+ text, cursor = '', 0
+ return text, cursor
+
+ def __update_input_chars(self):
+ text, cursor = self.__get_preedit()
+ attrs = IBus.AttrList()
+ attrs.append(IBus.attr_underline_new(
+ IBus.AttrUnderline.SINGLE, 0,
+ len(text)))
+
+ self.update_preedit(text,
+ attrs, cursor, not self.__preedit_ja_string.is_empty())
+ self.update_aux_string('', IBus.AttrList(), False)
+ self.update_lookup_table(self.__lookup_table,
+ self.__lookup_table_visible)
+
+ def __update_convert_chars(self):
+# if self.__convert_mode == CONV_MODE_ANTHY:
+ if self.__convert_mode == CONV_MODE_ANTHY or self.__convert_mode == CONV_MODE_PREDICTION:
+ self.__update_anthy_convert_chars()
+ return
+ if self.__convert_mode == CONV_MODE_HIRAGANA:
+# text, cursor = self.__preedit_ja_string.get_hiragana()
+ text, cursor = self.__preedit_ja_string.get_hiragana(True)
+ elif self.__convert_mode == CONV_MODE_KATAKANA:
+# text, cursor = self.__preedit_ja_string.get_katakana()
+ text, cursor = self.__preedit_ja_string.get_katakana(True)
+ elif self.__convert_mode == CONV_MODE_HALF_WIDTH_KATAKANA:
+# text, cursor = self.__preedit_ja_string.get_half_width_katakana()
+ text, cursor = self.__preedit_ja_string.get_half_width_katakana(True)
+ elif self.__convert_mode == CONV_MODE_LATIN_0:
+ text, cursor = self.__preedit_ja_string.get_latin()
+ if text == text.lower():
+ self.__convert_mode = CONV_MODE_LATIN_1
+ elif self.__convert_mode == CONV_MODE_LATIN_1:
+ text, cursor = self.__preedit_ja_string.get_latin()
+ text = text.lower()
+ elif self.__convert_mode == CONV_MODE_LATIN_2:
+ text, cursor = self.__preedit_ja_string.get_latin()
+ text = text.upper()
+ elif self.__convert_mode == CONV_MODE_LATIN_3:
+ text, cursor = self.__preedit_ja_string.get_latin()
+ text = text.capitalize()
+ elif self.__convert_mode == CONV_MODE_WIDE_LATIN_0:
+ text, cursor = self.__preedit_ja_string.get_wide_latin()
+ if text == text.lower():
+ self.__convert_mode = CONV_MODE_WIDE_LATIN_1
+ elif self.__convert_mode == CONV_MODE_WIDE_LATIN_1:
+ text, cursor = self.__preedit_ja_string.get_wide_latin()
+ text = text.lower()
+ elif self.__convert_mode == CONV_MODE_WIDE_LATIN_2:
+ text, cursor = self.__preedit_ja_string.get_wide_latin()
+ text = text.upper()
+ elif self.__convert_mode == CONV_MODE_WIDE_LATIN_3:
+ text, cursor = self.__preedit_ja_string.get_wide_latin()
+ text = text.capitalize()
+ self.__convert_chars = text
+ attrs = IBus.AttrList()
+ attrs.append(IBus.attr_underline_new(
+ IBus.AttrUnderline.SINGLE, 0, len(text)))
+ attrs.append(IBus.attr_background_new(self.__rgb(200, 200, 240),
+ 0, len(text)))
+ attrs.append(IBus.attr_foreground_new(self.__rgb(0, 0, 0),
+ 0, len(text)))
+ self.update_preedit(text, attrs, len(text), True)
+
+ self.update_aux_string('',
+ IBus.AttrList(), self.__lookup_table_visible)
+ self.update_lookup_table(self.__lookup_table,
+ self.__lookup_table_visible)
+
+ def __update_anthy_convert_chars(self):
+ self.__convert_chars = ''
+ pos = 0
+ for i, (seg_index, text) in enumerate(self.__segments):
+ self.__convert_chars += text
+ if i < self.__cursor_pos:
+ pos += len(text)
+ attrs = IBus.AttrList()
+ attrs.append(IBus.attr_underline_new(
+ IBus.AttrUnderline.SINGLE, 0, len(self.__convert_chars)))
+ attrs.append(IBus.attr_background_new(self.__rgb(200, 200, 240),
+ pos, pos + len(self.__segments[self.__cursor_pos][1])))
+ attrs.append(IBus.attr_foreground_new(self.__rgb(0, 0, 0),
+ pos, pos + len(self.__segments[self.__cursor_pos][1])))
+ self.update_preedit(self.__convert_chars, attrs, pos, True)
+ aux_string = '( %d / %d )' % (self.__lookup_table.get_cursor_pos() + 1, self.__lookup_table.get_number_of_candidates())
+ self.update_aux_string(aux_string,
+ IBus.AttrList(), self.__lookup_table_visible)
+ self.update_lookup_table(self.__lookup_table,
+ self.__lookup_table_visible)
+
+ def __update(self):
+ if self.__convert_mode == CONV_MODE_OFF:
+ self.__update_input_chars()
+ else:
+ self.__update_convert_chars()
+ self.__idle_id = 0
+
+ def __on_key_return(self):
+ if self.__preedit_ja_string.is_empty():
+ return False
+
+ if self.__convert_mode == CONV_MODE_OFF:
+# text, cursor = self.__get_preedit()
+ text, cursor = self.__get_preedit(True)
+ self.__commit_string(text)
+ elif self.__convert_mode == CONV_MODE_ANTHY:
+ for i, (seg_index, text) in enumerate(self.__segments):
+ self.__context.commit_segment(i, seg_index)
+ self.__commit_string(self.__convert_chars)
+ elif self.__convert_mode == CONV_MODE_PREDICTION:
+ self.__context.commit_prediction(self.__segments[0][0])
+ self.__commit_string(self.__convert_chars)
+ else:
+ self.__commit_string(self.__convert_chars)
+
+ return True
+
+ def __on_key_escape(self):
+ if self.__preedit_ja_string.is_empty():
+ return False
+ self.__reset()
+ self.__invalidate()
+ return True
+
+ def __on_key_back_space(self):
+ if self.__preedit_ja_string.is_empty():
+ return False
+
+ if self.__convert_mode != CONV_MODE_OFF:
+ if self.__lookup_table_visible:
+ if self.__lookup_table.get_number_of_candidates() > 0:
+ self.__lookup_table.set_cursor_pos(0)
+ candidate = self.__lookup_table.get_candidate(0).get_text()
+ self.__segments[self.__cursor_pos] = 0, candidate
+ self.__lookup_table_visible = False
+ elif self.__segments[self.__cursor_pos][0] != \
+ NTH_UNCONVERTED_CANDIDATE:
+ buf = self.__context.get_segment(self.__cursor_pos,
+ NTH_UNCONVERTED_CANDIDATE)
+ self.__segments[self.__cursor_pos] = \
+ NTH_UNCONVERTED_CANDIDATE, buf
+ #elif self._chk_mode('25'):
+ '''
+ # FIXME: Delete the last char in the active segment.
+ #
+ # If we are able to delete a char in the active segment,
+ # we also should be able to add a char in the active segment.
+ # Currently plain preedit, no segment mode, i.e.
+ # using self.__preedit_ja_string, can delete or add a char
+ # but anthy active segoment mode, i.e.
+ # using self.__segments, can not delete or add a char.
+ # Deleting a char could be easy here but adding a char is
+ # difficult because we need to update both self.__segments
+ # and self.__preedit_ja_string but self.__preedit_ja_string
+ # has no segment. To convert self.__segments to
+ # self.__preedit_ja_string, we may use the reconvert mode
+ # but no idea to convert keyvals to hiragana
+ # in self__on_key_common() with multiple key typings.
+
+ # Delete a char in the active segment
+ all_text = ''
+ nr_segments = self.__context.get_nr_segments()
+ for i in xrange(0, nr_segments):
+ buf = self.__context.get_segment(i,
+ NTH_UNCONVERTED_CANDIDATE)
+ text = buf
+ if i == self.__cursor_pos and len(text) > 0:
+ text = text[:len(text) - 1]
+ all_text += text
+
+ if all_text == '':
+ return
+
+ # Set self.__preedit_ja_string by anthy context.
+ self.__preedit_ja_string = jastring.JaString(Engine.__typing_mode,
+ self.__latin_with_shift)
+ self.__convert_chars = self.__normalize_preedit(all_text)
+ for i in xrange(0, len(self.__convert_chars)):
+ keyval = self.__convert_chars[i]
+ self.__preedit_ja_string.insert(chr(ord(keyval)))
+ self.__context.set_string(self.__convert_chars)
+
+ # Set self.__segments by anty context
+ # for editable self.__segments,
+ # save NTH_UNCONVERTED_CANDIDATE
+ nr_segments = self.__context.get_nr_segments()
+ if self.__cursor_pos >= nr_segments and \
+ nr_segments > 0:
+ self.__cursor_pos = nr_segments - 1
+ for i in xrange(self.__cursor_pos, nr_segments):
+ if i == self.__cursor_pos:
+ index = NTH_UNCONVERTED_CANDIDATE
+ else:
+ index = 0
+ buf = self.__context.get_segment(i,
+ index)
+ text = buf
+ self.__segments[i] = index, text
+
+ # Update self.__lookup_table
+ self.__fill_lookup_table()
+ '''
+ else:
+ self.__end_convert()
+ else:
+ self.__preedit_ja_string.remove_before()
+
+ self.__invalidate()
+ return True
+
+ def __on_key_delete(self):
+ if self.__preedit_ja_string.is_empty():
+ return False
+
+ if self.__convert_mode != CONV_MODE_OFF:
+ self.__end_convert()
+ else:
+ self.__preedit_ja_string.remove_after()
+
+ self.__invalidate()
+ return True
+
+ '''def __on_key_hiragana_katakana(self):
+ if self.__convert_mode == CONV_MODE_ANTHY:
+ self.__end_anthy_convert()
+
+ if Engine.__input_mode >= INPUT_MODE_HIRAGANA and \
+ Engine.__input_mode < INPUT_MODE_HALF_WIDTH_KATAKANA:
+ Engine.__input_mode += 1
+ else:
+ Engine.__input_mode = INPUT_MODE_HIRAGANA
+
+ modes = { INPUT_MODE_HIRAGANA: 'あ',
+ INPUT_MODE_KATAKANA: 'ア',
+ INPUT_MODE_HALF_WIDTH_KATAKANA: '_ア' }
+
+ prop = self.__prop_dict[u'InputMode']
+ label = modes[Engine.__input_mode]
+ prop.set_label(IBus.Text.new_from_string(label))
+ self.update_property(prop)
+
+ self.__invalidate()
+ return True'''
+
+ '''def __on_key_muhenka(self):
+ if self.__preedit_ja_string.is_empty():
+ return False
+
+ if self.__convert_mode == CONV_MODE_ANTHY:
+ self.__end_anthy_convert()
+
+ new_mode = CONV_MODE_HIRAGANA
+ if self.__convert_mode < CONV_MODE_WIDE_LATIN_3 and \
+ self.__convert_mode >= CONV_MODE_HIRAGANA :
+ self.__convert_mode += 1
+ else:
+ self.__convert_mode = CONV_MODE_HIRAGANA
+
+ self.__invalidate()
+
+ return True'''
+
+ '''def __on_key_henkan(self):
+ if self.__preedit_ja_string.is_empty():
+ return False
+ if self.__convert_mode != CONV_MODE_ANTHY:
+ self.__begin_anthy_convert()
+ self.__invalidate()
+ elif self.__convert_mode == CONV_MODE_ANTHY:
+ self.__lookup_table_visible = True
+ self.do_cursor_down()
+ return True'''
+
+ '''def __on_key_space(self, wide=False):
+ if Engine.__input_mode == INPUT_MODE_WIDE_LATIN or wide:
+ # Input Wide space U+3000
+ wide_char = symbol_rule[chr(IBus.KEY_space)]
+ self.__commit_string(wide_char)
+ return True
+
+ if self.__preedit_ja_string.is_empty():
+ if Engine.__input_mode in (INPUT_MODE_HIRAGANA, INPUT_MODE_KATAKANA):
+ # Input Wide space U+3000
+ wide_char = symbol_rule[chr(IBus.KEY_space)]
+ self.__commit_string(wide_char)
+ return True
+ else:
+ # Input Half space U+0020
+ self.__commit_string(chr(IBus.KEY_space))
+ return True
+
+ if self.__convert_mode != CONV_MODE_ANTHY:
+ self.__begin_anthy_convert()
+ self.__invalidate()
+ elif self.__convert_mode == CONV_MODE_ANTHY:
+ self.__lookup_table_visible = True
+ self.do_cursor_down()
+ return True'''
+
+ def __on_key_up(self):
+ if self.__preedit_ja_string.is_empty():
+ return False
+ self.__lookup_table_visible = True
+ self.do_cursor_up()
+ return True
+
+ def __on_key_down(self):
+ if self.__preedit_ja_string.is_empty():
+ return False
+ self.__lookup_table_visible = True
+ self.do_cursor_down()
+ return True
+
+ def __on_key_page_up(self):
+ if self.__preedit_ja_string.is_empty():
+ return False
+ if self.__lookup_table_visible == True:
+ self.do_page_up()
+ return True
+
+ def __on_key_page_down(self):
+ if self.__preedit_ja_string.is_empty():
+ return False
+ if self.__lookup_table_visible == True:
+ self.do_page_down()
+ return True
+
+ '''def __on_key_left(self):
+ if self.__preedit_ja_string.is_empty():
+ return False
+
+ if self.__convert_mode == CONV_MODE_OFF:
+ self.__preedit_ja_string.move_cursor(-1)
+ self.__invalidate()
+ return True
+
+ if self.__convert_mode != CONV_MODE_ANTHY:
+ return True
+
+ if self.__cursor_pos == 0:
+ return True
+ self.__cursor_pos -= 1
+ self.__lookup_table_visible = False
+ self.__fill_lookup_table()
+ self.__invalidate()
+ return True'''
+
+ def __on_key_right(self):
+ if self.__preedit_ja_string.is_empty():
+ return False
+
+ if self.__convert_mode == CONV_MODE_OFF:
+ self.__preedit_ja_string.move_cursor(1)
+ self.__invalidate()
+ return True
+
+ if self.__convert_mode != CONV_MODE_ANTHY:
+ return True
+
+ if self.__cursor_pos + 1 >= len(self.__segments):
+ return True
+
+ self.__cursor_pos += 1
+ self.__lookup_table_visible = False
+ self.__fill_lookup_table()
+ self.__invalidate()
+ return True
+
+ def __on_key_number(self, keyval):
+ if self.__convert_mode != CONV_MODE_ANTHY:
+ return False
+ if not self.__lookup_table_visible:
+ return False
+
+ if keyval == IBus.KEY_0:
+ keyval = IBus.KEY_9 + 1
+ index = keyval - IBus.KEY_1
+
+ return self.__on_candidate_index_in_page(index)
+
+ def __on_key_conv(self, mode):
+ if self.__preedit_ja_string.is_empty():
+ return False
+
+ if self.__convert_mode == CONV_MODE_ANTHY:
+ self.__end_anthy_convert()
+
+ if mode == 0 or mode == 1:
+ if self.__convert_mode == CONV_MODE_HIRAGANA + mode:
+ return True
+ self.__convert_mode = CONV_MODE_HIRAGANA + mode
+ elif mode == 2:
+ if self.__convert_mode == CONV_MODE_HALF_WIDTH_KATAKANA:
+ return True
+ self.__convert_mode = CONV_MODE_HALF_WIDTH_KATAKANA
+ elif mode == 3:
+ if CONV_MODE_WIDE_LATIN_0 <= self.__convert_mode <= CONV_MODE_WIDE_LATIN_3:
+ self.__convert_mode += 1
+ if self.__convert_mode > CONV_MODE_WIDE_LATIN_3:
+ self.__convert_mode = CONV_MODE_WIDE_LATIN_1
+ else:
+ self.__convert_mode = CONV_MODE_WIDE_LATIN_0
+ elif mode == 4:
+ if CONV_MODE_LATIN_0 <= self.__convert_mode <= CONV_MODE_LATIN_3:
+ self.__convert_mode += 1
+ if self.__convert_mode > CONV_MODE_LATIN_3:
+ self.__convert_mode = CONV_MODE_LATIN_1
+ else:
+ self.__convert_mode = CONV_MODE_LATIN_0
+ else:
+ printerr('Unkown convert mode (%d)!' % mode)
+ return False
+ self.__invalidate()
+ return True
+
+ def __on_key_common(self, keyval, state=0):
+
+ # If use-system-layout is FALSE in ibus 1.4.y or lower,
+ # ibus converts the keymap and ibus-anthy needed to use
+ # self.__commit_string
+ # ibus 1.5.y uses XKB directly so Latin mode can return FALSE.
+ if Engine.__input_mode == INPUT_MODE_LATIN:
+ return False
+
+ elif Engine.__input_mode == INPUT_MODE_WIDE_LATIN:
+ # Input Wide Latin chars
+ char = chr(keyval)
+ wide_char = None#symbol_rule.get(char, None)
+ if wide_char == None:
+ wide_char = unichar_half_to_full(char)
+ self.__commit_string(wide_char)
+ return True
+
+ # Input Japanese
+ if Engine.__segment_mode & SEGMENT_IMMEDIATE:
+ # Commit nothing
+ pass
+ elif self.__convert_mode == CONV_MODE_ANTHY:
+ for i, (seg_index, text) in enumerate(self.__segments):
+ self.__context.commit_segment(i, seg_index)
+ self.__commit_string(self.__convert_chars)
+ elif self.__convert_mode != CONV_MODE_OFF:
+ self.__commit_string(self.__convert_chars)
+
+ # 'n' + '\'' == 'nn' in romaji
+ if (keyval >= ord('A') and keyval <= ord('Z')) or \
+ (keyval >= ord('a') and keyval <= ord('z')):
+ shift = (state & IBus.ModifierType.SHIFT_MASK) != 0
+ else:
+ shift = False
+ self.__preedit_ja_string.set_shift(shift)
+ self.__preedit_ja_string.insert(chr(keyval))
+ if Engine.__segment_mode & SEGMENT_IMMEDIATE:
+ self.__begin_anthy_convert()
+ self.__invalidate()
+ return True
+
+#=======================================================================
+ @classmethod
+ def CONFIG_RELOADED(cls, bus):
+ if config.DEBUG:
+ print('RELOADED')
+ if not cls.__prefs:
+ cls.__prefs = AnthyPrefs(bus)
+ cls._init_prefs()
+
+ cls.__keybind = cls._mk_keybind()
+
+ jastring.JaString.SET_PREFS(cls.__prefs)
+
+ @classmethod
+ def CONFIG_VALUE_CHANGED(cls, bus, section, name, variant):
+ if config.DEBUG:
+ print('VALUE_CHAMGED =', section, name, variant)
+
+ if not section.startswith('engine/anthy'):
+ # This value is used for IBus.config.set_value only.
+ return
+
+ # The key was deleted by dconf.
+ # test case: update /desktop/ibus/engine/anthy/thumb/ls
+ # and reset the key with dconf direclty.
+ if variant.get_type_string() == '()':
+ cls.__prefs.undo_item(section, name)
+ return
+
+ value = cls.__prefs.variant_to_value(variant)
+ base_sec = section[len(cls.__prefs._prefix) + 1:]
+ sec = cls._get_shortcut_type()
+ if base_sec == sec:
+ cmd = '_Engine__cmd_' + name
+ old = cls.__prefs.get_value(sec, name)
+ value = value if value != [''] else []
+ for s in set(old).difference(value):
+ cls.__keybind.get(cls._s_to_key(s), []).remove(cmd)
+
+ keys = cls.__prefs.keys(sec)
+ for s in set(value).difference(old):
+ cls.__keybind.setdefault(cls._s_to_key(s), []).append(cmd)
+ cls.__keybind.get(cls._s_to_key(s)).sort(
+ key = lambda a: keys.index(a[13:]))
+ cls.__prefs.set_value(sec, name, value)
+ elif base_sec == 'common':
+ cls.__prefs.set_value(base_sec, name, value)
+ if name == 'shortcut_type':
+ cls.__keybind = cls._mk_keybind()
+ if name == 'latin_with_shift':
+ cls.__latin_with_shift = value
+ jastring.JaString.RESET(cls.__prefs, base_sec, name, value)
+ elif base_sec.startswith('kana_typing_rule'):
+ jastring.JaString.RESET(cls.__prefs, base_sec, name, value)
+
+ @classmethod
+ def _init_prefs(cls):
+ prefs = cls.__prefs
+ value = prefs.get_value('common', 'latin_with_shift')
+ cls.__latin_with_shift = value
+
+ @classmethod
+ def _mk_keybind(cls):
+ keybind = {}
+ sec = cls._get_shortcut_type()
+ for k in cls.__prefs.keys(sec):
+ cmd = '_Engine__cmd_' + k
+ for s in cls.__prefs.get_value(sec, k):
+ keybind.setdefault(cls._s_to_key(s), []).append(cmd)
+ return keybind
+
+ @classmethod
+ def _get_shortcut_type(cls):
+ try:
+ t = 'shortcut/' + cls.__prefs.get_value('common', 'shortcut_type')
+ except:
+ t = 'shortcut/default'
+ return t
+
+ @classmethod
+ def _s_to_key(cls, s):
+ keyval = IBus.keyval_from_name(s.split('+')[-1])
+ s = s.lower()
+ state = ('shift+' in s and IBus.ModifierType.SHIFT_MASK or 0) | (
+ 'ctrl+' in s and IBus.ModifierType.CONTROL_MASK or 0) | (
+ 'alt+' in s and IBus.ModifierType.MOD1_MASK or 0)
+ return cls._mk_key(keyval, state)
+
+ @classmethod
+ def _reset_thumb(cls):
+ if cls.__thumb == None:
+ import thumb
+ cls.__thumb = thumb.ThumbShiftKeyboard(cls.__prefs)
+
+ else:
+ cls.__thumb.reset()
+
+ @staticmethod
+ def _mk_key(keyval, state):
+ if state & (IBus.ModifierType.CONTROL_MASK | IBus.ModifierType.MOD1_MASK):
+ if keyval < 0xff and \
+ chr(keyval) in '!"#$%^\'()*+,-./:;<=>?@[\]^_`{|}~':
+ state |= IBus.ModifierType.SHIFT_MASK
+ elif IBus.KEY_a <= keyval <= IBus.KEY_z:
+ keyval -= (IBus.KEY_a - IBus.KEY_A)
+
+ return repr([int(state), int(keyval)])
+
+ def __process_key_event(self, obj, keyval, keycode, state):
+ try:
+ return self.__process_key_event_internal2(keyval, keycode, state)
+ except:
+ import traceback
+ traceback.print_exc()
+ return False
+
+ def __process_key_event_thumb(self, keyval, keycode, state):
+ if self.__thumb == None:
+ self._reset_thumb()
+
+ def on_timeout(keyval):
+ if self._MM:
+ insert(self.__thumb.get_char(self._MM)[self._SS])
+ else:
+ cmd_exec([0, RS(), LS()][self._SS])
+ self._H = None
+
+ def start(t):
+ self._H = GLib.timeout_add(t, on_timeout, keyval)
+
+ def stop():
+ if self._H:
+ GLib.source_remove(self._H)
+ self._H = None
+ return True
+ return False
+
+ def insert(keyval):
+ try:
+ self._MM = self._SS = 0
+ ret = self.__on_key_common(ord(keyval))
+ if (keyval in ',.、。' and
+ self.__prefs.get_value('common', 'behavior_on_period')):
+ return self.__cmd_convert(keyval, state)
+ return ret
+ except:
+ pass
+
+ def cmd_exec(keyval, state=0):
+ key = self._mk_key(keyval, state)
+ for cmd in self.__keybind.get(key, []):
+ if config.DEBUG:
+ print('cmd =', cmd)
+ try:
+ if getattr(self, cmd)(keyval, state):
+ return True
+ except:
+ printerr('Unknown command = %s' % cmd)
+ return False
+
+ def RS():
+ return self.__thumb.get_rs()
+
+ def LS():
+ return self.__thumb.get_ls()
+
+ def T1():
+ return self.__thumb.get_t1()
+
+ def T2():
+ return self.__thumb.get_t2()
+
+ state = state & (IBus.ModifierType.SHIFT_MASK |
+ IBus.ModifierType.CONTROL_MASK |
+ IBus.ModifierType.MOD1_MASK |
+ IBus.ModifierType.RELEASE_MASK)
+
+ if keyval in KP_Table and self.__prefs.get_value('common',
+ 'ten_key_mode'):
+ keyval = KP_Table[keyval]
+
+ if state & IBus.ModifierType.RELEASE_MASK:
+ if keyval == self._MM:
+ if stop():
+ insert(self.__thumb.get_char(self._MM)[self._SS])
+ self._MM = 0
+ elif (1 if keyval == RS() else 2) == self._SS:
+ if stop():
+ cmd_exec([0, RS(), LS()][self._SS])
+ self._SS = 0
+ if keyval in [RS(), LS()]:
+ self._RSS = 0
+ elif keyval == self._RMM:
+ self._RMM = 0
+ else:
+ if keyval in [LS(), RS()] and state == 0:
+ if self._SS:
+ stop()
+ cmd_exec([0, RS(), LS()][self._SS])
+ self._SS = 1 if keyval == RS() else 2
+ start(T1())
+ elif self._MM:
+ stop()
+ self._RMM = self._MM
+ self._RSS = 1 if keyval == RS() else 2
+ insert(self.__thumb.get_char(self._MM)[1 if keyval == RS() else 2])
+ else:
+ if self._RSS == (1 if keyval == RS() else 2):
+ if self._RMM:
+ insert(self.__thumb.get_char(self._RMM)[self._RSS])
+ else:
+ self._SS = 1 if keyval == RS() else 2
+ start(T1())
+ elif keyval in self.__thumb.get_chars() and state == 0:
+ if self._MM:
+ stop()
+ insert(self.__thumb.get_char(self._MM)[self._SS])
+ start(T2())
+ self._MM = keyval
+ elif self._SS:
+ stop()
+ self._RMM = keyval
+ self._RSS = self._SS
+ insert(self.__thumb.get_char(keyval)[self._SS])
+ else:
+ if self._RMM == keyval:
+ if self._RSS:
+ insert(self.__thumb.get_char(self._RMM)[self._RSS])
+ else:
+ if cmd_exec(keyval, state):
+ return True
+ start(T2())
+ self._MM = keyval
+ else:
+ if self._MM:
+ stop()
+ insert(self.__thumb.get_char(self._MM)[self._SS])
+ elif self._SS:
+ stop()
+ cmd_exec([0, RS(), LS()][self._SS])
+ if cmd_exec(keyval, state):
+ return True
+ elif 0x21 <= keyval <= 0x7e and state & \
+ (IBus.ModifierType.CONTROL_MASK | IBus.ModifierType.MOD1_MASK) == 0:
+ if state & IBus.ModifierType.SHIFT_MASK:
+ insert(self.__thumb.get_shift_char(keyval, chr(keyval)))
+ elif self._SS == 0:
+ insert(chr(keyval))
+ else:
+ if not self.__preedit_ja_string.is_empty():
+ return True
+ return False
+ return True
+
+ def __process_key_event_internal2(self, keyval, keycode, state):
+ if self.__has_input_purpose and \
+ self.__input_purpose == IBus.InputPurpose.PASSWORD:
+ return False
+
+ if Engine.__typing_mode == jastring.TYPING_MODE_THUMB_SHIFT and \
+ Engine.__input_mode not in [INPUT_MODE_LATIN, INPUT_MODE_WIDE_LATIN]:
+ return self.__process_key_event_thumb(keyval, keycode, state)
+
+ is_press = (state & IBus.ModifierType.RELEASE_MASK) == 0
+
+ state = state & (IBus.ModifierType.SHIFT_MASK |
+ IBus.ModifierType.CONTROL_MASK |
+ IBus.ModifierType.MOD1_MASK)
+
+ # ignore key release events
+ if not is_press:
+ return False
+
+ if keyval in KP_Table and self.__prefs.get_value('common',
+ 'ten_key_mode'):
+ keyval = KP_Table[keyval]
+
+ key = self._mk_key(keyval, state)
+ for cmd in self.__keybind.get(key, []):
+ if config.DEBUG:
+ print('cmd =', cmd)
+ try:
+ if getattr(self, cmd)(keyval, state):
+ return True
+ except:
+ printerr('Unknown command = %s' % cmd)
+
+ # If input mode is not LATIN, eat Ctrl+Shift+u
+ hex_mod_mask = IBus.ModifierType.SHIFT_MASK | \
+ IBus.ModifierType.CONTROL_MASK
+ if Engine.__input_mode != INPUT_MODE_LATIN and \
+ keyval == IBus.KEY_U and \
+ state & hex_mod_mask == hex_mod_mask:
+ return True
+
+ if state & (IBus.ModifierType.CONTROL_MASK | IBus.ModifierType.MOD1_MASK):
+ return False
+
+ if (IBus.KEY_exclam <= keyval <= IBus.KEY_asciitilde or
+ keyval == IBus.KEY_yen):
+ if Engine.__typing_mode == jastring.TYPING_MODE_KANA:
+ if keyval == IBus.KEY_0 and state == IBus.ModifierType.SHIFT_MASK:
+ keyval = IBus.KEY_asciitilde
+ elif keyval == IBus.KEY_backslash and keycode in [132-8, 133-8]:
+ keyval = IBus.KEY_yen
+ ret = self.__on_key_common(keyval, state)
+ if (Engine.__input_mode != INPUT_MODE_LATIN and
+ chr(keyval) in ',.' and
+ self.__prefs.get_value('common', 'behavior_on_period')):
+ return self.__cmd_convert(keyval, state)
+ return ret
+ else:
+ if not self.__preedit_ja_string.is_empty():
+ return True
+ return False
+
+ def _chk_mode(self, mode):
+ if '0' in mode and self.__preedit_ja_string.is_empty():
+ return True
+
+ if self.__convert_mode == CONV_MODE_OFF:
+ if '1' in mode and not self.__preedit_ja_string.is_empty():
+ return True
+ elif self.__convert_mode == CONV_MODE_ANTHY:
+ if '2' in mode and not self.__lookup_table_visible:
+ return True
+ elif self.__convert_mode == CONV_MODE_PREDICTION:
+ if '3' in mode and not self.__lookup_table_visible:
+ return True
+ else:
+ if '4' in mode:
+ return True
+
+ if '5' in mode and self.__lookup_table_visible:
+ return True
+
+ return False
+
+ def __get_quoted_id(self, file):
+ id = file
+ has_mbcs = False
+
+ for i in range(0, len(id)):
+ if ord(id[i]) >= 0x7f:
+ has_mbcs = True
+ break
+ if has_mbcs:
+ id = str(binascii.hexlify(id.encode()), 'ascii')
+
+ if id.find('/') >=0:
+ id = id[id.rindex('/') + 1:]
+ if id.find('.') >=0:
+ id = id[:id.rindex('.')]
+
+ if id.startswith('0x'):
+ id = str(binascii.hexlify(id.encode()), 'ascii')
+ has_mbcs = True
+ if has_mbcs:
+ id = '0x' + id
+ return id
+
+ def __get_dict_id_from_file(self, file):
+ return self.__get_quoted_id(file)
+
+ def __link_dict_file_with_id(self, file, id, link_mode):
+ if id == None:
+ return
+ if link_mode == LINK_DICT_EMBEDDED:
+ directory = get_userhome() + '/.anthy/' + IMPORTED_EMBEDDED_DICT_DIR
+ name = IMPORTED_EMBEDDED_DICT_PREFIX + id
+ elif link_mode == LINK_DICT_SINGLE:
+ directory = get_userhome() + '/.anthy'
+ name = IMPORTED_SINGLE_DICT_PREFIX + id
+ else:
+ return
+ if path.exists(directory):
+ if not path.isdir(directory):
+ printerr(directory + ' is not a directory')
+ return
+ else:
+ os.makedirs(directory, 0o700)
+ backup_dir = os.getcwd()
+ os.chdir(directory)
+ if path.lexists(directory + '/' + name):
+ if path.islink(directory + '/' + name):
+ printerr('Removing ' + name)
+ os.unlink(directory + '/' + name)
+ else:
+ alternate = name + str(os.getpid())
+ printerr('Moving ' + name + ' to ' + alternate)
+ os.rename(name, alternate)
+ os.symlink(file, directory + '/' + name)
+ if backup_dir != None:
+ os.chdir(backup_dir)
+
+ def __remove_dict_file_with_id(self, file, id, link_mode):
+ if id == None:
+ return
+ if link_mode == LINK_DICT_EMBEDDED:
+ directory = get_userhome() + '/.anthy/' + IMPORTED_EMBEDDED_DICT_DIR
+ name = IMPORTED_EMBEDDED_DICT_PREFIX + id
+ elif link_mode == LINK_DICT_SINGLE:
+ directory = get_userhome() + '/.anthy'
+ name = IMPORTED_SINGLE_DICT_PREFIX + id
+ else:
+ return
+ if path.exists(directory):
+ if not path.isdir(directory):
+ printerr(directory + ' is not a directory')
+ return
+ backup_dir = os.getcwd()
+ os.chdir(directory)
+ if path.lexists(directory + '/' + name):
+ os.unlink(directory + '/' + name)
+ if backup_dir != None:
+ os.chdir(backup_dir)
+
+ def __link_dict_file(self, file):
+ if not path.exists(file):
+ printerr(file + ' does not exist')
+ return False
+ id = self.__get_dict_id_from_file(file)
+ section = 'dict/file/' + id
+ if section not in self.__prefs.sections():
+ self.__fetch_dict_values(section)
+ if self.__prefs.get_value(section, 'embed'):
+ self.__link_dict_file_with_id(file, id, LINK_DICT_EMBEDDED)
+ if self.__prefs.get_value(section, 'single'):
+ self.__link_dict_file_with_id(file, id, LINK_DICT_SINGLE)
+ return True
+
+ def __remove_dict_file(self, file):
+ id = self.__get_dict_id_from_file(file)
+ section = 'dict/file/' + id
+ if section not in self.__prefs.sections():
+ self.__fetch_dict_values(section)
+ if self.__prefs.get_value(section, 'embed'):
+ self.__remove_dict_file_with_id(file, id, LINK_DICT_EMBEDDED)
+ if self.__prefs.get_value(section, 'single'):
+ self.__remove_dict_file_with_id(file, id, LINK_DICT_SINGLE)
+
+ def __set_dict_files_value(self, base_sec, name, value):
+ if name == 'files':
+ str_list = []
+ for file in value:
+ str_list.append(self.__prefs.str(file))
+ old_files = self.__prefs.get_value(base_sec, name)
+ for file in old_files:
+ if file in str_list:
+ continue
+ self.__remove_dict_file(file)
+ for file in str_list:
+ if file in old_files:
+ continue
+ self.__link_dict_file(file)
+ self.__prefs.set_value(base_sec, name, str_list)
+ else:
+ self.__prefs.set_value(base_sec, name, value)
+
+ def __fetch_dict_values(self, section):
+ self.__prefs.set_new_section(section)
+ self.__prefs.set_new_key(section, 'short_label')
+ self.__prefs.set_no_key_warning(True)
+ self.__prefs.fetch_item(section, 'short_label')
+ self.__prefs.set_new_key(section, 'long_label')
+ self.__prefs.fetch_item(section, 'long_label')
+ self.__prefs.set_new_key(section, 'embed')
+ self.__prefs.fetch_item(section, 'embed')
+ self.__prefs.set_new_key(section, 'single')
+ self.__prefs.fetch_item(section, 'single')
+ self.__prefs.set_new_key(section, 'reverse')
+ self.__prefs.fetch_item(section, 'reverse')
+ self.__prefs.set_no_key_warning(False)
+
+ def __config_value_changed_cb(self, ibus_config, section, name, variant):
+ if config.DEBUG:
+ print('VALUE_CHAMGED =', section, name, variant)
+
+ if not section.startswith('engine/anthy'):
+ # This value is used for IBus.config.set_value only.
+ return
+
+ # The key was deleted by dconf.
+ # test case: update /desktop/ibus/engine/anthy/thumb/ls
+ # and reset the key with dconf direclty.
+ if variant.get_type_string() == '()':
+ self.__prefs.undo_item(section, name)
+ return
+
+ value = self.__prefs.variant_to_value(variant)
+ base_sec = section[len(self.__prefs._prefix) + 1:]
+ sec = self._get_shortcut_type()
+
+ if base_sec == 'thumb':
+ self.__prefs.set_value(base_sec, name, value)
+ self._reset_thumb()
+ elif base_sec == 'dict':
+ self.__set_dict_files_value(base_sec, name, value)
+ self.__set_dict_mode_props(self.__prop_list, True)
+ elif base_sec.startswith('dict/file/'):
+ if base_sec not in self.__prefs.sections():
+ self.__fetch_dict_values(base_sec)
+ self.__prefs.set_value(base_sec, name, value)
+ self.__set_dict_mode_props(self.__prop_list, True)
+ elif base_sec:
+ self.__prefs.set_value(base_sec, name, value)
+ else:
+ self.__prefs.set_value(section, name, value)
+
+ #mod_keys
+ def __set_input_mode(self, mode):
+ self.__input_mode_activate(mode, IBus.PropState.CHECKED)
+ self.__reset()
+ self.__invalidate()
+
+ return True
+
+ def __unset_current_input_mode(self):
+ modes = {
+ INPUT_MODE_HIRAGANA: 'InputMode.Hiragana',
+ INPUT_MODE_KATAKANA: 'InputMode.Katakana',
+ INPUT_MODE_HALF_WIDTH_KATAKANA: 'InputMode.HalfWidthKatakana',
+ INPUT_MODE_LATIN: 'InputMode.Latin',
+ INPUT_MODE_WIDE_LATIN: 'InputMode.WideLatin'
+ }
+ self.__input_mode_activate(modes[Engine.__input_mode],
+ IBus.PropState.UNCHECKED)
+
+ def __cmd_on_off(self, keyval, state):
+ # ibus 1.5 or later needs to send UNCHECKED
+ self.__unset_current_input_mode()
+ if Engine.__input_mode == INPUT_MODE_LATIN:
+ return self.__set_input_mode('InputMode.Hiragana')
+ else:
+ return self.__set_input_mode('InputMode.Latin')
+
+ def __cmd_circle_input_mode(self, keyval, state):
+ modes = {
+ INPUT_MODE_HIRAGANA: 'InputMode.Katakana',
+ INPUT_MODE_KATAKANA: 'InputMode.HalfWidthKatakana',
+ INPUT_MODE_HALF_WIDTH_KATAKANA: 'InputMode.Latin',
+ INPUT_MODE_LATIN: 'InputMode.WideLatin',
+ INPUT_MODE_WIDE_LATIN: 'InputMode.Hiragana'
+ }
+ # ibus 1.5 or later needs to send UNCHECKED
+ self.__unset_current_input_mode()
+ return self.__set_input_mode(modes[Engine.__input_mode])
+
+ def __cmd_circle_kana_mode(self, keyval, state):
+ modes = {
+ INPUT_MODE_HIRAGANA: 'InputMode.Katakana',
+ INPUT_MODE_KATAKANA: 'InputMode.HalfWidthKatakana',
+ INPUT_MODE_HALF_WIDTH_KATAKANA: 'InputMode.Hiragana',
+ INPUT_MODE_LATIN: 'InputMode.Hiragana',
+ INPUT_MODE_WIDE_LATIN: 'InputMode.Hiragana'
+ }
+ # ibus 1.5 or later needs to send UNCHECKED
+ self.__unset_current_input_mode()
+ return self.__set_input_mode(modes[Engine.__input_mode])
+
+ def __cmd_latin_mode(self, keyval, state):
+ # ibus 1.5 or later needs to send UNCHECKED
+ self.__unset_current_input_mode()
+ return self.__set_input_mode('InputMode.Latin')
+
+ def __cmd_wide_latin_mode(self, keyval, state):
+ # ibus 1.5 or later needs to send UNCHECKED
+ self.__unset_current_input_mode()
+ return self.__set_input_mode('InputMode.WideLatin')
+
+ def __cmd_hiragana_mode(self, keyval, state):
+ # ibus 1.5 or later needs to send UNCHECKED
+ self.__unset_current_input_mode()
+ return self.__set_input_mode('InputMode.Hiragana')
+
+ def __cmd_katakana_mode(self, keyval, state):
+ # ibus 1.5 or later needs to send UNCHECKED
+ self.__unset_current_input_mode()
+ return self.__set_input_mode('InputMode.Katakana')
+
+ def __cmd_half_katakana(self, keyval, state):
+ # ibus 1.5 or later needs to send UNCHECKED
+ self.__unset_current_input_mode()
+ return self.__set_input_mode('InputMode.HalfWidthKatakana')
+
+# def __cmd_cancel_pseudo_ascii_mode_key(self, keyval, state):
+# pass
+
+ def __unset_current_typing_mode(self):
+ modes = {
+ jastring.TYPING_MODE_ROMAJI: 'TypingMode.Romaji',
+ jastring.TYPING_MODE_KANA: 'TypingMode.Kana',
+ jastring.TYPING_MODE_THUMB_SHIFT: 'TypingMode.ThumbShift',
+ }
+ self.__typing_mode_activate(modes[Engine.__typing_mode],
+ IBus.PropState.UNCHECKED)
+
+ def __cmd_circle_typing_method(self, keyval, state):
+ if not self._chk_mode('0'):
+ return False
+
+ modes = {
+ jastring.TYPING_MODE_THUMB_SHIFT: 'TypingMode.Romaji',
+ jastring.TYPING_MODE_KANA: 'TypingMode.ThumbShift',
+ jastring.TYPING_MODE_ROMAJI: 'TypingMode.Kana',
+ }
+ # ibus 1.5 or later needs to send UNCHECKED
+ self.__unset_current_typing_mode()
+ self.__typing_mode_activate(modes[Engine.__typing_mode],
+ IBus.PropState.CHECKED)
+ return True
+
+ def __cmd_circle_dict_method(self, keyval, state):
+ if not self._chk_mode('0'):
+ return False
+
+ # ibus 1.5 or later needs to send UNCHECKED
+ prop_name = self.__dict_mode_get_prop_name(Engine.__dict_mode)
+ if prop_name != None:
+ self.__dict_mode_activate(prop_name,
+ IBus.PropState.UNCHECKED)
+
+ single_files = self.__get_single_dict_files()
+ new_mode = Engine.__dict_mode + 1
+ if new_mode > len(single_files):
+ new_mode = 0
+ Engine.__dict_mode = new_mode
+ prop_name = self.__dict_mode_get_prop_name(Engine.__dict_mode)
+ if prop_name == None:
+ return False
+ self.__dict_mode_activate(prop_name,
+ IBus.PropState.CHECKED)
+ return True
+
+ #edit_keys
+ def __cmd_insert_space(self, keyval, state):
+ if Engine.__input_mode == INPUT_MODE_LATIN:
+ return False
+ if (self.__prefs.get_value('common', 'half_width_space') or
+ Engine.__input_mode == INPUT_MODE_HALF_WIDTH_KATAKANA):
+ return self.__cmd_insert_half_space(keyval, state)
+ else:
+ return self.__cmd_insert_wide_space(keyval, state)
+
+ def __cmd_insert_alternate_space(self, keyval, state):
+ if Engine.__input_mode == INPUT_MODE_LATIN:
+ return False
+ if (self.__prefs.get_value('common', 'half_width_space') or
+ Engine.__input_mode == INPUT_MODE_HALF_WIDTH_KATAKANA):
+ return self.__cmd_insert_wide_space(keyval, state)
+ else:
+ return self.__cmd_insert_half_space(keyval, state)
+
+ def __cmd_insert_half_space(self, keyval, state):
+ if not self._chk_mode('0'):
+ return False
+
+ if not self.__preedit_ja_string.is_empty():
+ return False
+ self.__commit_string(chr(IBus.KEY_space))
+ return True
+
+ def __cmd_insert_wide_space(self, keyval, state):
+ if not self._chk_mode('0'):
+ return False
+
+ if not self.__preedit_ja_string.is_empty():
+ return False
+ char = chr(IBus.KEY_space)
+ wide_char = symbol_rule.get(char, None)
+ if wide_char == None:
+ wide_char = unichar_half_to_full(char)
+ self.__commit_string(wide_char)
+ return True
+
+ def __cmd_backspace(self, keyval, state):
+ if not self._chk_mode('12345'):
+ return False
+
+ return self.__on_key_back_space()
+
+ def __cmd_delete(self, keyval, state):
+ if not self._chk_mode('12345'):
+ return False
+
+ return self.__on_key_delete()
+
+ def __cmd_commit(self, keyval, state):
+ if not self._chk_mode('12345'):
+ return False
+
+ return self.__on_key_return()
+
+ def __cmd_convert(self, keyval, state):
+ if not self._chk_mode('14'):
+ return False
+
+ self.__begin_anthy_convert()
+ self.__invalidate()
+
+ return True
+
+ def __cmd_predict(self, keyval, state):
+ if not self._chk_mode('14'):
+ return False
+
+ text, cursor = self.__preedit_ja_string.get_hiragana(True)
+
+ self.__context.set_prediction_string(text)
+ nr_predictions = self.__context.get_nr_predictions()
+
+# for i in range(nr_predictions):
+# print self.__context.get_prediction(i)
+
+ buf = self.__context.get_prediction(0)
+ if not buf:
+ return False
+
+ text = buf
+ self.__segments.append((0, text))
+
+ self.__convert_mode = CONV_MODE_PREDICTION
+ self.__cursor_pos = 0
+ self.__fill_lookup_table()
+ self.__lookup_table_visible = False
+ self.__invalidate()
+
+ return True
+
+ def __cmd_cancel(self, keyval, state):
+ return self.__cmd_cancel_all(keyval, state)
+
+ def __cmd_cancel_all(self, keyval, state):
+ if not self._chk_mode('12345'):
+ return False
+
+ if self.__convert_mode == CONV_MODE_OFF:
+ return self.__on_key_escape()
+ else:
+ self.__end_convert()
+ self.__invalidate()
+ return True
+
+ def __cmd_reconvert(self, keyval, state):
+ if not self.__preedit_ja_string.is_empty():
+ # if user has inputed some chars
+ return False
+
+ # Move importing Gtk into Engine from the header
+ # because ibus-engine-anthy --xml does not requre to open X.
+ try:
+ from gi.repository import Gtk
+ clipboard_get = Gtk.Clipboard.get
+ except ImportError:
+ clipboard_get = lambda a : None
+ except RuntimeError:
+ # Do we support the engine without display?
+ printerr("Gtk couldn't be initialized")
+ printerr('Could not open display')
+ clipboard_get = lambda a : None
+
+ # Use Gtk.Clipboard.request_text() instead of
+ # Gtk.Clipboard.wait_for_text() because DBus is timed out.
+ clipboard = clipboard_get ('PRIMARY')
+ if clipboard:
+ clipboard.request_text (self.__get_clipboard, CLIPBOARD_RECONVERT)
+
+ return True
+
+ def __update_reconvert(self, clipboard_text):
+ if clipboard_text == None:
+ return False
+
+ self.__convert_chars = clipboard_text
+ for i in range(0, len(self.__convert_chars)):
+ keyval = self.__convert_chars[i]
+ self.__preedit_ja_string.insert(chr(ord(keyval)))
+
+ self.__context.set_string(self.__convert_chars)
+ nr_segments = self.__context.get_nr_segments()
+
+ for i in range(0, nr_segments):
+ buf = self.__context.get_segment(i, 0)
+ text = buf
+ self.__segments.append((0, text))
+
+ self.__convert_mode = CONV_MODE_ANTHY
+ self.__cursor_pos = 0
+ self.__fill_lookup_table()
+ self.__lookup_table_visible = False
+ self.__invalidate()
+
+ return True
+
+# def __cmd_do_nothing(self, keyval, state):
+# return True
+
+ #caret_keys
+ def __move_caret(self, i):
+ if not self._chk_mode('1'):
+ return False
+
+ if self.__convert_mode == CONV_MODE_OFF:
+ self.__preedit_ja_string.move_cursor(
+ -len(self.__preedit_ja_string.get_latin()[0]) if i == 0 else
+ i if i in [-1, 1] else
+ len(self.__preedit_ja_string.get_latin()[0]))
+ self.__invalidate()
+ return True
+
+ return False
+
+ def __cmd_move_caret_first(self, keyval, state):
+ return self.__move_caret(0)
+
+ def __cmd_move_caret_last(self, keyval, state):
+ return self.__move_caret(2)
+
+ def __cmd_move_caret_forward(self, keyval, state):
+ return self.__move_caret(1)
+
+ def __cmd_move_caret_backward(self, keyval, state):
+ return self.__move_caret(-1)
+
+ #segments_keys
+ def __select_segment(self, i):
+ if not self._chk_mode('25'):
+ return False
+
+ pos = 0 if i == 0 else \
+ self.__cursor_pos + i if i in [-1, 1] else \
+ len(self.__segments) - 1
+
+ if 0 <= pos < len(self.__segments) and pos != self.__cursor_pos:
+ self.__cursor_pos = pos
+ self.__lookup_table_visible = False
+ self.__fill_lookup_table()
+ self.__invalidate()
+
+ return True
+
+ def __cmd_select_first_segment(self, keyval, state):
+ return self.__select_segment(0)
+
+ def __cmd_select_last_segment(self, keyval, state):
+ return self.__select_segment(2)
+
+ def __cmd_select_next_segment(self, keyval, state):
+ return self.__select_segment(1)
+
+ def __cmd_select_prev_segment(self, keyval, state):
+ return self.__select_segment(-1)
+
+ def __cmd_shrink_segment(self, keyval, state):
+ if not self._chk_mode('25'):
+ return False
+
+ if self.__convert_mode == CONV_MODE_ANTHY:
+ self.__shrink_segment(-1)
+ return True
+
+ def __cmd_expand_segment(self, keyval, state):
+ if not self._chk_mode('25'):
+ return False
+
+ if self.__convert_mode == CONV_MODE_ANTHY:
+ self.__shrink_segment(1)
+ return True
+
+ def __move_cursor_char_length(self, length):
+ if Engine.__input_mode == INPUT_MODE_HIRAGANA:
+ self.__preedit_ja_string.move_cursor_hiragana_length(length)
+ elif Engine.__input_mode == INPUT_MODE_KATAKANA:
+ self.__preedit_ja_string.move_cursor_katakana_length(length)
+ elif Engine.__input_mode == INPUT_MODE_HALF_WIDTH_KATAKANA:
+ self.__preedit_ja_string.move_cursor_half_with_katakana_length(length)
+ else:
+ self.__preedit_ja_string.move_cursor(length)
+
+ def __commit_nth_segment(self, commit_index, keyval, state):
+
+ if commit_index >= len(self.__segments):
+ return False
+
+ if self.__convert_mode == CONV_MODE_ANTHY:
+ for i in range(0, commit_index + 1):
+ (seg_index, text) = self.__segments[i]
+ self.commit_text(IBus.Text.new_from_string(text))
+
+ text, cursor = self.__get_preedit()
+ commit_length = 0
+ for i in range(0, commit_index + 1):
+ buf = self.__context.get_segment(i, NTH_UNCONVERTED_CANDIDATE)
+ commit_length += len(buf)
+ self.__move_cursor_char_length(commit_length - cursor)
+ for i in range(0, commit_length):
+ self.__preedit_ja_string.remove_before()
+ self.__move_cursor_char_length(cursor - commit_length)
+
+ del self.__segments[0:commit_index + 1]
+
+ if len(self.__segments) == 0:
+ self.__reset()
+ else:
+ if self.__cursor_pos > commit_index:
+ self.__cursor_pos -= (commit_index + 1)
+ else:
+ self.__cursor_pos = 0
+ text, cursor = self.__get_preedit()
+ self.__convert_chars = text
+ self.__context.set_string(text)
+
+ self.__lookup_table.clear()
+ self.__lookup_table.set_cursor_visible(False)
+ self.__lookup_table_visible = False
+ self.update_aux_string('', IBus.AttrList(),
+ self.__lookup_table_visible)
+ self.__fill_lookup_table()
+ self.__invalidate()
+ self.__update_input_chars()
+
+ return True
+
+ def __cmd_commit_first_segment(self, keyval, state):
+ return self.__commit_nth_segment(0, keyval, state)
+
+ def __cmd_commit_selected_segment(self, keyval, state):
+ return self.__commit_nth_segment(self.__cursor_pos, keyval, state)
+
+ #candidates_keys
+ def __on_candidate_index_in_page(self, index):
+ if not self._chk_mode('5'):
+ return False
+
+ if index >= self.__lookup_table.get_page_size():
+ return False
+ cursor_pos = self.__lookup_table.get_cursor_pos()
+ cursor_in_page = self.__lookup_table.get_cursor_in_page()
+ real_index = cursor_pos - cursor_in_page + index
+ if real_index >= self.__lookup_table.get_number_of_candidates():
+ return False
+ self.__lookup_table.set_cursor_pos(real_index)
+ index = self.__lookup_table.get_cursor_pos()
+ candidate = self.__lookup_table.get_candidate(index).get_text()
+ self.__segments[self.__cursor_pos] = index, candidate
+ self.__lookup_table_visible = False
+ self.__on_key_right()
+ self.__invalidate()
+ return True
+
+ def __cmd_select_first_candidate(self, keyval, state):
+ return self.__on_candidate_index_in_page(0)
+
+ def __cmd_select_last_candidate(self, keyval, state):
+ return self.__on_candidate_index_in_page(
+ self.__lookup_table.get_page_size() - 1)
+
+ def __cmd_select_next_candidate(self, keyval, state):
+ if not self._chk_mode('235'):
+ return False
+
+ return self.__on_key_down()
+
+ def __cmd_select_prev_candidate(self, keyval, state):
+ if not self._chk_mode('235'):
+ return False
+
+ return self.__on_key_up()
+
+ def __cmd_candidates_page_up(self, keyval, state):
+ if not self._chk_mode('5'):
+ return False
+
+ return self.__on_key_page_up()
+
+ def __cmd_candidates_page_down(self, keyval, state):
+ if not self._chk_mode('5'):
+ return False
+
+ return self.__on_key_page_down()
+
+ #direct_select_keys
+ def __select_keyval(self, keyval):
+ if not self._chk_mode('5'):
+ return False
+
+ return self.__on_key_number(keyval)
+
+ def __cmd_select_candidates_1(self, keyval, state):
+ return self.__select_keyval(keyval)
+
+ def __cmd_select_candidates_2(self, keyval, state):
+ return self.__select_keyval(keyval)
+
+ def __cmd_select_candidates_3(self, keyval, state):
+ return self.__select_keyval(keyval)
+
+ def __cmd_select_candidates_4(self, keyval, state):
+ return self.__select_keyval(keyval)
+
+ def __cmd_select_candidates_5(self, keyval, state):
+ return self.__select_keyval(keyval)
+
+ def __cmd_select_candidates_6(self, keyval, state):
+ return self.__select_keyval(keyval)
+
+ def __cmd_select_candidates_7(self, keyval, state):
+ return self.__select_keyval(keyval)
+
+ def __cmd_select_candidates_8(self, keyval, state):
+ return self.__select_keyval(keyval)
+
+ def __cmd_select_candidates_9(self, keyval, state):
+ return self.__select_keyval(keyval)
+
+ def __cmd_select_candidates_0(self, keyval, state):
+ return self.__select_keyval(keyval)
+
+ #convert_keys
+ def __cmd_convert_to_char_type_forward(self, keyval, state):
+ if self.__convert_mode == CONV_MODE_ANTHY:
+ n = self.__segments[self.__cursor_pos][0]
+ if n == NTH_HIRAGANA_CANDIDATE:
+ return self.__convert_segment_to_kana(NTH_KATAKANA_CANDIDATE)
+ elif n == NTH_KATAKANA_CANDIDATE:
+ return self.__convert_segment_to_kana(NTH_HALFKANA_CANDIDATE)
+ elif n == NTH_HALFKANA_CANDIDATE:
+ return self.__convert_segment_to_latin(-100)
+ elif n == -100:
+ return self.__convert_segment_to_latin(-101)
+ else:
+ return self.__convert_segment_to_kana(NTH_HIRAGANA_CANDIDATE)
+
+ if self.__convert_mode == CONV_MODE_KATAKANA:
+ return self.__cmd_convert_to_half_katakana(keyval, state)
+ elif self.__convert_mode == CONV_MODE_HALF_WIDTH_KATAKANA:
+ return self.__cmd_convert_to_latin(keyval, state)
+ elif CONV_MODE_LATIN_0 <= self.__convert_mode <= CONV_MODE_LATIN_3:
+ return self.__cmd_convert_to_wide_latin(keyval, state)
+ elif (CONV_MODE_WIDE_LATIN_0 <= self.__convert_mode
+ <= CONV_MODE_WIDE_LATIN_3):
+ return self.__cmd_convert_to_hiragana(keyval, state)
+ else:
+ return self.__cmd_convert_to_katakana(keyval, state)
+
+ def __cmd_convert_to_char_type_backward(self, keyval, state):
+ if self.__convert_mode == CONV_MODE_ANTHY:
+ n = self.__segments[self.__cursor_pos][0]
+ if n == NTH_KATAKANA_CANDIDATE:
+ return self.__convert_segment_to_kana(NTH_HIRAGANA_CANDIDATE)
+ elif n == NTH_HALFKANA_CANDIDATE:
+ return self.__convert_segment_to_kana(NTH_KATAKANA_CANDIDATE)
+ elif n == -100:
+ return self.__convert_segment_to_kana(NTH_HALFKANA_CANDIDATE)
+ elif n == -101:
+ return self.__convert_segment_to_latin(-100)
+ else:
+ return self.__convert_segment_to_latin(-101)
+
+ if self.__convert_mode == CONV_MODE_KATAKANA:
+ return self.__cmd_convert_to_hiragana(keyval, state)
+ elif self.__convert_mode == CONV_MODE_HALF_WIDTH_KATAKANA:
+ return self.__cmd_convert_to_katakana(keyval, state)
+ elif CONV_MODE_LATIN_0 <= self.__convert_mode <= CONV_MODE_LATIN_3:
+ return self.__cmd_convert_to_half_katakana(keyval, state)
+ elif (CONV_MODE_WIDE_LATIN_0 <= self.__convert_mode
+ <= CONV_MODE_WIDE_LATIN_3):
+ return self.__cmd_convert_to_latin(keyval, state)
+ else:
+ return self.__cmd_convert_to_wide_latin(keyval, state)
+
+ def __convert_segment_to_kana(self, n):
+ if self.__convert_mode == CONV_MODE_ANTHY and -4 <= n <= -2:
+ buf = self.__context.get_segment(self.__cursor_pos, n)
+ self.__segments[self.__cursor_pos] = n, buf
+ self.__lookup_table_visible = False
+ self.__invalidate()
+ return True
+
+ return False
+
+ def __cmd_convert_to_hiragana(self, keyval, state):
+ if not self._chk_mode('12345'):
+ return False
+
+ if self.__convert_mode == CONV_MODE_ANTHY:
+ return self.__convert_segment_to_kana(NTH_HIRAGANA_CANDIDATE)
+
+ return self.__on_key_conv(0)
+
+ def __cmd_convert_to_katakana(self, keyval, state):
+ if not self._chk_mode('12345'):
+ return False
+
+ if self.__convert_mode == CONV_MODE_ANTHY:
+ return self.__convert_segment_to_kana(NTH_KATAKANA_CANDIDATE)
+
+ return self.__on_key_conv(1)
+
+ def __cmd_convert_to_half(self, keyval, state):
+ if not self._chk_mode('12345'):
+ return False
+
+ if self.__convert_mode == CONV_MODE_ANTHY:
+ i, s = self.__segments[self.__cursor_pos]
+ if i == -101:
+ return self.__convert_segment_to_latin(-100)
+ elif i == -100:
+ return self.__convert_segment_to_latin(-100)
+ return self.__convert_segment_to_kana(NTH_HALFKANA_CANDIDATE)
+
+ elif CONV_MODE_WIDE_LATIN_0 <= self.__convert_mode <= CONV_MODE_WIDE_LATIN_3:
+ return self.__on_key_conv(4)
+ elif CONV_MODE_LATIN_0 <= self.__convert_mode <= CONV_MODE_LATIN_3:
+ return self.__on_key_conv(4)
+ return self.__on_key_conv(2)
+
+ def __cmd_convert_to_half_katakana(self, keyval, state):
+ if not self._chk_mode('12345'):
+ return False
+
+ if self.__convert_mode == CONV_MODE_ANTHY:
+ return self.__convert_segment_to_kana(NTH_HALFKANA_CANDIDATE)
+
+ return self.__on_key_conv(2)
+
+ def __convert_segment_to_latin(self, n):
+ if self.__convert_mode == CONV_MODE_ANTHY and n in [-100, -101]:
+ start = 0
+ for i in range(self.__cursor_pos):
+ start += len(self.__context.get_segment(i, NTH_UNCONVERTED_CANDIDATE))
+ end = start + len(self.__context.get_segment(self.__cursor_pos, NTH_UNCONVERTED_CANDIDATE))
+ i, s = self.__segments[self.__cursor_pos]
+ s2 = self.__preedit_ja_string.get_raw(start, end)
+ if n == -101:
+ s2 = ''.join([unichar_half_to_full(c) for c in s2])
+ if i == n:
+ if s == s2.lower():
+ s2 = s2.upper()
+ elif s == s2.upper():
+ s2 = s2.capitalize()
+ elif s == s2 or s == s2.capitalize():
+ s2 = s2.lower()
+ self.__segments[self.__cursor_pos] = n, s2
+ self.__lookup_table_visible = False
+ self.__invalidate()
+ return True
+
+ return False
+
+ def __cmd_convert_to_wide_latin(self, keyval, state):
+ if not self._chk_mode('12345'):
+ return False
+
+ if self.__convert_mode == CONV_MODE_ANTHY:
+ return self.__convert_segment_to_latin(-101)
+
+ return self.__on_key_conv(3)
+
+ def __cmd_convert_to_latin(self, keyval, state):
+ if not self._chk_mode('12345'):
+ return False
+
+ if self.__convert_mode == CONV_MODE_ANTHY:
+ return self.__convert_segment_to_latin(-100)
+
+ return self.__on_key_conv(4)
+
+ #dictonary_keys
+ def __cmd_dict_admin(self, keyval, state):
+ if not self._chk_mode('0'):
+ return False
+
+ self.__start_dict_admin()
+ return True
+
+ def __cmd_add_word(self, keyval, state):
+ if not self._chk_mode('0'):
+ return False
+
+ self.__start_add_word()
+ return True
+
+ def __cmd_start_setup(self, keyval, state):
+ if not self._chk_mode('0'):
+ return False
+
+ self.__start_setup()
+ return True
+
+ def __start_dict_admin(self):
+ command = self.__prefs.get_value('common', 'dict_admin_command')
+ os.spawnl(os.P_NOWAIT, *command)
+
+ def __start_add_word(self):
+ command = self.__prefs.get_value('common', 'add_word_command')
+ os.spawnl(os.P_NOWAIT, *command)
+
+ def __start_setup(self):
+ if Engine.__setup_pid != 0:
+ pid, state = os.waitpid(Engine.__setup_pid, os.P_NOWAIT)
+ if pid != Engine.__setup_pid:
+ return
+ Engine.__setup_pid = 0
+ setup_cmd = path.join(config.LIBEXECDIR, 'ibus-setup-anthy')
+ Engine.__setup_pid = os.spawnl(os.P_NOWAIT, setup_cmd, 'ibus-setup-anthy')
+
+ def __cmd_hiragana_for_latin_with_shift(self, keyval, state):
+ self.__preedit_ja_string.set_hiragana_katakana(True)
+
diff --git a/engine/python3/factory.py b/engine/python3/factory.py
new file mode 100644
index 0000000..8994793
--- /dev/null
+++ b/engine/python3/factory.py
@@ -0,0 +1,80 @@
+# vim:set et sts=4 sw=4:
+# -*- coding: utf-8 -*-
+#
+# ibus-anthy - The Anthy engine for IBus
+#
+# Copyright (c) 2007-2008 Peng Huang <shawn.p.huang@gmail.com>
+# Copyright (c) 2010-2014 Takao Fujiwara <takao.fujiwara1@gmail.com>
+# Copyright (c) 2007-2014 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+import os
+
+from gi.repository import IBus
+
+import _config as config
+import engine
+
+
+class EngineFactory(IBus.Factory):
+ FACTORY_PATH = '/com/redhat/IBus/engines/Anthy/Factory'
+ ENGINE_PATH = '/com/redhat/IBus/engines/Anthy/Engine'
+ NAME = 'Anthy'
+ LANG = 'ja'
+ ICON = config.PKGDATADIR + '/icons/ibus-anthy.png'
+ AUTHORS = 'Huang Peng <shawn.p.huang@gmail.com>'
+ CREDITS = 'GPLv2'
+
+ def __init__(self, bus):
+ self.__bus = bus
+ engine.Engine.CONFIG_RELOADED(bus)
+ super(EngineFactory, self).__init__(object_path=IBus.PATH_FACTORY,
+ connection=bus.get_connection())
+
+ self.__id = 0
+ self.__config = self.__bus.get_config()
+
+ if self.__config != None:
+ self.__config.connect('value-changed',
+ self.__config_value_changed_cb)
+ else:
+ print('ibus-config is not running or bus address is not correct.',
+ file=sys.stderr)
+
+ bus.get_connection().signal_subscribe('org.freedesktop.DBus',
+ 'org.freedesktop.DBus',
+ 'NameOwnerChanged',
+ '/org/freedesktop/DBus',
+ None,
+ 0,
+ self.__name_owner_changed_cb,
+ bus)
+
+ def do_create_engine(self, engine_name):
+ if engine_name == 'anthy':
+ self.__id += 1
+ return engine.Engine(self.__bus, '%s/%d' % (self.ENGINE_PATH, self.__id))
+
+ return super(EngineFactory, self).do_create_engine(engine_name)
+
+ def __config_value_changed_cb(self, config, section, name, value):
+ engine.Engine.CONFIG_VALUE_CHANGED(self.__bus, section, name, value)
+
+ def __name_owner_changed_cb(self, connection, sender_name, object_path,
+ interface_name, signal_name, parameters,
+ user_data):
+ if signal_name == 'NameOwnerChanged':
+ engine.Engine.CONFIG_RELOADED(self.__bus)
diff --git a/engine/python3/ibus-engine-anthy.in b/engine/python3/ibus-engine-anthy.in
new file mode 100644
index 0000000..c54b10a
--- /dev/null
+++ b/engine/python3/ibus-engine-anthy.in
@@ -0,0 +1,33 @@
+#!/bin/sh
+#
+# vim:set noet ts=4:
+#
+# ibus-anthy - The Anthy engine for IBus
+#
+# Copyright (c) 2007-2008 Peng Huang <shawn.p.huang@gmail.com>
+# Copyright (c) 2010-2013 Takao Fujiwara <takao.fujiwara1@gmail.com>
+# Copyright (c) 2007-2013 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+prefix=@prefix@
+datarootdir=@datarootdir@
+exec_prefix=@exec_prefix@
+libexecdir=@libexecdir@
+export IBUS_PREFIX=@prefix@
+export IBUS_ANTHY_PKGDATADIR=@datarootdir@/@PACKAGE@
+export LIBEXECDIR=$libexecdir
+exec @ENV_IBUS_ENGINE@ @PYTHON@ @datarootdir@/@PACKAGE@/engine/main.py $@
+
diff --git a/engine/python3/jastring.py b/engine/python3/jastring.py
new file mode 100644
index 0000000..255799d
--- /dev/null
+++ b/engine/python3/jastring.py
@@ -0,0 +1,304 @@
+# vim:set et sts=4 sw=4:
+# -*- coding: utf-8 -*-
+#
+# ibus-anthy - The Anthy engine for IBus
+#
+# Copyright (c) 2007-2008 Peng Huang <shawn.p.huang@gmail.com>
+# Copyright (c) 2010-2014 Takao Fujiwara <takao.fujiwara1@gmail.com>
+# Copyright (c) 2007-2014 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+import romaji
+import kana
+import thumb
+
+from segment import unichar_half_to_full
+
+HalfSymbolTable = {}
+for i in range(32, 127):
+ if not chr(i).isalnum():
+ HalfSymbolTable[unichar_half_to_full(chr(i))] = chr(i)
+
+HalfNumberTable = {}
+for i in range(10):
+ HalfNumberTable[unichar_half_to_full(str(i))] = str(i)
+
+PeriodTable = {'。': '.', '、': ',', '。': '.', '、': ','}
+
+SymbolTable = {}
+SymbolTable[0] = {'「': '「', '」': '」', '/': '/'}
+SymbolTable[1] = {'「': '「', '」': '」', '/': '・'}
+SymbolTable[2] = {'「': '[', '」': ']', '/': '/'}
+SymbolTable[3] = {'「': '[', '」': ']', '/': '・'}
+
+TYPING_MODE_ROMAJI, \
+TYPING_MODE_KANA, \
+TYPING_MODE_THUMB_SHIFT = list(range(3))
+
+class JaString:
+ _prefs = None
+ _mode = TYPING_MODE_ROMAJI
+ _shift = False
+ _unshift = False
+
+ def __init__(self, mode=TYPING_MODE_ROMAJI, latin_with_shift=True):
+ self._init_mode(mode)
+ if mode == TYPING_MODE_ROMAJI:
+ romaji.RomajiSegment.SET_LATIN_WITH_SHIFT(latin_with_shift)
+
+ @classmethod
+ def _init_mode(cls, mode):
+ cls._mode = mode
+ cls._shift = False
+ cls._unshift = False
+ cls.__cursor = 0
+ cls.__segments = list()
+ if mode == TYPING_MODE_ROMAJI:
+ romaji.RomajiSegment.INIT_ROMAJI_TYPING_RULE(cls._prefs)
+ elif mode == TYPING_MODE_KANA:
+ kana.KanaSegment.INIT_KANA_TYPING_RULE(cls._prefs)
+ elif mode == TYPING_MODE_THUMB_SHIFT:
+ thumb.ThumbShiftSegment.INIT_THUMB_TYPING_RULE(cls._prefs)
+
+ @classmethod
+ def SET_PREFS(cls, prefs):
+ cls._prefs = prefs
+
+ @classmethod
+ def RESET(cls, prefs, section, name, value):
+ cls._prefs = prefs
+ if section.startswith('kana_typing_rule'):
+ mode = TYPING_MODE_KANA
+ kana.KanaSegment.RESET(prefs, section, name, value)
+ cls._init_mode(mode)
+ if section == 'common' and name == 'latin_with_shift':
+ romaji.RomajiSegment.SET_LATIN_WITH_SHIFT(value)
+
+ def set_shift(self, shift):
+ self._shift = shift
+
+ def set_hiragana_katakana(self, mode):
+ if mode and self._mode == TYPING_MODE_ROMAJI:
+ self._unshift = True
+
+ def insert(self, c):
+ segment_before = None
+ segment_after = None
+ new_segments = None
+
+ if self.__cursor >= 1:
+ segment_before = self.__segments[self.__cursor - 1]
+ if self.__cursor < len(self.__segments):
+ segment_after = self.__segments[self.__cursor]
+ if segment_before and not segment_before.is_finished():
+ if type(segment_before) == romaji.RomajiSegment:
+ new_segments = segment_before.append(c,
+ self._shift,
+ self._unshift)
+ self._unshift = False
+ else:
+ new_segments = segment_before.append(c)
+ elif segment_after and not segment_after.is_finished():
+ if type(segment_after) == romaji.RomajiSegment:
+ new_segments = segment_after.prepend(c,
+ self._shift,
+ self._unshift)
+ self._unshift = False
+ else:
+ new_segments = segment_after.prepend(c)
+ else:
+ if c != '\0' and c != '':
+ if self._mode == TYPING_MODE_ROMAJI:
+ new_segments = [romaji.RomajiSegment(c,
+ '',
+ self._shift,
+ self._unshift)]
+ self._unshift = False
+ elif self._mode == TYPING_MODE_KANA:
+ # kana mode doesn't have shift latin in MS.
+ new_segments = [kana.KanaSegment(c)]
+ elif self._mode == TYPING_MODE_THUMB_SHIFT:
+ new_segments = [thumb.ThumbShiftSegment(c)]
+ if new_segments:
+ self.__segments[self.__cursor:self.__cursor] = new_segments
+ self.__cursor += len(new_segments)
+
+ def remove_before(self):
+ index = self.__cursor - 1
+ if index >= 0:
+ segment = self.__segments[index]
+ segment.pop()
+ if segment.is_empty():
+ del self.__segments[index]
+ self.__cursor = index
+ return True
+
+ return False
+
+ def remove_after(self):
+ index = self.__cursor
+ if index < len(self.__segments):
+ segment = self.__segments[index]
+ segment.pop()
+ if segment.is_empty():
+ del self.__segments[index]
+ return True
+
+ return False
+
+ def get_string(self, type):
+ pass
+
+ def move_cursor(self, delta):
+ self.__cursor += delta
+ if self.__cursor < 0:
+ self.__cursor = 0
+ elif self.__cursor > len(self.__segments):
+ self.__cursor = len(self.__segments)
+
+ # hiragana segments are not char lengths.
+ # e.g. 'ya' is 1 segment and 1 char and 'kya' is 1 segment and 2 chars.
+ def move_cursor_hiragana_length(self, length):
+ delta = length
+ if delta < 0:
+ if self.__cursor >= len(self.__segments):
+ delta = delta + (self.__cursor - len(self.__segments) + 1)
+ self.__cursor = len(self.__segments) - 1
+ while delta < 0:
+ text = str(self.__segments[self.__cursor].to_hiragana())
+ if len(text) > -delta:
+ break
+ delta = delta + len(text)
+ self.__cursor = self.__cursor - 1
+ else:
+ if self.__cursor >= len(self.__segments):
+ self.__cursor = len(self.__segments)
+ return
+ while delta > 0:
+ text = str(self.__segments[self.__cursor].to_hiragana())
+ if len(text) > delta:
+ break
+ delta = delta - len(text)
+ self.__cursor = self.__cursor + 1
+
+ def move_cursor_katakana_length(self, length):
+ delta = length
+ if delta < 0:
+ if self.__cursor >= len(self.__segments):
+ delta = delta + (self.__cursor - len(self.__segments) + 1)
+ self.__cursor = len(self.__segments) - 1
+ while delta < 0:
+ text = str(self.__segments[self.__cursor].to_katanaka())
+ if len(text) > -delta:
+ break
+ delta = delta + len(text)
+ self.__cursor = self.__cursor - 1
+ else:
+ if self.__cursor >= len(self.__segments):
+ self.__cursor = len(self.__segments)
+ return
+ while delta > 0:
+ text = str(self.__segments[self.__cursor].to_katanaka())
+ if len(text) > delta:
+ break
+ delta = delta - len(text)
+ self.__cursor = self.__cursor + 1
+
+ def move_cursor_half_with_katakana_length(self, length):
+ delta = length
+ if delta < 0:
+ if self.__cursor >= len(self.__segments):
+ delta = delta + (self.__cursor - len(self.__segments) + 1)
+ self.__cursor = len(self.__segments) - 1
+ while delta < 0:
+ text = str(self.__segments[self.__cursor].to_half_width_katakana())
+ if len(text) > -delta:
+ break
+ delta = delta + len(text)
+ self.__cursor = self.__cursor - 1
+ else:
+ if self.__cursor >= len(self.__segments):
+ self.__cursor = len(self.__segments)
+ return
+ while delta > 0:
+ text = str(self.__segments[self.__cursor].to_half_width_katakana())
+ if len(text) > delta:
+ break
+ delta = delta - len(text)
+ self.__cursor = self.__cursor + 1
+
+ def _chk_text(self, s):
+ period = self._prefs.get_value('common', 'period_style')
+ symbol = self._prefs.get_value('common', 'symbol_style')
+ half_symbol = self._prefs.get_value('common', 'half_width_symbol')
+ half_number = self._prefs.get_value('common', 'half_width_number')
+ ret = ''
+ for c in s:
+ c = c if not period else PeriodTable.get(c, c)
+ # thumb_left + '2' and '/' are different
+ if self._mode != TYPING_MODE_THUMB_SHIFT:
+ c = c if not symbol else SymbolTable[symbol].get(c, c)
+ c = c if not half_symbol else HalfSymbolTable.get(c, c)
+ c = c if not half_number else HalfNumberTable.get(c, c)
+ ret += c
+ return ret
+
+ def get_hiragana(self, commit=False):
+ conv = lambda s: s.to_hiragana()
+ R = lambda s: s if not (commit and s[-1:] == 'n') else s[:-1] + 'ん'
+ text_before = R(''.join(map(conv, self.__segments[:self.__cursor])))
+ text_after = R(''.join(map(conv, self.__segments[self.__cursor:])))
+ return self._chk_text(text_before + text_after), len(text_before)
+
+ def get_katakana(self, commit=False):
+ conv = lambda s: s.to_katakana()
+ R = lambda s: s if not (commit and s[-1:] == 'n') else s[:-1] + 'ン'
+ text_before = R(''.join(map(conv, self.__segments[:self.__cursor])))
+ text_after = R(''.join(map(conv, self.__segments[self.__cursor:])))
+ return self._chk_text(text_before + text_after), len(text_before)
+
+ def get_half_width_katakana(self, commit=False):
+ conv = lambda s: s.to_half_width_katakana()
+ R = lambda s: s if not (commit and s[-1:] == 'n') else s[:-1] + 'ン'
+ text_before = R(''.join(map(conv, self.__segments[:self.__cursor])))
+ text_after = R(''.join(map(conv, self.__segments[self.__cursor:])))
+ return self._chk_text(text_before + text_after), len(text_before)
+
+ def get_latin(self):
+ conv = lambda s: s.to_latin()
+ text_before = ''.join(map(conv, self.__segments[:self.__cursor]))
+ text_after = ''.join(map(conv, self.__segments[self.__cursor:]))
+ return text_before + text_after, len(text_before)
+
+ def get_wide_latin(self):
+ conv = lambda s: s.to_wide_latin()
+ text_before = ''.join(map(conv, self.__segments[:self.__cursor]))
+ text_after = ''.join(map(conv, self.__segments[self.__cursor:]))
+ return text_before + text_after, len(text_before)
+
+ def is_empty(self):
+ return all([s.is_empty() for s in self.__segments])
+
+ def get_raw(self, start, end):
+ i = 0
+ r = ''
+ for s in self.__segments:
+ if i >= end:
+ break
+ elif start <= i:
+ r += s.to_latin()
+ i += len(s.to_hiragana())
+ return r
diff --git a/engine/python3/kana.py b/engine/python3/kana.py
new file mode 100644
index 0000000..10e1b96
--- /dev/null
+++ b/engine/python3/kana.py
@@ -0,0 +1,170 @@
+# vim:set et sts=4 sw=4:
+# -*- coding: utf-8 -*-
+#
+# ibus-anthy - The Anthy engine for IBus
+#
+# Copyright (c) 2007-2008 Peng Huang <shawn.p.huang@gmail.com>
+# Copyright (c) 2010-2014 Takao Fujiwara <takao.fujiwara1@gmail.com>
+# Copyright (c) 2007-2014 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+import sys
+
+from tables import *
+import segment
+
+_UNFINISHED_HIRAGANA = set('かきくけこさしすせそたちつてとはひふへほ')
+
+class KanaSegment(segment.Segment):
+ _prefs = None
+ _kana_typing_rule_section = None
+ _kana_voiced_consonant_rule = None
+
+ def __init__(self, enchars='', jachars=''):
+ if not jachars:
+ jachars = self.__get_kana_typing_rule(enchars, '')
+ super(KanaSegment, self).__init__(enchars, jachars)
+
+ @classmethod
+ def INIT_KANA_TYPING_RULE(cls, prefs):
+ cls._prefs = prefs
+ if prefs == None:
+ cls._kana_typing_rule_section = None
+ return
+ if cls._kana_typing_rule_section == None:
+ cls._init_kana_typing_method()
+ if cls._kana_voiced_consonant_rule == None and \
+ cls._kana_typing_rule_section != None:
+ cls._init_kana_voiced_consonant_rule()
+
+ @classmethod
+ def _init_kana_typing_method(cls, method=None):
+ prefs = cls._prefs
+ if method == None:
+ method = prefs.get_value('kana_typing_rule', 'method')
+ if method == None:
+ method = 'jp'
+ cls._kana_typing_rule_section = 'kana_typing_rule/' + method
+ if cls._kana_typing_rule_section not in prefs.sections():
+ cls._kana_typing_rule_section = None
+
+ @classmethod
+ def _init_kana_voiced_consonant_rule(cls):
+ prefs = cls._prefs
+ # Create kana_voiced_consonant_rule dynamically.
+ # E.g. 't' + '@' on jp kbd becomes Hiragana GA
+ # 't' + '[' on us kbd becomes Hiragana GA
+ # If the customized table provides U+309b with other chars,
+ # it needs to be detected dynamically.
+ cls._kana_voiced_consonant_rule = {}
+ section = cls._kana_typing_rule_section
+ for gkey in prefs.keys(section):
+ value = prefs.get_value(section, gkey)
+ key = prefs.typing_from_config_key(gkey)
+ if key == '':
+ continue
+ if value == chr(0x309b):
+ for no_voiced, voiced in \
+ list(kana_voiced_consonant_no_rule.items()):
+ rule = no_voiced + key
+ cls._kana_voiced_consonant_rule[rule] = voiced
+ if value == chr(0x309c):
+ for no_voiced, voiced in \
+ list(kana_semi_voiced_consonant_no_rule.items()):
+ rule = no_voiced + key
+ cls._kana_voiced_consonant_rule[rule] = voiced
+
+ @classmethod
+ def RESET(cls, prefs, section, name, value):
+ cls._prefs = prefs
+ if section == 'kana_typing_rule' and name == 'method' and \
+ value != None:
+ cls._kana_typing_rule_section = None
+ cls._kana_voiced_consonant_rule = None
+ cls._init_kana_typing_method(value)
+ elif section.startswith('kana_typing_rule/'):
+ # Probably it's better to restart ibus by manual
+ # instead of saving the emitted values from config.
+ cls._kana_voiced_consonant_rule = None
+
+ def __get_kana_typing_rule(self, enchars, retval=None):
+ prefs = self._prefs
+ value = None
+ section = self._kana_typing_rule_section
+ if section != None:
+ # Need to send Unicode to typing_to_config_key instead of UTF-8
+ # not to separate U+A5
+ gkey = prefs.typing_to_config_key(enchars)
+ if gkey == '':
+ return None
+ enchars = gkey
+ if enchars in prefs.keys(section):
+ value = prefs.str(prefs.str(prefs.get_value(section, enchars)))
+ else:
+ prefs.set_no_key_warning(True)
+ value = prefs.get_value_direct(section, enchars)
+ prefs.set_no_key_warning(False)
+ if value != None:
+ value = prefs.str(prefs.str(value))
+ if value == '':
+ value = None
+ if value == None:
+ value = retval
+ else:
+ value = kana_typing_rule_static.get(enchars, retval)
+ return value
+
+ def is_finished(self):
+ return not (self._jachars in _UNFINISHED_HIRAGANA)
+
+ def append(self, enchar):
+ if enchar == '\0' or enchar == '':
+ return []
+ if self._jachars:
+ text = self._jachars + enchar
+ if self._kana_voiced_consonant_rule != None:
+ jachars = self._kana_voiced_consonant_rule.get(text, None)
+ if jachars:
+ self._enchars = self._enchars + enchar
+ self._jachars = jachars
+ return []
+ return [KanaSegment(enchar)]
+ self._enchars = self._enchars + enchar
+ self._jachars = self.__get_kana_typing_rule(self._enchars, '')
+ return []
+
+ def prepend(self, enchar):
+ if enchar == '\0' or enchar == '':
+ return []
+ if self._enchars == '':
+ self._enchars = enchar
+ self._jachars = self.__get_kana_typing_rule(self._enchars, '')
+ return []
+ return [KanaSegment(enchar)]
+
+ def pop(self, index=-1):
+ if index == -1:
+ index = len(self._enchars) - 1
+ if index < 0 or index >= len(self._enchars):
+ raise IndexError('Out of bound')
+ if self.is_finished():
+ self._enchars = ''
+ self._jachars = ''
+ else:
+ enchars = list(self._enchars)
+ del enchars[index]
+ self._enchars = ''.join(enchars)
+ self._jachars = self.__get_kana_typing_rule(self._enchars, '')
diff --git a/engine/python3/main.py b/engine/python3/main.py
new file mode 100644
index 0000000..eb6fe5f
--- /dev/null
+++ b/engine/python3/main.py
@@ -0,0 +1,188 @@
+# vim:set et sts=4 sw=4:
+# -*- coding: utf-8 -*-
+#
+# ibus-anthy - The Anthy engine for IBus
+#
+# Copyright (c) 2007-2008 Peng Huang <shawn.p.huang@gmail.com>
+# Copyright (c) 2010-2014 Takao Fujiwara <takao.fujiwara1@gmail.com>
+# Copyright (c) 2007-2014 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+import os
+from os import path
+import sys
+import getopt
+import locale
+import xml.dom.minidom
+
+from gi.repository import GLib
+
+# set_prgname before importing factory to show the name in warning
+# messages when import modules are failed. E.g. Gtk.
+GLib.set_prgname('ibus-engine-anthy')
+
+from gi.repository import IBus
+
+import _config as config
+import factory
+
+class IMApp:
+ def __init__(self, exec_by_ibus):
+ command_line = config.LIBEXECDIR + '/ibus-engine-anthy --ibus'
+ self.__component = IBus.Component(name='org.freedesktop.IBus.Anthy',
+ description='Anthy Component',
+ version='0.1.0',
+ license='GPL',
+ author='Peng Huang <shawn.p.huang@gmail.com>',
+ homepage='http://code.google.com/p/ibus/',
+ command_line=command_line,
+ textdomain='ibus-anthy')
+ engine = IBus.EngineDesc(name='anthy',
+ longname='Anthy',
+ description='Anthy Input Method',
+ language='ja',
+ license='GPL',
+ author='Peng Huang <shawn.p.huang@gmail.com>',
+ icon='ibus-anthy',
+ layout=config.LAYOUT,
+ symbol=config.SYMBOL_CHAR,
+ rank=99)
+ self.__component.add_engine(engine)
+ self.__mainloop = GLib.MainLoop()
+ self.__bus = IBus.Bus()
+ self.__bus.connect('disconnected', self.__bus_disconnected_cb)
+ self.__factory = factory.EngineFactory(self.__bus)
+ if exec_by_ibus:
+ self.__bus.request_name('org.freedesktop.IBus.Anthy', 0)
+ else:
+ self.__bus.register_component(self.__component)
+
+ def run(self):
+ self.__mainloop.run()
+
+ def __bus_disconnected_cb(self, bus):
+ self.__mainloop.quit()
+
+
+def launch_engine(exec_by_ibus):
+ IMApp(exec_by_ibus).run()
+
+def get_userhome():
+ if 'HOME' not in os.environ:
+ import pwd
+ userhome = pwd.getpwuid(os.getuid()).pw_dir
+ else:
+ userhome = os.environ['HOME']
+ userhome = userhome.rstrip('/')
+ return userhome
+
+def resync_engine_file():
+ user_config = path.join(get_userhome(), '.config',
+ 'ibus-anthy', 'engines.xml')
+ system_config = path.join(config.PKGDATADIR, 'engine', 'default.xml')
+ if not path.exists(user_config):
+ return
+ if not path.exists(system_config):
+ os.unlink(user_config)
+ return
+
+ # path.getmtime depends on the build time rather than install time.
+ def __get_engine_file_version(engine_file):
+ version_str = ''
+ dom = xml.dom.minidom.parse(engine_file)
+ elements = dom.getElementsByTagName('version')
+ nodes = []
+ if len(elements) > 0:
+ nodes = elements[0].childNodes
+ if len(nodes) > 0:
+ version_str = nodes[0].data
+ if version_str != '':
+ version_str = version_str.strip()
+ return version_str
+
+ user_config_version = __get_engine_file_version(user_config)
+ system_config_version = __get_engine_file_version(system_config)
+ if system_config_version > user_config_version:
+ import shutil
+ shutil.copyfile(system_config, user_config)
+
+def print_xml():
+ user_config = os.path.join(get_userhome(), '.config',
+ 'ibus-anthy', 'engines.xml')
+ system_config = os.path.join(config.PKGDATADIR, 'engine', 'default.xml')
+ xml = None
+ for f in [user_config, system_config]:
+ if os.path.exists(f):
+ xml = f
+ break
+ if xml == None:
+ print('Not exist: %s' % system_config, file=sys.stderr)
+ return
+ file = open(xml, 'r')
+ print(file.read())
+ file.close()
+
+def print_help(out, v = 0):
+ print('-i, --ibus executed by ibus.', file=out)
+ print('-h, --help show this message.', file=out)
+ print('-d, --daemonize daemonize ibus.', file=out)
+ print('-x, --xml print engine xml.', file=out)
+ sys.exit(v)
+
+def main():
+ try:
+ locale.setlocale(locale.LC_ALL, '')
+ except:
+ pass
+
+ exec_by_ibus = False
+ daemonize = False
+ xml = False
+
+ shortopt = 'ihdx'
+ longopt = ['ibus', 'help', 'daemonize', 'xml']
+
+ try:
+ opts, args = getopt.getopt(sys.argv[1:], shortopt, longopt)
+ except getopt.GetoptError as err:
+ print_help(sys.stderr, 1)
+
+ for o, a in opts:
+ if o in ('-h', '--help'):
+ print_help(sys.stdout)
+ elif o in ('-d', '--daemonize'):
+ daemonize = True
+ elif o in ('-i', '--ibus'):
+ exec_by_ibus = True
+ elif o in ('-x', '--xml'):
+ xml = True
+ else:
+ print('Unknown argument: %s' % o, file=sys.stderr)
+ print_help(sys.stderr, 1)
+
+ if daemonize:
+ if os.fork():
+ sys.exit()
+
+ if xml:
+ resync_engine_file()
+ print_xml()
+ return
+
+ launch_engine(exec_by_ibus)
+
+if __name__ == '__main__':
+ main()
diff --git a/engine/python3/romaji.py b/engine/python3/romaji.py
new file mode 100644
index 0000000..d495120
--- /dev/null
+++ b/engine/python3/romaji.py
@@ -0,0 +1,263 @@
+# vim:set et sts=4 sw=4:
+# -*- coding: utf-8 -*-
+#
+# ibus-anthy - The Anthy engine for IBus
+#
+# Copyright (c) 2007-2008 Peng Huang <shawn.p.huang@gmail.com>
+# Copyright (c) 2010-2014 Takao Fujiwara <takao.fujiwara1@gmail.com>
+# Copyright (c) 2007-2014 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+import sys
+
+from tables import *
+import segment
+
+def romaji_correction_rule_get(k, d):
+ return ('ん', k[1:2]) if k[0:1] == 'n' and not k[1:2] in "aiueony'" else d
+
+class RomajiSegment(segment.Segment):
+ _prefs = None
+ _romaji_typing_rule_section = None
+ _latin_with_shift = True
+ _shift_mode = False
+
+ def __init__(self, enchars='', jachars='', shift=False, unshift=False):
+ if self._latin_with_shift:
+ # If Shift key is pressed, Latin mode.
+ # If Hiragana_Katakana key is pressed, Hiragana mode.
+ if shift:
+ self._shift_mode = True
+ if unshift:
+ self._shift_mode = False
+
+ enchars_orig = enchars
+ # Even if the chars are capital with CapsLock, Hiragana
+ # should be converted. E.g. 'SA'
+ enchars = enchars.lower()
+
+ if not jachars and not shift:
+ jachars = self.__get_romaji_typing_rule(enchars, None)
+ if jachars == None:
+ jachars = symbol_rule.get(enchars, '')
+ super(RomajiSegment, self).__init__(enchars_orig, jachars)
+
+ @classmethod
+ def INIT_ROMAJI_TYPING_RULE(cls, prefs):
+ cls._prefs = prefs
+ if prefs == None:
+ cls._romaji_typing_rule_section = None
+ return
+ method = prefs.get_value('romaji_typing_rule', 'method')
+ if method == None:
+ method = 'default'
+ cls._romaji_typing_rule_section = 'romaji_typing_rule/' + method
+ if cls._romaji_typing_rule_section not in prefs.sections():
+ cls._romaji_typing_rule_section = None
+
+ @classmethod
+ def SET_LATIN_WITH_SHIFT(cls, latin_with_shift):
+ # Do not use IBus.Config in every conversion for the performance.
+ cls._latin_with_shift = latin_with_shift
+
+ def __get_romaji_typing_rule(self, enchars, retval=None):
+ prefs = self._prefs
+ value = None
+ section = self._romaji_typing_rule_section
+ if section != None:
+ # Need to send Unicode to typing_to_config_key instead of UTF-8
+ # not to separate U+A5
+ gkey = prefs.typing_to_config_key(enchars)
+ if gkey == '':
+ return None
+ if gkey in prefs.keys(section):
+ value = prefs.get_value(section, gkey)
+ else:
+ prefs.set_no_key_warning(True)
+ value = prefs.get_value_direct(section, gkey)
+ prefs.set_no_key_warning(False)
+ if value == '':
+ value = None
+ if value == None:
+ value = retval
+ else:
+ value = romaji_typing_rule_static.get(enchars, retval)
+ return value
+
+ def is_finished(self):
+ return self._jachars != ''
+
+ def append(self, enchar, shift=False, unshift=False):
+ if self.is_finished():
+ if enchar == '' and enchar == '\0':
+ return []
+ return [RomajiSegment(enchar)]
+
+ text_orig = self._enchars + enchar
+ text = text_orig.lower()
+
+ if self._latin_with_shift:
+ # If Shift key is pressed, Latin mode.
+ # If Hiragana_Katakana key is pressed, Hiragana mode.
+ if shift:
+ self._shift_mode = True
+ if unshift:
+ self._shift_mode = False
+ if self._shift_mode:
+ self._enchars = text_orig
+ return []
+
+ if shift:
+ self._enchars = text_orig
+ return []
+
+ jachars = self.__get_romaji_typing_rule(text, None)
+ if jachars == None:
+ jachars = symbol_rule.get(text, None)
+ if jachars:
+ self._enchars = text_orig
+ self._jachars = jachars
+ return []
+
+ jachars, c = romaji_double_consonat_typing_rule.get(text, (None, None))
+ if jachars:
+ self._enchars = text_orig[0]
+ self._jachars = jachars
+ return [RomajiSegment(c)]
+
+# jachars, c = romaji_correction_rule.get(text, (None, None))
+ jachars, c = romaji_correction_rule_get(text, (None, None))
+ if jachars:
+ self._enchars = text_orig[0]
+ self._jachars = jachars
+ return [RomajiSegment(c)]
+
+ for i in range(-min(4, len(text)), 0):
+ enchars = text[i:]
+
+ jachars = self.__get_romaji_typing_rule(enchars, None)
+ if jachars == None:
+ jachars = symbol_rule.get(enchars, None)
+ if jachars:
+ jasegment = RomajiSegment(enchars, jachars)
+ self._enchars = text_orig[:i]
+ return [jasegment]
+
+ jachars, c = romaji_double_consonat_typing_rule.get(enchars, (None, None))
+ if jachars:
+ jasegment = RomajiSegment(enchars[:-len(c)], jachars)
+ self._enchars = text_orig[:i]
+ if c:
+ return [jasegment, RomajiSegment(c)]
+ return [jasegment]
+
+# jachars, c = romaji_correction_rule.get(enchars, (None, None))
+ jachars, c = romaji_correction_rule_get(enchars, (None, None))
+ if jachars:
+ jasegment = RomajiSegment(enchars[:-len(c)], jachars)
+ self._enchars = text_orig[:i]
+ if c:
+ return [jasegment, RomajiSegment(c)]
+ return [jasegment]
+
+ self._enchars = text_orig
+ return []
+
+ def prepend(self, enchar, shift=False, unshift=False):
+ if enchar == '' or enchar == '\0':
+ return []
+
+ if self.is_finished():
+ return [RomajiSegment(enchar)]
+
+ text_orig = enchar + self._enchars
+ text = text_orig.lower()
+
+ if self._latin_with_shift:
+ if shift:
+ self._shift_mode = True
+ if unshift:
+ self._shift_mode = False
+ if self._shift_mode:
+ self._enchars = text_orig
+ return []
+
+ if shift:
+ self._enchars = text_orig
+ return []
+
+ jachars = self.__get_romaji_typing_rule(text, None)
+ if jachars == None:
+ jachars = symbol_rule.get(text, None)
+ if jachars:
+ self._enchars = text_orig
+ self._jachars = jachars
+ return []
+
+ jachars, c = romaji_double_consonat_typing_rule.get(text, (None, None))
+ if jachars:
+ self._enchars = c
+ return [RomajiSegment(text_orig[0], jachars)]
+
+# jachars, c = romaji_correction_rule.get(text, (None, None))
+ jachars, c = romaji_correction_rule_get(text, (None, None))
+ if jachars:
+ self._enchars = c
+ return [RomajiSegment(text_orig[0], jachars)]
+
+ for i in range(min(4, len(text)), 0, -1):
+ enchars = text[:i]
+
+ jachars = self.__get_romaji_typing_rule(enchars, None)
+ if jachars == None:
+ jachars = symbol_rule.get(enchars, None)
+ if jachars:
+ jasegment = RomajiSegment(enchars, jachars)
+ self._enchars = text_orig[i:]
+ return [jasegment]
+
+ jachars, c = romaji_double_consonat_typing_rule.get(enchars, (None, None))
+ if jachars:
+ self._enchars = c + text_orig[i:]
+ return [RomajiSegment(enchars[:-len(c)], jachars)]
+
+# jachars, c = romaji_correction_rule.get(enchars, (None, None))
+ jachars, c = romaji_correction_rule_get(enchars, (None, None))
+ if jachars:
+ self._enchars = c + text_orig[i:]
+ return [RomajiSegment(enchars[:-len(c)], jachars)]
+
+ self._enchars = text_orig
+ return []
+
+ def pop(self, index=-1):
+ if index == -1:
+ index = len(self._enchars) - 1
+ if index < 0 or index >= len(self._enchars):
+ raise IndexError('Out of bound')
+ if self.is_finished():
+ self._enchars = ''
+ self._jachars = ''
+ else:
+ enchars = list(self._enchars)
+ del enchars[index]
+ self._enchars = ''.join(enchars)
+ jachars = self.__get_romaji_typing_rule(self._enchars, None)
+ if jachars == None:
+ jachars = symbol_rule.get(self._enchars, '')
+ self._jachars = jachars
+
+
diff --git a/engine/python3/segment.py b/engine/python3/segment.py
new file mode 100644
index 0000000..b7450ec
--- /dev/null
+++ b/engine/python3/segment.py
@@ -0,0 +1,95 @@
+# vim:set et sts=4 sw=4:
+# -*- coding: utf-8 -*-
+#
+# ibus-anthy - The Anthy engine for IBus
+#
+# Copyright (c) 2007-2008 Peng Huang <shawn.p.huang@gmail.com>
+# Copyright (c) 2010-2014 Takao Fujiwara <takao.fujiwara1@gmail.com>
+# Copyright (c) 2007-2014 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+from tables import *
+
+_half_full_table = [
+ (0x0020, 0x3000, 1),
+ (0x0021, 0xFF01, 0x5E),
+]
+
+def _h_to_f(c):
+ code = ord (c)
+ for half, full, size in _half_full_table:
+ if code >= half and code < half + size:
+ return chr(full + code - half)
+ return c
+
+def unichar_half_to_full(c):
+ tdl = {'"': '\u201d', "'": '\u2019', '`': '\u2018'}
+ return tdl[c] if c in tdl else _h_to_f(c)
+
+class Segment(object):
+ def __init__(self, enchars='', jachars=''):
+ self._enchars = enchars
+ self._jachars = jachars
+
+ def append(self, enchar):
+ raise NotImplementedError('append() is not implemented')
+
+ def prepend(self, enchar):
+ raise NotImplementedError('prepend() is not implemented')
+
+ def pop(self, index=-1):
+ raise NotImplementedError('pop() is not implemented')
+
+ def is_finished(self):
+ raise NotImplementedError('is_finised() is not implemented')
+
+ def set_enchars(self, enchars):
+ self.enchars = enchars
+
+ def get_enchars(self):
+ return self._enchars
+
+ def set_jachars(self, jachars):
+ self._jachars = jachars
+
+ def get_jachars(self):
+ return self._jachars
+
+ def to_hiragana(self):
+ if self._jachars:
+ return self._jachars
+ return self._enchars
+
+ def to_katakana(self):
+ if self._jachars:
+ return ''.join([hiragana_katakana_table.get(c, (c, c, c))[0] for c in self._jachars])
+ return self._enchars
+
+ def to_half_width_katakana(self):
+ if self._jachars:
+ return ''.join([hiragana_katakana_table.get(c, (c, c, c))[1] for c in self._jachars])
+ return self._enchars
+
+ def to_latin(self):
+ return self._enchars
+
+ def to_wide_latin(self):
+ return ''.join(map(unichar_half_to_full, self._enchars))
+
+ def is_empty(self):
+ if self._enchars or self._jachars:
+ return False
+ return True
diff --git a/engine/python3/tables.py b/engine/python3/tables.py
new file mode 100644
index 0000000..b2c4cac
--- /dev/null
+++ b/engine/python3/tables.py
@@ -0,0 +1,731 @@
+# vim:set et sts=4 sw=4:
+# -*- coding: utf-8 -*-
+#
+# ibus-anthy - The Anthy engine for IBus
+#
+# Copyright (c) 2007-2008 Peng Huang <shawn.p.huang@gmail.com>
+# Copyright (c) 2010-2014 Takao Fujiwara <takao.fujiwara1@gmail.com>
+# Copyright (c) 2007-2014 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+# string, result, cont
+romaji_typing_rule_static = {
+ '-' : 'ー',
+ 'a' : 'あ',
+ 'i' : 'い',
+ 'u' : 'う',
+ 'e' : 'え',
+ 'o' : 'お',
+ 'xa' : 'ぁ',
+ 'xi' : 'ぃ',
+ 'xu' : 'ぅ',
+ 'xe' : 'ぇ',
+ 'xo' : 'ぉ',
+ 'la' : 'ぁ',
+ 'li' : 'ぃ',
+ 'lu' : 'ぅ',
+ 'le' : 'ぇ',
+ 'lo' : 'ぉ',
+ 'wha' : 'うぁ',
+ 'whi' : 'うぃ',
+ 'whe' : 'うぇ',
+ 'who' : 'うぉ',
+ 'va' : 'ヴぁ',
+ 'vi' : 'ヴぃ',
+ 'vu' : 'ヴ',
+ 've' : 'ヴぇ',
+ 'vo' : 'ヴぉ',
+ 'ka' : 'か',
+ 'ki' : 'き',
+ 'ku' : 'く',
+ 'ke' : 'け',
+ 'ko' : 'こ',
+ 'lka' : 'ヵ',
+ 'lke' : 'ヶ',
+# u'xka' : u'ゕ',
+ 'xka' : 'ヵ',
+# u'xke' : u'ゖ',
+ 'xke' : 'ヶ',
+ 'ga' : 'が',
+ 'gi' : 'ぎ',
+ 'gu' : 'ぐ',
+ 'ge' : 'げ',
+ 'go' : 'ご',
+ 'kya' : 'きゃ',
+ 'kyi' : 'きぃ',
+ 'kyu' : 'きゅ',
+ 'kye' : 'きぇ',
+ 'kyo' : 'きょ',
+ 'kwa' : 'くぁ',
+ 'gya' : 'ぎゃ',
+ 'gyi' : 'ぎぃ',
+ 'gyu' : 'ぎゅ',
+ 'gye' : 'ぎぇ',
+ 'gyo' : 'ぎょ',
+ 'gwa' : 'ぐぁ',
+ 'sa' : 'さ',
+ 'si' : 'し',
+ 'su' : 'す',
+ 'se' : 'せ',
+ 'so' : 'そ',
+ 'za' : 'ざ',
+ 'zi' : 'じ',
+ 'zu' : 'ず',
+ 'ze' : 'ぜ',
+ 'zo' : 'ぞ',
+ 'sya' : 'しゃ',
+ 'syi' : 'しぃ',
+ 'syu' : 'しゅ',
+ 'sye' : 'しぇ',
+ 'syo' : 'しょ',
+ 'sha' : 'しゃ',
+ 'shi' : 'し',
+ 'shu' : 'しゅ',
+ 'she' : 'しぇ',
+ 'sho' : 'しょ',
+ 'zya' : 'じゃ',
+ 'zyi' : 'じぃ',
+ 'zyu' : 'じゅ',
+ 'zye' : 'じぇ',
+ 'zyo' : 'じょ',
+ 'ja' : 'じゃ',
+ 'jya' : 'じゃ',
+ 'ji' : 'じ',
+ 'jyi' : 'じぃ',
+ 'ju' : 'じゅ',
+ 'jyu' : 'じゅ',
+ 'je' : 'じぇ',
+ 'jye' : 'じぇ',
+ 'jo' : 'じょ',
+ 'jyo' : 'じょ',
+ 'ta' : 'た',
+ 'ti' : 'ち',
+ 'tu' : 'つ',
+ 'tsu' : 'つ',
+ 'te' : 'て',
+ 'to' : 'と',
+ 'da' : 'だ',
+ 'di' : 'ぢ',
+ 'du' : 'づ',
+ 'de' : 'で',
+ 'do' : 'ど',
+ 'xtu' : 'っ',
+ 'xtsu' : 'っ',
+ 'ltu' : 'っ',
+ 'ltsu' : 'っ',
+ 'tya' : 'ちゃ',
+ 'tyi' : 'ちぃ',
+ 'tyu' : 'ちゅ',
+ 'tye' : 'ちぇ',
+ 'tyo' : 'ちょ',
+ 'cya' : 'ちゃ',
+ 'cyi' : 'ちぃ',
+ 'cyu' : 'ちゅ',
+ 'cye' : 'ちぇ',
+ 'cyo' : 'ちょ',
+ 'cha' : 'ちゃ',
+ 'chi' : 'ち',
+ 'chu' : 'ちゅ',
+ 'che' : 'ちぇ',
+ 'cho' : 'ちょ',
+ 'dya' : 'ぢゃ',
+ 'dyi' : 'ぢぃ',
+ 'dyu' : 'ぢゅ',
+ 'dye' : 'ぢぇ',
+ 'dyo' : 'ぢょ',
+ 'tsa' : 'つぁ',
+ 'tsi' : 'つぃ',
+ 'tse' : 'つぇ',
+ 'tso' : 'つぉ',
+ 'tha' : 'てゃ',
+ 'thi' : 'てぃ',
+ 'thu' : 'てゅ',
+ 'the' : 'てぇ',
+ 'tho' : 'てょ',
+ 'twu' : 'とぅ',
+ 'dha' : 'でゃ',
+ 'dhi' : 'でぃ',
+ 'dhu' : 'でゅ',
+ 'dhe' : 'でぇ',
+ 'dho' : 'でょ',
+ 'dwu' : 'どぅ',
+ 'na' : 'な',
+ 'ni' : 'に',
+ 'nu' : 'ぬ',
+ 'ne' : 'ね',
+ 'no' : 'の',
+ 'nya' : 'にゃ',
+ 'nyi' : 'にぃ',
+ 'nyu' : 'にゅ',
+ 'nye' : 'にぇ',
+ 'nyo' : 'にょ',
+ 'ha' : 'は',
+ 'hi' : 'ひ',
+ 'hu' : 'ふ',
+ 'he' : 'へ',
+ 'ho' : 'ほ',
+ 'ba' : 'ば',
+ 'bi' : 'び',
+ 'bu' : 'ぶ',
+ 'be' : 'べ',
+ 'bo' : 'ぼ',
+ 'pa' : 'ぱ',
+ 'pi' : 'ぴ',
+ 'pu' : 'ぷ',
+ 'pe' : 'ぺ',
+ 'po' : 'ぽ',
+ 'hya' : 'ひゃ',
+ 'hyi' : 'ひぃ',
+ 'hyu' : 'ひゅ',
+ 'hye' : 'ひぇ',
+ 'hyo' : 'ひょ',
+ 'bya' : 'びゃ',
+ 'byi' : 'びぃ',
+ 'byu' : 'びゅ',
+ 'bye' : 'びぇ',
+ 'byo' : 'びょ',
+ 'pya' : 'ぴゃ',
+ 'pyi' : 'ぴぃ',
+ 'pyu' : 'ぴゅ',
+ 'pye' : 'ぴぇ',
+ 'pyo' : 'ぴょ',
+ 'fa' : 'ふぁ',
+ 'fi' : 'ふぃ',
+ 'fu' : 'ふ',
+ 'fe' : 'ふぇ',
+ 'fo' : 'ふぉ',
+ 'fya' : 'ふゃ',
+ 'fyi' : 'ふぃ',
+ 'fyu' : 'ふゅ',
+ 'fye' : 'ふぇ',
+ 'fyo' : 'ふょ',
+ 'ma' : 'ま',
+ 'mi' : 'み',
+ 'mu' : 'む',
+ 'me' : 'め',
+ 'mo' : 'も',
+ 'mya' : 'みゃ',
+ 'myi' : 'みぃ',
+ 'myu' : 'みゅ',
+ 'mye' : 'みぇ',
+ 'myo' : 'みょ',
+ 'ya' : 'や',
+ 'yi' : 'い',
+ 'yu' : 'ゆ',
+ 'ye' : 'いぇ',
+ 'yo' : 'よ',
+ 'lya' : 'ゃ',
+ 'lyi' : 'ぃ',
+ 'lyu' : 'ゅ',
+ 'lye' : 'ぇ',
+ 'lyo' : 'ょ',
+ 'xya' : 'ゃ',
+ 'xyi' : 'ぃ',
+ 'xyu' : 'ゅ',
+ 'xye' : 'ぇ',
+ 'xyo' : 'ょ',
+ 'ra' : 'ら',
+ 'ri' : 'り',
+ 'ru' : 'る',
+ 're' : 'れ',
+ 'ro' : 'ろ',
+ 'rya' : 'りゃ',
+ 'ryi' : 'りぃ',
+ 'ryu' : 'りゅ',
+ 'rye' : 'りぇ',
+ 'ryo' : 'りょ',
+ 'wa' : 'わ',
+ 'wi' : 'うぃ',
+ 'wu' : 'う',
+ 'we' : 'うぇ',
+ 'wo' : 'を',
+ 'lwa' : 'ゎ',
+ 'xwa' : 'ゎ',
+ 'n\'' : 'ん',
+ 'nn' : 'ん',
+ 'wyi' : 'ゐ',
+ 'wye' : 'ゑ',
+}
+
+symbol_rule = {
+ # symbols
+ ' ' : ' ',
+ ',' : '、',
+ '.' : '。',
+ '!' : '!',
+ '"' : '\u201d',
+ '#' : '#',
+ '$' : '$',
+ '%' : '%',
+ '&' : '&',
+ '\'' : '\u2019',
+ '(' : '(',
+ ')' : ')',
+ '~' : '\uff5e',
+ '-' : 'ー',
+ '=' : '=',
+ '^' : '^',
+ '\\' : '\',
+ '|' : '|',
+ '`' : '\u2018',
+ '@' : '@',
+ '{' : '{',
+ '[' : '「',
+ '+' : '+',
+ ';' : ';',
+ '*' : '*',
+ ':' : ':',
+ '}' : '}',
+ ']' : '」',
+ '<' : '<',
+ '>' : '>',
+ '?' : '?',
+ '/' : '/',
+ '_' : '_',
+ '¥' : '¥',
+
+ # numbers
+ '0': '0',
+ '1': '1',
+ '2': '2',
+ '3': '3',
+ '4': '4',
+ '5': '5',
+ '6': '6',
+ '7': '7',
+ '8': '8',
+ '9': '9',
+}
+
+# this is only used with romaji_typing_rule
+romaji_double_consonat_typing_rule = {
+ # double consonant rule
+ 'bb' : ('っ', 'b'),
+ 'cc' : ('っ', 'c'),
+ 'dd' : ('っ', 'd'),
+ 'ff' : ('っ', 'f'),
+ 'gg' : ('っ', 'g'),
+ 'hh' : ('っ', 'h'),
+ 'jj' : ('っ', 'j'),
+ 'kk' : ('っ', 'k'),
+ 'mm' : ('っ', 'm'),
+ 'pp' : ('っ', 'p'),
+ 'rr' : ('っ', 'r'),
+ 'ss' : ('っ', 's'),
+ 'tt' : ('っ', 't'),
+ 'vv' : ('っ', 'v'),
+ 'ww' : ('っ', 'w'),
+ 'xx' : ('っ', 'x'),
+ 'yy' : ('っ', 'y'),
+ 'zz' : ('っ', 'z'),
+}
+
+# this is only used with romaji_typing_rule
+romaji_correction_rule = {
+ 'nb' : ('ん', 'b'),
+ 'nc' : ('ん', 'c'),
+ 'nd' : ('ん', 'd'),
+ 'nf' : ('ん', 'f'),
+ 'ng' : ('ん', 'g'),
+ 'nh' : ('ん', 'h'),
+ 'nj' : ('ん', 'j'),
+ 'nk' : ('ん', 'k'),
+ 'nl' : ('ん', 'l'),
+ 'nm' : ('ん', 'm'),
+ 'np' : ('ん', 'p'),
+ 'nr' : ('ん', 'r'),
+ 'ns' : ('ん', 's'),
+ 'nt' : ('ん', 't'),
+ 'nv' : ('ん', 'v'),
+ 'nw' : ('ん', 'w'),
+ 'nx' : ('ん', 'x'),
+ 'nz' : ('ん', 'z'),
+ 'n\0' : ('ん', ''),
+ 'n,' : ('ん', ','),
+ 'n.' : ('ん', '.'),
+}
+
+# EUC-JP and SJIS do not have the chars
+romaji_utf8_rule = {
+ 'う゛' : ['ゔ'],
+}
+
+# Hiragana normalization is needed for the personal dict.
+romaji_normalize_rule = {
+ 'ヴ' : ['う゛'],
+}
+
+# a port of 101kana.sty from scim-anthy
+kana_typing_rule_static = {
+ # no modifiers keys
+ '1' : 'ぬ',
+ '2' : 'ふ',
+ '3' : 'あ',
+ '4' : 'う',
+ '5' : 'え',
+ '6' : 'お',
+ '7' : 'や',
+ '8' : 'ゆ',
+ '9' : 'よ',
+ '0' : 'わ',
+ '-' : 'ほ',
+ '^' : 'へ',
+
+ 'q' : 'た',
+ 'w' : 'て',
+ 'e' : 'い',
+ 'r' : 'す',
+ 't' : 'か',
+ 'y' : 'ん',
+ 'u' : 'な',
+ 'i' : 'に',
+ 'o' : 'ら',
+ 'p' : 'せ',
+ '@' : '゛',
+ '[' : '゜',
+
+ 'a' : 'ち',
+ 's' : 'と',
+ 'd' : 'し',
+ 'f' : 'は',
+ 'g' : 'き',
+ 'h' : 'く',
+ 'j' : 'ま',
+ 'k' : 'の',
+ 'l' : 'り',
+ ';' : 'れ',
+ ':' : 'け',
+ ']' : 'む',
+
+ 'z' : 'つ',
+ 'x' : 'さ',
+ 'c' : 'そ',
+ 'v' : 'ひ',
+ 'b' : 'こ',
+ 'n' : 'み',
+ 'm' : 'も',
+ ',' : 'ね',
+ '.' : 'る',
+ '/' : 'め',
+ # u'\\' : u'ー',
+ '\\' : 'ろ',
+
+ # shift modifiered keys
+ '!' : 'ぬ',
+ '"' : 'ふ',
+ '#' : 'ぁ',
+ '$' : 'ぅ',
+ '%' : 'ぇ',
+ '&' : 'ぉ',
+ '\'' : 'ゃ',
+ '(' : 'ゅ',
+ ')' : 'ょ',
+ '~' : 'を',
+ '=' : 'ほ',
+ '|' : 'ー',
+
+ 'Q' : 'た',
+ 'W' : 'て',
+ 'E' : 'ぃ',
+ 'R' : 'す',
+ 'T' : 'ヵ',
+ 'Y' : 'ん',
+ 'U' : 'な',
+ 'I' : 'に',
+ 'O' : 'ら',
+ 'P' : 'せ',
+ '`' : '゛',
+
+ '{' : '「',
+
+ 'A' : 'ち',
+ 'S' : 'と',
+ 'D' : 'し',
+ 'F' : 'ゎ',
+ 'G' : 'き',
+ 'H' : 'く',
+ 'J' : 'ま',
+ 'K' : 'の',
+ 'L' : 'り',
+ '+' : 'れ',
+ '*' : 'ヶ',
+
+ '}' : '」',
+
+ 'Z' : 'っ',
+ 'X' : 'さ',
+ 'C' : 'そ',
+ 'V' : 'ゐ',
+ 'B' : 'こ',
+ 'M' : 'も',
+ 'N' : 'み',
+ '<' : '、',
+ '>' : '。',
+
+ '?' : '・',
+ '_' : 'ろ',
+
+ '¥' : 'ー',
+}
+
+kana_voiced_consonant_no_rule = {
+ 'か' : 'が',
+ 'き' : 'ぎ',
+ 'く' : 'ぐ',
+ 'け' : 'げ',
+ 'こ' : 'ご',
+ 'さ' : 'ざ',
+ 'し' : 'じ',
+ 'す' : 'ず',
+ 'せ' : 'ぜ',
+ 'そ' : 'ぞ',
+ 'た' : 'だ',
+ 'ち' : 'ぢ',
+ 'つ' : 'づ',
+ 'て' : 'で',
+ 'と' : 'ど',
+ 'は' : 'ば',
+ 'ひ' : 'び',
+ 'ふ' : 'ぶ',
+ 'へ' : 'べ',
+ 'ほ' : 'ぼ',
+}
+
+kana_semi_voiced_consonant_no_rule = {
+ 'は' : 'ぱ',
+ 'ひ' : 'ぴ',
+ 'ふ' : 'ぷ',
+ 'へ' : 'ぺ',
+ 'ほ' : 'ぽ',
+}
+
+# Create the table dynamically with kana_voiced_consonant_no_rule
+#
+#kana_voiced_consonant_rule = {
+# u'か@' : u'が',
+# u'き@' : u'ぎ',
+# u'く@' : u'ぐ',
+# u'け@' : u'げ',
+# u'こ@' : u'ご',
+# u'さ@' : u'ざ',
+# u'し@' : u'じ',
+# u'す@' : u'ず',
+# u'せ@' : u'ぜ',
+# u'そ@' : u'ぞ',
+# u'た@' : u'だ',
+# u'ち@' : u'ぢ',
+# u'つ@' : u'づ',
+# u'て@' : u'で',
+# u'と@' : u'ど',
+# u'は@' : u'ば',
+# u'ひ@' : u'び',
+# u'ふ@' : u'ぶ',
+# u'へ@' : u'べ',
+# u'ほ@' : u'ぼ',
+# u'か`' : u'が',
+# u'き`' : u'ぎ',
+# u'く`' : u'ぐ',
+# u'け`' : u'げ',
+# u'こ`' : u'ご',
+# u'さ`' : u'ざ',
+# u'し`' : u'じ',
+# u'す`' : u'ず',
+# u'せ`' : u'ぜ',
+# u'そ`' : u'ぞ',
+# u'た`' : u'だ',
+# u'ち`' : u'ぢ',
+# u'つ`' : u'づ',
+# u'て`' : u'で',
+# u'と`' : u'ど',
+# u'は`' : u'ば',
+# u'ひ`' : u'び',
+# u'ふ`' : u'ぶ',
+# u'へ`' : u'べ',
+# u'ほ`' : u'ぼ',
+# u'は[' : u'ぱ',
+# u'ひ[' : u'ぴ',
+# u'ふ[' : u'ぷ',
+# u'へ[' : u'ぺ',
+# u'ほ[' : u'ぽ',
+#}
+#
+#kana_voiced_consonant_us_rule = {
+# u'か[' : u'が',
+# u'き[' : u'ぎ',
+# u'く[' : u'ぐ',
+# u'け[' : u'げ',
+# u'こ[' : u'ご',
+# u'さ[' : u'ざ',
+# u'し[' : u'じ',
+# u'す[' : u'ず',
+# u'せ[' : u'ぜ',
+# u'そ[' : u'ぞ',
+# u'た[' : u'だ',
+# u'ち[' : u'ぢ',
+# u'つ[' : u'づ',
+# u'て[' : u'で',
+# u'と[' : u'ど',
+# u'は[' : u'ば',
+# u'ひ[' : u'び',
+# u'ふ[' : u'ぶ',
+# u'へ[' : u'べ',
+# u'ほ[' : u'ぼ',
+# u'は]' : u'ぱ',
+# u'ひ]' : u'ぴ',
+# u'ふ]' : u'ぷ',
+# u'へ]' : u'ぺ',
+# u'ほ]' : u'ぽ',
+#}
+
+#hiragana, katakana, half_katakana
+hiragana_katakana_table = {
+ 'あ' : ('ア', 'ア'),
+ 'い' : ('イ', 'イ'),
+ 'う' : ('ウ', 'ウ'),
+ 'え' : ('エ', 'エ'),
+ 'お' : ('オ', 'オ'),
+ 'か' : ('カ', 'カ'),
+ 'き' : ('キ', 'キ'),
+ 'く' : ('ク', 'ク'),
+ 'け' : ('ケ', 'ケ'),
+ 'こ' : ('コ', 'コ'),
+ 'が' : ('ガ', 'ガ'),
+ 'ぎ' : ('ギ', 'ギ'),
+ 'ぐ' : ('グ', 'グ'),
+ 'げ' : ('ゲ', 'ゲ'),
+ 'ご' : ('ゴ', 'ゴ'),
+ 'さ' : ('サ', 'サ'),
+ 'し' : ('シ', 'シ'),
+ 'す' : ('ス', 'ス'),
+ 'せ' : ('セ', 'セ'),
+ 'そ' : ('ソ', 'ソ'),
+ 'ざ' : ('ザ', 'ザ'),
+ 'じ' : ('ジ', 'ジ'),
+ 'ず' : ('ズ', 'ズ'),
+ 'ぜ' : ('ゼ', 'ゼ'),
+ 'ぞ' : ('ゾ', 'ゾ'),
+ 'た' : ('タ', 'タ'),
+ 'ち' : ('チ', 'チ'),
+ 'つ' : ('ツ', 'ツ'),
+ 'て' : ('テ', 'テ'),
+ 'と' : ('ト', 'ト'),
+ 'だ' : ('ダ', 'ダ'),
+ 'ぢ' : ('ヂ', 'ヂ'),
+ 'づ' : ('ヅ', 'ヅ'),
+ 'で' : ('デ', 'デ'),
+ 'ど' : ('ド', 'ド'),
+ 'な' : ('ナ', 'ナ'),
+ 'に' : ('ニ', 'ニ'),
+ 'ぬ' : ('ヌ', 'ヌ'),
+ 'ね' : ('ネ', 'ネ'),
+ 'の' : ('ノ', 'ノ'),
+ 'は' : ('ハ', 'ハ'),
+ 'ひ' : ('ヒ', 'ヒ'),
+ 'ふ' : ('フ', 'フ'),
+ 'へ' : ('ヘ', 'ヘ'),
+ 'ほ' : ('ホ', 'ホ'),
+ 'ば' : ('バ', 'バ'),
+ 'び' : ('ビ', 'ビ'),
+ 'ぶ' : ('ブ', 'ブ'),
+ 'べ' : ('ベ', 'ベ'),
+ 'ぼ' : ('ボ', 'ボ'),
+ 'ぱ' : ('パ', 'パ'),
+ 'ぴ' : ('ピ', 'ピ'),
+ 'ぷ' : ('プ', 'プ'),
+ 'ぺ' : ('ペ', 'ペ'),
+ 'ぽ' : ('ポ', 'ポ'),
+ 'ま' : ('マ', 'マ'),
+ 'み' : ('ミ', 'ミ'),
+ 'む' : ('ム', 'ム'),
+ 'め' : ('メ', 'メ'),
+ 'も' : ('モ', 'モ'),
+ 'や' : ('ヤ', 'ヤ'),
+ 'ゆ' : ('ユ', 'ユ'),
+ 'よ' : ('ヨ', 'ヨ'),
+ 'ら' : ('ラ', 'ラ'),
+ 'り' : ('リ', 'リ'),
+ 'る' : ('ル', 'ル'),
+ 'れ' : ('レ', 'レ'),
+ 'ろ' : ('ロ', 'ロ'),
+ 'わ' : ('ワ', 'ワ'),
+ 'を' : ('ヲ', 'ヲ'),
+ 'ん' : ('ン', 'ン'),
+ 'ぁ' : ('ァ', 'ァ'),
+ 'ぃ' : ('ィ', 'ィ'),
+ 'ぅ' : ('ゥ', 'ゥ'),
+ 'ぇ' : ('ェ', 'ェ'),
+ 'ぉ' : ('ォ', 'ォ'),
+ 'っ' : ('ッ', 'ッ'),
+ 'ゃ' : ('ャ', 'ャ'),
+ 'ゅ' : ('ュ', 'ュ'),
+ 'ょ' : ('ョ', 'ョ'),
+ 'ヵ' : ('ヵ', 'カ'),
+ 'ヶ' : ('ヶ', 'ケ'),
+ 'ゎ' : ('ヮ', 'ワ'),
+ 'ゐ' : ('ヰ', 'ィ'),
+ 'ゑ' : ('ヱ', 'ェ'),
+ 'ヴ' : ('ヴ', 'ヴ'),
+
+ # symbols
+ 'ー' : ('ー', 'ー'),
+ '、' : ('、', '、'),
+ '。' : ('。', '。'),
+ '!' : ('!', '!'),
+ '\u201d' : ('\u201d', '"'),
+ '#' : ('#', '#'),
+ '$' : ('$', '$'),
+ '%' : ('%', '%'),
+ '&' : ('&', '&'),
+ '\u2019' : ('\u2019', '\''),
+ '(' : ('(', '('),
+ ')' : (')', ')'),
+ '\uff5e' : ('\uff5e', '~'),
+ '=' : ('=', '='),
+ '^' : ('^', '^'),
+ '\' : ('\', '\\'),
+ '|' : ('|', '|'),
+ '\u2018' : ('\u2018', '`'),
+ '@' : ('@', '@'),
+ '゛' : ('゛', '゙'),
+ '{' : ('{', '{'),
+ '゜' : ('゜', '゚'),
+ '「' : ('「', '「'),
+ '+' : ('+', '+'),
+ ';' : (';', ';'),
+ '*' : ('*', '*'),
+ ':' : (':', ':'),
+ '}' : ('}', '}'),
+ '」' : ('」', '」'),
+ '<' : ('<', '<'),
+ '>' : ('>', '>'),
+ '?' : ('?', '?'),
+ '・' : ('・', '・'),
+ '/' : ('/', '/'),
+ '_' : ('_', '_'),
+ '¥' : ('¥', '¥'),
+
+ # numbers
+ '0': ('0', '0'),
+ '1': ('1', '1'),
+ '2': ('2', '2'),
+ '3': ('3', '3'),
+ '4': ('4', '4'),
+ '5': ('5', '5'),
+ '6': ('6', '6'),
+ '7': ('7', '7'),
+ '8': ('8', '8'),
+ '9': ('9', '9'),
+}
diff --git a/engine/python3/test.py b/engine/python3/test.py
new file mode 100644
index 0000000..cd67997
--- /dev/null
+++ b/engine/python3/test.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+import anthy
+import sys
+
+ctx = anthy.anthy_context ()
+ctx._set_encoding (2)
+if len(sys.argv) >= 2:
+ ctx.set_string (sys.argv[1])
+else:
+ ctx.set_string ("かまぁく")
+conv_stat = anthy.anthy_conv_stat ()
+seg_stat = anthy.anthy_segment_stat ()
+ctx.get_stat (conv_stat)
+for i in range (0, conv_stat.nr_segment):
+ ctx.get_segment_stat (i, seg_stat)
+ buf = " "
+ i = ctx.get_segment (i, 0, buf, 10)
+ print buf[:i]
+# anthy.anthy_release_context (ctx)
+ctx = None
diff --git a/engine/python3/thumb.py b/engine/python3/thumb.py
new file mode 100644
index 0000000..93a3967
--- /dev/null
+++ b/engine/python3/thumb.py
@@ -0,0 +1,657 @@
+# -*- coding: utf-8 -*-
+# vim:set et sts=4 sw=4:
+#
+# ibus-anthy - The Anthy engine for IBus
+#
+# Copyright (c) 2007-2008 Peng Huang <shawn.p.huang@gmail.com>
+# Copyright (c) 2009 Hideaki ABE <abe.sendai@gmail.com>
+# Copyright (c) 2010-2014 Takao Fujiwara <takao.fujiwara1@gmail.com>
+# Copyright (c) 2007-2014 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+__all__ = (
+ 'ThumbShiftKeyboard',
+ 'ThumbShiftSegment',
+ )
+
+from gi.repository import GLib
+from gi.repository import IBus
+
+import segment
+
+_THUMB_BASIC_METHOD = 'base'
+
+_table_static = {
+ 'q': ['。', '', 'ぁ'],
+ 'w': ['か', 'が', 'え'],
+ 'e': ['た', 'だ', 'り'],
+ 'r': ['こ', 'ご', 'ゃ'],
+ 't': ['さ', 'ざ', 'れ'],
+
+ 'y': ['ら', 'よ', 'ぱ'],
+ 'u': ['ち', 'に', 'ぢ'],
+ 'i': ['く', 'る', 'ぐ'],
+ 'o': ['つ', 'ま', 'づ'],
+ 'p': [',', 'ぇ', 'ぴ'],
+ '@': ['、', '', ''],
+ '[': ['゛', '゜', ''],
+
+ 'a': ['う', '', 'を'],
+ 's': ['し', 'じ', 'あ'],
+ 'd': ['て', 'で', 'な'],
+ 'f': ['け', 'げ', 'ゅ'],
+ 'g': ['せ', 'ぜ', 'も'],
+
+ 'h': ['は', 'み', 'ば'],
+ 'j': ['と', 'お', 'ど'],
+ 'k': ['き', 'の', 'ぎ'],
+ 'l': ['い', 'ょ', 'ぽ'],
+ ';': ['ん', 'っ', ''],
+
+ 'z': ['.', '', 'ぅ'],
+ 'x': ['ひ', 'び', 'ー'],
+ 'c': ['す', 'ず', 'ろ'],
+ 'v': ['ふ', 'ぶ', 'や'],
+ 'b': ['へ', 'べ', 'ぃ'],
+
+ 'n': ['め', 'ぬ', 'ぷ'],
+ 'm': ['そ', 'ゆ', 'ぞ'],
+ ',': ['ね', 'む', 'ぺ'],
+ '.': ['ほ', 'わ', 'ぼ'],
+ '/': ['・', 'ぉ', ''],
+
+ '1': ['1', '', '?'],
+ '2': ['2', '', '/'],
+ '4': ['4', '', '「'],
+ '5': ['5', '', '」'],
+
+ '6': ['6', '[', ''],
+ '7': ['7', ']', ''],
+ '8': ['8', '(', ''],
+ '9': ['9', ')', ''],
+ '\\': ['¥', '', ''],
+}
+
+_nicola_j_table_static = {
+ ':': [':', '', ''],
+ '@': ['、', '', ''],
+ '[': ['゛', '゜', ''],
+ ']': ['」', '', ''],
+ '8': ['8', '(', ''],
+ '9': ['9', ')', ''],
+ '0': ['0', '', ''],
+}
+
+_nicola_a_table_static = {
+ ':': [':', '', ''],
+ '@': ['@', '', ''],
+ '[': ['、', '', ''],
+ ']': ['゛', '゜', ''],
+ '8': ['8', '', ''],
+ '9': ['9', '(', ''],
+ '0': ['0', ')', ''],
+}
+
+_nicola_f_table_static = {
+ ':': ['、', '', ''],
+ '@': ['@', '', ''],
+ '[': ['゛', '゜', ''],
+ ']': ['」', '', ''],
+ '8': ['8', '(', ''],
+ '9': ['9', ')', ''],
+ '0': ['0', '', ''],
+}
+
+_kb231_j_fmv_table_static = {
+ '3': ['3', '', '~'],
+ '0': ['0', '『', ''],
+ '-': ['-', '』', ''],
+ '=': ['=', '', ''],
+}
+
+_kb231_a_fmv_table_static = {
+ '3': ['3', '', '~'],
+ '0': ['0', ')', ''],
+ '-': ['-', '『', ''],
+ '=': ['=', '』', ''],
+}
+
+_kb231_f_fmv_table_static = {
+ '3': ['3', '', '~'],
+ '0': ['0', '『', ''],
+ '-': ['-', '』', ''],
+ '=': ['=', '', ''],
+}
+
+_kb611_j_fmv_table_static = {
+ '`': ['‘', '', ''],
+ '^': ['々', '£', ''],
+ ':': [':', '', ''],
+ '@': ['、', '¢', ''],
+ '[': ['゛', '゜', ''],
+ # keysyms are same and keycodes depend on the platforms.
+ #'¥': [u'¥', u'¬', u''],
+ '\\': ['¥', '¦', ''],
+}
+
+_kb611_a_fmv_table_static = {
+ '`': ['々', '', '£'],
+ ':': [':', '', ''],
+ '@': ['@', '', ''],
+ '[': ['、', '¢', ''],
+ #'¥': [u'¥', u'¬', u''],
+ '\\': ['¥', '¦', ''],
+}
+
+_kb611_f_fmv_table_static = {
+ '`': ['‘', '', ''],
+ '^': ['々', '£', ''],
+ ':': ['、', '¢', ''],
+ '@': ['@', '', ''],
+ '[': ['゛', '゜', ''],
+ #'¥': [u'¥', u'¬', u''],
+ '\\': ['¥', '¦', ''],
+}
+
+_shift_table = {
+ 'H': 'ぱ',
+ 'X': 'ぴ',
+ 'V': 'ぷ',
+ 'B': 'ぺ',
+ '>': 'ぽ',
+}
+
+table_static = {}
+r_table_static = {}
+
+for k in list(_table_static.keys()):
+ table_static[ord(k)] = _table_static[k]
+ for c in _table_static[k]:
+ r_table_static[c] = k
+
+kana_voiced_consonant_rule = {
+ 'か゛' : 'が',
+ 'き゛' : 'ぎ',
+ 'く゛' : 'ぐ',
+ 'け゛' : 'げ',
+ 'こ゛' : 'ご',
+ 'さ゛' : 'ざ',
+ 'し゛' : 'じ',
+ 'す゛' : 'ず',
+ 'せ゛' : 'ぜ',
+ 'そ゛' : 'ぞ',
+ 'た゛' : 'だ',
+ 'ち゛' : 'ぢ',
+ 'つ゛' : 'づ',
+ 'て゛' : 'で',
+ 'と゛' : 'ど',
+ 'は゛' : 'ば',
+ 'ひ゛' : 'び',
+ 'ふ゛' : 'ぶ',
+ 'へ゛' : 'べ',
+ 'ほ゛' : 'ぼ',
+ 'は゜' : 'ぱ',
+ 'ひ゜' : 'ぴ',
+ 'ふ゜' : 'ぷ',
+ 'へ゜' : 'ぺ',
+ 'ほ゜' : 'ぽ',
+}
+
+_UNFINISHED_HIRAGANA = set('かきくけこさしすせそたちつてとはひふへほ')
+
+class ThumbShiftKeyboard:
+ def __init__(self, prefs=None):
+ self.__prefs = prefs
+ self.__table = table_static
+ self.__r_table = r_table_static
+ self.__shift_table = {}
+ self.__ls = 0
+ self.__rs = 0
+ self.__t1 = 0
+ self.__t2 = 0
+ self.__layout = 0
+ self.__fmv_extension = 2
+ self.__handakuten = False
+ self.__thumb_typing_rule_section_base = None
+ self.__thumb_typing_rule_section = None
+ self.__init_thumb_typing_rule()
+ self.__init_layout_table()
+ if self.__prefs != None:
+ self.reset()
+ self.__reset_shift_table(False)
+
+ def __init_thumb_typing_rule(self):
+ prefs = self.__prefs
+ if prefs == None:
+ self.__thumb_typing_rule_section = None
+ return
+ method = prefs.get_value('thumb_typing_rule', 'method')
+ if method == None:
+ method = _THUMB_BASIC_METHOD
+ self.__thumb_typing_rule_section_base = 'thumb_typing_rule'
+ self.__thumb_typing_rule_section = \
+ self.__thumb_typing_rule_section_base + '/' + method
+ if self.__thumb_typing_rule_section not in prefs.sections():
+ self.__thumb_typing_rule_section = None
+
+ def __init_layout_table(self):
+ if self.__table != {}:
+ self.__table.clear()
+ if self.__r_table != {}:
+ self.__r_table.clear()
+ section_base = self.__thumb_typing_rule_section_base
+ section = self.__thumb_typing_rule_section
+ if section != None:
+ prefs = self.__prefs
+ for k in prefs.keys(section):
+ value = prefs.get_value(section, k)
+ ch = prefs.typing_from_config_key(k)
+ if ch == '':
+ continue
+ self.__set_bus_table(ch, value)
+ for k in prefs.get_value(section_base, 'newkeys'):
+ value = prefs.get_value_direct(section, k)
+ ch = prefs.typing_from_config_key(k)
+ if ch == '':
+ continue
+ self.__set_bus_table(ch, value)
+ else:
+ for k in list(_table.keys()):
+ self.__table[ord(k)] = _table_static[k]
+ for c in _table_static[k]:
+ self.__r_table[c] = k
+
+ def __set_bus_table(self, key, value):
+ prefs = self.__prefs
+ if value == None or len(value) != 3:
+ return
+ if value[0] == '' and \
+ value[1] == '' and value[2] == '':
+ return
+ self.__table[ord(key)] = value
+ for c in value:
+ self.__r_table[c] = key
+
+ def __reset_layout_table(self, init,
+ j_table_label, j_table,
+ a_table_label, a_table,
+ f_table_label, f_table):
+ if init:
+ self.__init_layout_table()
+ method = None
+ sub_table = None
+ if self.__layout == 0:
+ method = j_table_label
+ sub_table = j_table
+ elif self.__layout == 1:
+ method = a_table_label
+ sub_table = a_table
+ elif self.__layout == 2:
+ method = f_table_label
+ sub_table = f_table
+ if method == None or sub_table == None:
+ return
+ section_base = self.__thumb_typing_rule_section_base
+ section = self.__thumb_typing_rule_section
+ sub_section = section_base + '/' + method
+ if section != None:
+ prefs = self.__prefs
+ for k in prefs.keys(sub_section):
+ value = prefs.get_value(sub_section, k)
+ ch = prefs.typing_from_config_key(k)
+ if ch == '':
+ continue
+ self.__set_bus_table(ch, value)
+ for k in prefs.get_value(section_base, method + '_newkeys'):
+ value = prefs.get_value_direct(sub_section, k)
+ ch = prefs.typing_from_config_key(k)
+ if ch == '':
+ continue
+ self.__set_bus_table(ch, value)
+ else:
+ for k in list(sub_table.keys()):
+ self.__table[ord(str(k))] = sub_table[k]
+ for c in sub_table[k]:
+ self.__r_table[c] = k
+
+ def __reset_extension_table(self, init):
+ self.__reset_layout_table(init,
+ 'nicola_j_table',
+ _nicola_j_table_static,
+ 'nicola_a_table',
+ _nicola_a_table_static,
+ 'nicola_f_table',
+ _nicola_f_table_static)
+ if self.__fmv_extension == 0:
+ return
+ if self.__fmv_extension >= 1:
+ self.__reset_layout_table(False,
+ 'kb231_j_fmv_table',
+ _kb231_j_fmv_table_static,
+ 'kb231_a_fmv_table',
+ _kb231_a_fmv_table_static,
+ 'kb231_f_fmv_table',
+ _kb231_f_fmv_table_static)
+ if self.__fmv_extension >= 2:
+ self.__reset_layout_table(False,
+ 'kb611_j_fmv_table',
+ _kb611_j_fmv_table_static,
+ 'kb611_a_fmv_table',
+ _kb611_a_fmv_table_static,
+ 'kb611_f_fmv_table',
+ _kb611_f_fmv_table_static)
+
+ def __reset_shift_table(self, init):
+ self.__reset_extension_table(init)
+ if self.__handakuten:
+ for k in list(_shift_table.keys()):
+ self.__shift_table[ord(k)] = _shift_table[k]
+ self.__r_table[_shift_table[k]] = k
+ elif self.__shift_table != {}:
+ for k in list(_shift_table.keys()):
+ if ord(k) in self.__shift_table:
+ del self.__shift_table[ord(k)]
+ if _shift_table[k] in self.__r_table:
+ del self.__r_table[_shift_table[k]]
+
+ def __s_to_key_raw(self, s):
+ keyval = IBus.keyval_from_name(s.split('+')[-1])
+ s = s.lower()
+ state = ('shift+' in s and IBus.ModifierType.SHIFT_MASK or 0) | (
+ 'ctrl+' in s and IBus.ModifierType.CONTROL_MASK or 0) | (
+ 'alt+' in s and IBus.ModifierType.MOD1_MASK or 0)
+ return (keyval, state)
+
+ def __get_xkb_layout(self):
+ # Until Gdk.property_get is fixed
+ '''
+ # Move importing Gdk into ThumbShiftKeyboard from the header
+ # because ibus-engine-anthy --xml does not requre to open X.
+ try:
+ from gi.repository import Gdk
+ get_default_root_window = Gdk.get_default_root_window
+ property_get = Gdk.property_get
+ intern = Gdk.Atom.intern
+ except ImportError:
+ get_default_root_window = lambda : None
+ property_get = lambda : None
+ intern = lambda : None
+ except RuntimeError:
+ # Do we support the engine without display?
+ print >> sys.stderr, "Gdk couldn't be initialized"
+ print >> sys.stderr, 'Could not open display'
+ get_default_root_window = lambda : None
+ property_get = lambda : None
+ intern = lambda : None
+
+ root_window = get_default_root_window()
+ if not root_window:
+ return 0
+ xkb_rules_names = intern('_XKB_RULES_NAMES', False)
+ xa_string = intern('STRING', False)
+ try:
+ prop = property_get(root_window,
+ xkb_rules_names, xa_string,
+ 0, 1024, 0)[3]
+ layout_list = prop.split('\0')
+ except TypeError:
+ import sys
+ print >> sys.stderr, \
+ 'This problem is fixed in the latest gobject-introspection'
+ print >> sys.stderr, \
+ 'https://bugzilla.gnome.org/show_bug.cgi?id=670509'
+ return 0
+ layout = 0
+ for data in layout_list:
+ if data == 'jp':
+ layout = 0
+ elif data == 'us':
+ layout = 1
+ elif data.find('japan:nicola_f_bs') >= 0:
+ layout = 2
+ elif data.find('japan:') >= 0:
+ layout = 0
+ return layout
+ '''
+
+ layout = 0
+ argv = ['setxkbmap', '-query']
+ (ret, std_out, std_error, exit_status) = \
+ GLib.spawn_sync(None, argv, None,
+ GLib.SpawnFlags.SEARCH_PATH_FROM_ENVP,
+ None, None)
+ if not ret:
+ print(std_error, file=sys.stderr)
+ return layout
+ for line in std_out.split('\n'):
+ if line.startswith('layout:'):
+ data = line.split()[1]
+ if data == 'jp':
+ layout = 0
+ elif data == 'us':
+ layout = 1
+ elif line.startswith('options:'):
+ data = line.split()[1]
+ if data.find('japan:nicola_f_bs') >= 0:
+ layout = 2
+ elif data.find('japan:') >= 0:
+ layout = 0
+ return 0
+
+ def __reset_layout_and_handakuten(self):
+ mode = self.__prefs.get_value('thumb', 'keyboard_layout_mode')
+ layout = 0
+ if mode == 1:
+ layout = self.__get_xkb_layout()
+ else:
+ layout = self.__prefs.get_value('thumb', 'keyboard_layout')
+ self.set_layout(layout)
+
+ fmv_extension = self.__prefs.get_value('thumb', 'fmv_extension')
+ self.set_fmv_extension(fmv_extension)
+ handakuten = self.__prefs.get_value('thumb', 'handakuten')
+ self.set_handakuten(handakuten)
+
+ def reset(self):
+ s = self.__prefs.get_value('thumb', 'ls')
+ ls, state = self.__s_to_key_raw(s)
+ if ls == 0xffffff:
+ ls = IBus.KEY_Muhenkan
+ self.set_ls(ls)
+
+ s = self.__prefs.get_value('thumb', 'rs')
+ rs, state = self.__s_to_key_raw(s)
+ if rs == 0xffffff:
+ rs = IBus.KEY_Henkan
+ self.set_rs(rs)
+
+ t1 = self.__prefs.get_value('thumb', 't1')
+ t2 = self.__prefs.get_value('thumb', 't2')
+ self.set_t1(t1)
+ self.set_t2(t2)
+
+ GLib.idle_add(self.__reset_layout_and_handakuten,
+ priority = GLib.PRIORITY_LOW)
+
+ def get_ls(self):
+ return self.__ls
+
+ def set_ls(self, ls):
+ self.__ls = ls
+
+ def get_rs(self):
+ return self.__rs
+
+ def set_rs(self, rs):
+ self.__rs = rs
+
+ def get_t1(self):
+ return self.__t1
+
+ def set_t1(self, t1):
+ self.__t1 = t1
+
+ def get_t2(self):
+ return self.__t2
+
+ def set_t2(self, t2):
+ self.__t2 = t2
+
+ def get_layout(self):
+ return self.__layout
+
+ def set_layout(self, layout):
+ if self.__layout == layout:
+ return
+ self.__layout = layout
+ self.__reset_shift_table(True)
+
+ def get_fmv_extension (self):
+ return self.__fmv_extension
+
+ def set_fmv_extension (self, fmv_extension):
+ if self.__fmv_extension == fmv_extension:
+ return
+ self.__fmv_extension = fmv_extension
+ self.__reset_shift_table(True)
+
+ def get_handakuten(self):
+ return self.__handakuten
+
+ def set_handakuten(self, handakuten):
+ if self.__handakuten == handakuten:
+ return
+ self.__handakuten = handakuten
+ self.__reset_shift_table(True)
+
+ def get_char(self, key, fallback=None):
+ return self.__table.get(key, fallback)
+
+ def get_chars(self):
+ return list(self.__table.keys())
+
+ def get_r_char(self, key, fallback=None):
+ return self.__r_table.get(key, fallback)
+
+ def get_r_chars(self):
+ return list(self.__r_table.keys())
+
+ def get_shift_char(self, key, fallback=None):
+ return self.__shift_table.get(key, fallback)
+
+ def get_shift_chars(self):
+ return list(self.__shift_table.keys())
+
+
+class ThumbShiftSegment(segment.Segment):
+ _prefs = None
+ _thumb_typing_rule_section_base = None
+ _thumb_typing_rule_section = None
+ _r_table = {}
+
+ def __init__(self, enchars='', jachars=''):
+ if not jachars:
+ if '!' <= enchars <= '~':
+ jachars = segment.unichar_half_to_full(enchars)
+ else:
+ jachars = enchars
+ enchars = self._r_table.get(jachars, '')
+ super(ThumbShiftSegment, self).__init__(enchars, jachars)
+
+ @classmethod
+ def INIT_THUMB_TYPING_RULE(cls, prefs):
+ cls._prefs = prefs
+ if prefs == None:
+ cls._thumb_typing_rule_section = None
+ return
+ method = prefs.get_value('thumb_typing_rule', 'method')
+ if method == None:
+ method = _THUMB_BASIC_METHOD
+ cls._thumb_typing_rule_section_base = 'thumb_typing_rule'
+ cls._thumb_typing_rule_section = \
+ cls._thumb_typing_rule_section_base + '/' + method
+ if cls._thumb_typing_rule_section not in prefs.sections():
+ cls._thumb_typing_rule_section = None
+ cls._init_layout_table()
+
+ @classmethod
+ def _init_layout_table(cls):
+ if cls._r_table != {}:
+ cls._r_table.clear()
+ section_base = cls._thumb_typing_rule_section_base
+ section = cls._thumb_typing_rule_section
+ if section != None:
+ prefs = cls._prefs
+ for k in prefs.keys(section):
+ value = prefs.get_value(section, k)
+ ch = prefs.typing_from_config_key(k)
+ if ch == '':
+ continue
+ cls._set_bus_table(ch, value)
+ for k in prefs.get_value(section_base, 'newkeys'):
+ value = prefs.get_value_direct(section, k)
+ ch = prefs.typing_from_config_key(k)
+ if ch == '':
+ continue
+ cls._set_bus_table(ch, value)
+ else:
+ for k in list(_table.keys()):
+ for c in _table_static[k]:
+ cls._r_table[c] = k
+
+ @classmethod
+ def _set_bus_table(cls, key, value):
+ prefs = cls._prefs
+ if value == None or len(value) != 3:
+ return
+ if value[0] == '' and \
+ value[1] == '' and value[2] == '':
+ return
+ for c in value:
+ cls._r_table[c] = key
+
+ def is_finished(self):
+ return not (self._jachars in _UNFINISHED_HIRAGANA)
+
+ def append(self, enchar):
+ if enchar == '\0' or enchar == '':
+ return []
+ text = self._jachars + enchar
+ jachars = kana_voiced_consonant_rule.get(text, None)
+ if jachars:
+ self._enchars = self._enchars + self._r_table.get(enchar, '')
+ self._jachars = jachars
+ return []
+ return [ThumbShiftSegment(enchar)]
+
+ def prepend(self, enchar):
+ if enchar == '\0' or enchar == '':
+ return []
+ if self._jachars == '':
+ if 0x21 <= enchars <= 0x7e:
+ self._enchars = enchar
+ self._jachars = segment.unichar_half_to_full(enchars)
+ else:
+ self._enchars = self._r_table.get(enchar, '')
+ self._jachars = enchar
+ return []
+ return [ThumbShiftSegment(enchar)]
+
+ def pop(self, index=-1):
+ self._enchars = ''
+ self._jachars = ''
+ return
+
diff --git a/setup/Makefile.am b/setup/Makefile.am
index f1a8e8d..3c64425 100644
--- a/setup/Makefile.am
+++ b/setup/Makefile.am
@@ -2,10 +2,8 @@
#
# ibus-anthy - The Anthy engine for IBus
#
-# Copyright (c) 2007-2008 Peng Huang <shawn.p.huang@gmail.com>
-# Copyright (c) 2009 Hideaki ABE <abe.sendai@gmail.com>
-# Copyright (c) 2010-2013 Takao Fujiwara <takao.fujiwara1@gmail.com>
-# Copyright (c) 2007-2013 Red Hat, Inc.
+# Copyright (c) 2014 Takao Fujiwara <takao.fujiwara1@gmail.com>
+# Copyright (c) 2014 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -21,96 +19,12 @@
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-desktop_in_in_files = ibus-setup-anthy.desktop.in.in
-desktop_in_files = $(desktop_in_in_files:.in.in=.in)
+SUBDIRS =
-$(desktop_in_files): %.desktop.in: %.desktop.in.in Makefile
- $(AM_V_GEN) sed \
- -e "s|\@libexecdir\@|$(libexecdir)|" \
- -e "s|\@pkgdatadir\@|$(pkgdatadir)|" \
- $< > $@.tmp && mv $@.tmp $@
-
-desktopdir=$(datadir)/applications
-desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
-
-@INTLTOOL_DESKTOP_RULE@
-
-BUILT_SOURCES = \
- _config.py \
- anthyprefs.py \
- $(NULL)
-
-libexec_SCRIPTS = ibus-setup-anthy
-
-setup_anthy_PYTHON = \
- _config.py \
- anthyprefs.py \
- main.py \
- prefs.py \
- setup.ui \
- $(NULL)
-
-setup_anthy_built_files = \
- $(BUILT_SOURCES) \
- $(libexec_SCRIPTS) \
- $(NULL)
-
-setup_anthy_built_in_files = $(addsuffix .in, $(setup_anthy_built_files))
-
-setup_anthydir = $(datadir)/ibus-anthy/setup
-
-CONFIG_CLEAN_FILES = \
- $(BUILT_SOURCES) \
- $(libexec_SCRIPTS) \
- $(NULL)
-
-CLEANFILES = \
- $(BUILT_SOURCES) \
- $(desktop_DATA) \
- $(desktop_in_files) \
- *.pyc \
- $(NULL)
-
-EXTRA_DIST = \
- $(desktop_in_in_files) \
- $(setup_anthy_built_in_files) \
- $(NULL)
-
-anthyprefs.py: anthyprefs.py.in
- sed -e "s|\@ANTHY_ZIPCODE_FILE\@|$(ANTHY_ZIPCODE_FILE)|g" \
- -e "s|\@KASUMI_EXEC_FILE\@|$(KASUMI_EXEC_FILE)|g" \
- -e "s|\@KASUMI_ICON_FILE\@|$(KASUMI_ICON_FILE)|g" \
- -e "s|\@ON_OFF_KEYS\@|$(ON_OFF_KEYS)|g" \
- -e "s|\@VERSION\@|$(VERSION)|g" \
- -e "s|\@pkgdatadir\@|$(pkgdatadir)|g" \
- $< > $@
-
-_config.py: _config.py.in
- ( \
- PKGDATADIR=$(pkgdatadir); \
- LIBEXECDIR=$(libexecdir); \
- DATADIR=$(datadir); \
- LAYOUT=$(LAYOUT); \
- SYMBOL_CHAR_INT=$(SYMBOL_CHAR_INT); \
- ICON_PREFERENCE=$(ICON_PREFERENCE); \
- s=`cat $<`; \
- eval "echo \"$${s}\""; \
- ) > $@
-
-# Need a time lag between .py and .py.in files to build .py files
-# because *_PYTHON valuables are installed in the tarball.
-dist-hook:
- @sleep 1; \
- for in_file in $(setup_anthy_built_in_files) ; do \
- if [ -f $(distdir)/$(srcdir)/$$in_file ] ; then \
- touch $(distdir)/$(srcdir)/$$in_file; \
- fi; \
- done;
-
-test:
- $(ENV_IBUS_TEST) DBUS_DEBUG=true \
- LANG=en_US \
- PYTHONPATH=$(abs_top_srcdir):$(pyexecdir) \
- IBUS_LOCALEDIR=@localedir@ \
- $(PYTHON) $(srcdir)/main.py
+if ENABLE_PYTHON2
+SUBDIRS += python2
+endif
+if ENABLE_PYTHON3
+SUBDIRS += python3
+endif
diff --git a/setup/_config.py.in b/setup/_config.py.in
deleted file mode 120000
index d646d61..0000000
--- a/setup/_config.py.in
+++ /dev/null
@@ -1 +0,0 @@
-../engine/_config.py.in \ No newline at end of file
diff --git a/setup/python2/Makefile.am b/setup/python2/Makefile.am
new file mode 100644
index 0000000..f1a8e8d
--- /dev/null
+++ b/setup/python2/Makefile.am
@@ -0,0 +1,116 @@
+# vim:set noet ts=4:
+#
+# ibus-anthy - The Anthy engine for IBus
+#
+# Copyright (c) 2007-2008 Peng Huang <shawn.p.huang@gmail.com>
+# Copyright (c) 2009 Hideaki ABE <abe.sendai@gmail.com>
+# Copyright (c) 2010-2013 Takao Fujiwara <takao.fujiwara1@gmail.com>
+# Copyright (c) 2007-2013 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+desktop_in_in_files = ibus-setup-anthy.desktop.in.in
+desktop_in_files = $(desktop_in_in_files:.in.in=.in)
+
+$(desktop_in_files): %.desktop.in: %.desktop.in.in Makefile
+ $(AM_V_GEN) sed \
+ -e "s|\@libexecdir\@|$(libexecdir)|" \
+ -e "s|\@pkgdatadir\@|$(pkgdatadir)|" \
+ $< > $@.tmp && mv $@.tmp $@
+
+desktopdir=$(datadir)/applications
+desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
+
+@INTLTOOL_DESKTOP_RULE@
+
+BUILT_SOURCES = \
+ _config.py \
+ anthyprefs.py \
+ $(NULL)
+
+libexec_SCRIPTS = ibus-setup-anthy
+
+setup_anthy_PYTHON = \
+ _config.py \
+ anthyprefs.py \
+ main.py \
+ prefs.py \
+ setup.ui \
+ $(NULL)
+
+setup_anthy_built_files = \
+ $(BUILT_SOURCES) \
+ $(libexec_SCRIPTS) \
+ $(NULL)
+
+setup_anthy_built_in_files = $(addsuffix .in, $(setup_anthy_built_files))
+
+setup_anthydir = $(datadir)/ibus-anthy/setup
+
+CONFIG_CLEAN_FILES = \
+ $(BUILT_SOURCES) \
+ $(libexec_SCRIPTS) \
+ $(NULL)
+
+CLEANFILES = \
+ $(BUILT_SOURCES) \
+ $(desktop_DATA) \
+ $(desktop_in_files) \
+ *.pyc \
+ $(NULL)
+
+EXTRA_DIST = \
+ $(desktop_in_in_files) \
+ $(setup_anthy_built_in_files) \
+ $(NULL)
+
+anthyprefs.py: anthyprefs.py.in
+ sed -e "s|\@ANTHY_ZIPCODE_FILE\@|$(ANTHY_ZIPCODE_FILE)|g" \
+ -e "s|\@KASUMI_EXEC_FILE\@|$(KASUMI_EXEC_FILE)|g" \
+ -e "s|\@KASUMI_ICON_FILE\@|$(KASUMI_ICON_FILE)|g" \
+ -e "s|\@ON_OFF_KEYS\@|$(ON_OFF_KEYS)|g" \
+ -e "s|\@VERSION\@|$(VERSION)|g" \
+ -e "s|\@pkgdatadir\@|$(pkgdatadir)|g" \
+ $< > $@
+
+_config.py: _config.py.in
+ ( \
+ PKGDATADIR=$(pkgdatadir); \
+ LIBEXECDIR=$(libexecdir); \
+ DATADIR=$(datadir); \
+ LAYOUT=$(LAYOUT); \
+ SYMBOL_CHAR_INT=$(SYMBOL_CHAR_INT); \
+ ICON_PREFERENCE=$(ICON_PREFERENCE); \
+ s=`cat $<`; \
+ eval "echo \"$${s}\""; \
+ ) > $@
+
+# Need a time lag between .py and .py.in files to build .py files
+# because *_PYTHON valuables are installed in the tarball.
+dist-hook:
+ @sleep 1; \
+ for in_file in $(setup_anthy_built_in_files) ; do \
+ if [ -f $(distdir)/$(srcdir)/$$in_file ] ; then \
+ touch $(distdir)/$(srcdir)/$$in_file; \
+ fi; \
+ done;
+
+test:
+ $(ENV_IBUS_TEST) DBUS_DEBUG=true \
+ LANG=en_US \
+ PYTHONPATH=$(abs_top_srcdir):$(pyexecdir) \
+ IBUS_LOCALEDIR=@localedir@ \
+ $(PYTHON) $(srcdir)/main.py
+
diff --git a/setup/python2/_config.py.in b/setup/python2/_config.py.in
new file mode 120000
index 0000000..a064604
--- /dev/null
+++ b/setup/python2/_config.py.in
@@ -0,0 +1 @@
+../../engine/python2/_config.py.in \ No newline at end of file
diff --git a/setup/anthyprefs.py.in b/setup/python2/anthyprefs.py.in
index a685da1..a685da1 100644
--- a/setup/anthyprefs.py.in
+++ b/setup/python2/anthyprefs.py.in
diff --git a/setup/ibus-setup-anthy.desktop.in.in b/setup/python2/ibus-setup-anthy.desktop.in.in
index 1dd35f9..1dd35f9 100644
--- a/setup/ibus-setup-anthy.desktop.in.in
+++ b/setup/python2/ibus-setup-anthy.desktop.in.in
diff --git a/setup/ibus-setup-anthy.in b/setup/python2/ibus-setup-anthy.in
index f8832fd..f8832fd 100644
--- a/setup/ibus-setup-anthy.in
+++ b/setup/python2/ibus-setup-anthy.in
diff --git a/setup/main.py b/setup/python2/main.py
index 98486ad..98486ad 100644
--- a/setup/main.py
+++ b/setup/python2/main.py
diff --git a/setup/prefs.py b/setup/python2/prefs.py
index 1b88908..1b88908 100644
--- a/setup/prefs.py
+++ b/setup/python2/prefs.py
diff --git a/setup/setup.ui b/setup/python2/setup.ui
index d9ec626..d9ec626 100644
--- a/setup/setup.ui
+++ b/setup/python2/setup.ui
diff --git a/setup/python3/Makefile.am b/setup/python3/Makefile.am
new file mode 100644
index 0000000..f1a8e8d
--- /dev/null
+++ b/setup/python3/Makefile.am
@@ -0,0 +1,116 @@
+# vim:set noet ts=4:
+#
+# ibus-anthy - The Anthy engine for IBus
+#
+# Copyright (c) 2007-2008 Peng Huang <shawn.p.huang@gmail.com>
+# Copyright (c) 2009 Hideaki ABE <abe.sendai@gmail.com>
+# Copyright (c) 2010-2013 Takao Fujiwara <takao.fujiwara1@gmail.com>
+# Copyright (c) 2007-2013 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+desktop_in_in_files = ibus-setup-anthy.desktop.in.in
+desktop_in_files = $(desktop_in_in_files:.in.in=.in)
+
+$(desktop_in_files): %.desktop.in: %.desktop.in.in Makefile
+ $(AM_V_GEN) sed \
+ -e "s|\@libexecdir\@|$(libexecdir)|" \
+ -e "s|\@pkgdatadir\@|$(pkgdatadir)|" \
+ $< > $@.tmp && mv $@.tmp $@
+
+desktopdir=$(datadir)/applications
+desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
+
+@INTLTOOL_DESKTOP_RULE@
+
+BUILT_SOURCES = \
+ _config.py \
+ anthyprefs.py \
+ $(NULL)
+
+libexec_SCRIPTS = ibus-setup-anthy
+
+setup_anthy_PYTHON = \
+ _config.py \
+ anthyprefs.py \
+ main.py \
+ prefs.py \
+ setup.ui \
+ $(NULL)
+
+setup_anthy_built_files = \
+ $(BUILT_SOURCES) \
+ $(libexec_SCRIPTS) \
+ $(NULL)
+
+setup_anthy_built_in_files = $(addsuffix .in, $(setup_anthy_built_files))
+
+setup_anthydir = $(datadir)/ibus-anthy/setup
+
+CONFIG_CLEAN_FILES = \
+ $(BUILT_SOURCES) \
+ $(libexec_SCRIPTS) \
+ $(NULL)
+
+CLEANFILES = \
+ $(BUILT_SOURCES) \
+ $(desktop_DATA) \
+ $(desktop_in_files) \
+ *.pyc \
+ $(NULL)
+
+EXTRA_DIST = \
+ $(desktop_in_in_files) \
+ $(setup_anthy_built_in_files) \
+ $(NULL)
+
+anthyprefs.py: anthyprefs.py.in
+ sed -e "s|\@ANTHY_ZIPCODE_FILE\@|$(ANTHY_ZIPCODE_FILE)|g" \
+ -e "s|\@KASUMI_EXEC_FILE\@|$(KASUMI_EXEC_FILE)|g" \
+ -e "s|\@KASUMI_ICON_FILE\@|$(KASUMI_ICON_FILE)|g" \
+ -e "s|\@ON_OFF_KEYS\@|$(ON_OFF_KEYS)|g" \
+ -e "s|\@VERSION\@|$(VERSION)|g" \
+ -e "s|\@pkgdatadir\@|$(pkgdatadir)|g" \
+ $< > $@
+
+_config.py: _config.py.in
+ ( \
+ PKGDATADIR=$(pkgdatadir); \
+ LIBEXECDIR=$(libexecdir); \
+ DATADIR=$(datadir); \
+ LAYOUT=$(LAYOUT); \
+ SYMBOL_CHAR_INT=$(SYMBOL_CHAR_INT); \
+ ICON_PREFERENCE=$(ICON_PREFERENCE); \
+ s=`cat $<`; \
+ eval "echo \"$${s}\""; \
+ ) > $@
+
+# Need a time lag between .py and .py.in files to build .py files
+# because *_PYTHON valuables are installed in the tarball.
+dist-hook:
+ @sleep 1; \
+ for in_file in $(setup_anthy_built_in_files) ; do \
+ if [ -f $(distdir)/$(srcdir)/$$in_file ] ; then \
+ touch $(distdir)/$(srcdir)/$$in_file; \
+ fi; \
+ done;
+
+test:
+ $(ENV_IBUS_TEST) DBUS_DEBUG=true \
+ LANG=en_US \
+ PYTHONPATH=$(abs_top_srcdir):$(pyexecdir) \
+ IBUS_LOCALEDIR=@localedir@ \
+ $(PYTHON) $(srcdir)/main.py
+
diff --git a/setup/python3/_config.py.in b/setup/python3/_config.py.in
new file mode 120000
index 0000000..5f5764f
--- /dev/null
+++ b/setup/python3/_config.py.in
@@ -0,0 +1 @@
+../../engine/python3/_config.py.in \ No newline at end of file
diff --git a/setup/python3/anthyprefs.py.in b/setup/python3/anthyprefs.py.in
new file mode 100644
index 0000000..53c9d1d
--- /dev/null
+++ b/setup/python3/anthyprefs.py.in
@@ -0,0 +1,1329 @@
+# -*- coding: utf-8 -*-
+# vim:set noet ts=4:
+#
+# ibus-anthy - The Anthy engine for IBus
+#
+# Copyright (c) 2007-2008 Peng Huang <shawn.p.huang@gmail.com>
+# Copyright (c) 2009 Hideaki ABE <abe.sendai@gmail.com>
+# Copyright (c) 2010-2014 Takao Fujiwara <takao.fujiwara1@gmail.com>
+# Copyright (c) 2007-2014 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+import sys
+
+from prefs import Prefs
+
+N_ = lambda a : a
+
+__all__ = ['AnthyPrefs']
+
+
+class AnthyPrefs(Prefs):
+ _prefix = 'engine/anthy'
+ _char_to_config_key = None
+
+ def __init__(self, bus=None, config=None):
+ super(AnthyPrefs, self).__init__(bus, config)
+ if _config != None:
+ self.default = _config
+ self.set_no_key_warning(True)
+ self.fetch_all()
+ self.set_no_key_warning(False)
+
+ def __update_key (self, section, old_key, new_key):
+ file = __file__
+ if __file__.find('/') >= 0:
+ file = __file__[__file__.rindex('/') + 1:]
+ warning_message = \
+ '(' + file + ') ibus-anthy-WARNING **: ' \
+ 'The key (' + old_key + ') will be removed in the future. ' \
+ 'Currently the key (' + new_key + ') is used instead. ' \
+ 'The ibus keys are defined in ' + \
+ '/'.join(['/desktop/ibus', self._prefix, section]) + ' .'
+
+ if not self.fetch_item(section, old_key, True):
+ return
+ print(warning_message, file=sys.stderr)
+ if self.fetch_item(section, new_key, True):
+ return
+
+ self.fetch_item(section, old_key)
+ value = self.get_value(section, old_key)
+ self.set_value(section, new_key, value)
+ self.commit_item(section, new_key)
+ self.undo_item(section, new_key)
+
+ def keys(self, section):
+ if section.startswith('shortcut/'):
+ return _cmd_keys
+ return list(self.default[section].keys())
+
+ def get_japanese_ordered_list(self):
+ return _japanese_ordered_list
+
+ def get_version(self):
+ return '@VERSION@'
+
+ # Convert typing sequences to gsettings key.
+ # E.g. 'largea-bracketleft' to 'A['
+ def typing_from_config_key(self, gkeys):
+ retval = ''
+ for key in gkeys.split('-'):
+ if key in _supported_gsettings_key_chars:
+ retval += key
+ continue
+ try:
+ ch = _config_key_to_char[key]
+ except KeyError:
+ print('Not supported key in gsettings', gkeys, file=sys.stderr)
+ retval = ''
+ break
+ retval += ch
+ return retval
+
+ # Convert typing sequences to gsettings key.
+ # E.g. 'A[' to 'largea-bracketleft'
+ def typing_to_config_key(self, typing):
+ retval = ''
+ if self._char_to_config_key == None:
+ self._char_to_config_key = {}
+ for _key, _ch in list(_config_key_to_char.items()):
+ self._char_to_config_key[_ch] = _key
+ for ch in typing:
+ if ch in _supported_gsettings_key_chars:
+ if retval != '':
+ retval += '-'
+ retval += ch
+ continue
+ try:
+ key = self._char_to_config_key[ch]
+ except KeyError:
+ print('Not supported key in gsettings', typing, file=sys.stderr)
+ retval = ''
+ break
+ if retval != '':
+ retval += '-'
+ retval += key
+ return retval
+
+# Sad! dict.keys() doesn't return the saved order.
+# locale.strcoll() also just returns the Unicode code point.
+# Unicode order is wrong in Japanese large 'a' and small 'a'.
+# The workaround is to save the order here...
+_japanese_ordered_list = [
+ 'あ', 'い', 'う', 'え', 'お',
+ 'ぁ', 'ぃ', 'ぅ', 'ぇ', 'ぉ',
+ 'いぇ',
+ 'うぁ', 'うぃ', 'うぅ', 'うぇ', 'うぉ',
+ 'うゃ', 'うゅ', 'うょ',
+ 'か', 'き', 'く', 'け', 'こ',
+ 'ゕ', 'ゖ', 'ヵ', 'ヶ',
+ 'が', 'ぎ', 'ぐ', 'げ', 'ご',
+ 'きゃ', 'きぃ', 'きゅ', 'きぇ', 'きょ',
+ 'くぁ', 'くぃ', 'くぅ', 'くぇ', 'くぉ',
+ 'ぎゃ', 'ぎぃ', 'ぎゅ', 'ぎぇ', 'ぎょ',
+ 'ぐぁ', 'ぐぃ', 'ぐぅ', 'ぐぇ', 'ぐぉ',
+ 'さ', 'し', 'す', 'せ', 'そ',
+ 'ざ', 'じ', 'ず', 'ぜ', 'ぞ',
+ 'しゃ', 'しぃ', 'しゅ', 'しぇ', 'しょ',
+ 'じゃ', 'じぃ', 'じゅ', 'じぇ', 'じょ',
+ 'すぅぃ', 'すぇ',
+ 'ずぇ',
+ 'た', 'ち', 'つ', 'て', 'と',
+ 'だ', 'ぢ', 'づ', 'で', 'ど',
+ 'っ',
+ 'ちゃ', 'ちぃ', 'ちゅ', 'ちぇ', 'ちょ',
+ 'ぢぃ', 'ぢぇ',
+ 'ぢゃ', 'ぢゅ', 'ぢょ',
+ 'つぁ', 'つぃ', 'つぇ', 'つぉ',
+ 'つゃ', 'つぃぇ', 'つゅ', 'つょ',
+ 'づぁ', 'づぃ', 'づぇ', 'づぉ',
+ 'づゃ', 'づぃぇ', 'づゅ', 'づょ',
+ 'てぃ', 'てぇ',
+ 'てゃ', 'てゅ', 'てょ',
+ 'とぅ',
+ 'でぃ', 'でぇ',
+ 'でゃ', 'でゅ', 'でょ',
+ 'どぅ',
+ 'な', 'に', 'ぬ', 'ね', 'の',
+ 'にぃ', 'にぇ',
+ 'にゃ', 'にゅ', 'にょ',
+ 'は', 'ひ', 'ふ', 'へ', 'ほ',
+ 'ば', 'び', 'ぶ', 'べ', 'ぼ',
+ 'ぱ', 'ぴ', 'ぷ', 'ぺ', 'ぽ',
+ 'ひぃ', 'ひぇ',
+ 'ひゃ', 'ひゅ', 'ひょ',
+ 'びぃ', 'びぇ',
+ 'びゃ', 'びゅ', 'びょ',
+ 'ぴぃ', 'ぴぇ',
+ 'ぴゃ', 'ぴゅ', 'ぴょ',
+ 'ふぁ', 'ふぃ', 'ふぇ', 'ふぉ',
+ 'ふゃ', 'ふゅ', 'ふょ',
+ 'ぶぁ', 'ぶぇ', 'ぶぉ',
+ 'ぷぁ', 'ぷぇ', 'ぷぉ',
+ 'ま', 'み', 'む', 'め', 'も',
+ 'みぃ', 'みぇ',
+ 'みゃ', 'みゅ', 'みょ',
+ 'や', 'ゆ', 'よ',
+ 'ゃ', 'ゅ', 'ょ',
+ 'ら', 'り', 'る', 'れ', 'ろ',
+ 'りぃ', 'りぇ',
+ 'りゃ', 'りゅ', 'りょ',
+ 'わ', 'を', 'ん',
+ 'ゎ',
+ 'ゐ', 'ゑ',
+ 'ー',
+ 'ヴぁ', 'ヴぃ', 'ヴ', 'ヴぇ', 'ヴぉ',
+ 'ヴゃ', 'ヴぃぇ', 'ヴゅ', 'ヴょ',
+]
+
+# http://git.gnome.org/browse/glib/tree/gio/glib-compile-schemas.c#n765
+# gsettings supports keys named by "abcdefghijklmnopqrstuvwxyz0123456789-"
+# and ibus-anthy uses '-' as the delimiter.
+_supported_gsettings_key_chars = "abcdefghijklmnopqrstuvwxyz0123456789"
+
+_config_key_to_char = {
+ # no modifiers keys
+ 'minus' : '-',
+ 'asciicircum' : '^',
+ 'at' : '@',
+ 'bracketleft' : '[',
+ 'semicolon' : ';',
+ 'colon' : ':',
+ 'bracketright' : ']',
+ 'comma' : ',',
+ 'period' : '.',
+ 'slash' : '/',
+ 'backslash' : '\\',
+
+ # shift modifiered keys
+ 'exclam' : '!',
+ 'quotedbl' : '"',
+ 'numbersign' : '#',
+ 'dollar' : '$',
+ 'percent' : '%',
+ 'ampersand' : '&',
+ 'apostrophe' : '\'',
+ 'parenleft' : '(',
+ 'parenright' : ')',
+ 'asciitilde' : '~',
+ 'equal' : '=',
+ 'bar' : '|',
+
+ 'largeq' : 'Q',
+ 'largew' : 'W',
+ 'largee' : 'E',
+ 'larger' : 'R',
+ 'larget' : 'T',
+ 'largey' : 'Y',
+ 'largeu' : 'U',
+ 'largei' : 'I',
+ 'largeo' : 'O',
+ 'largep' : 'P',
+ 'grave' : '`',
+
+ 'braceleft' : '{',
+
+ 'largea' : 'A',
+ 'larges' : 'S',
+ 'larged' : 'D',
+ 'largef' : 'F',
+ 'largeg' : 'G',
+ 'largeh' : 'H',
+ 'largej' : 'J',
+ 'largek' : 'K',
+ 'largel' : 'L',
+ 'plus' : '+',
+ 'asterisk' : '*',
+
+ 'braceright' : '}',
+
+ 'largez' : 'Z',
+ 'largex' : 'X',
+ 'largec' : 'C',
+ 'largev' : 'V',
+ 'largeb' : 'B',
+ 'largen' : 'N',
+ 'largem' : 'M',
+ 'less' : '<',
+ 'greater' : '>',
+
+ 'question' : '?',
+ 'underscore' : '_',
+
+ 'yen' : '¥',
+}
+
+_cmd_keys = [
+ 'on_off',
+ 'circle_input_mode',
+ 'circle_kana_mode',
+ 'circle_typing_method',
+ 'circle_dict_method',
+ 'latin_mode',
+ 'wide_latin_mode',
+ 'hiragana_mode',
+ 'katakana_mode',
+ 'half_katakana_mode',
+# 'cancel_pseudo_ascii_mode_key',
+
+ 'hiragana_for_latin_with_shift',
+
+ 'insert_space',
+ 'insert_alternate_space',
+ 'insert_half_space',
+ 'insert_wide_space',
+ 'backspace',
+ 'delete',
+ 'commit',
+ 'convert',
+ 'predict',
+ 'cancel',
+ 'cancel_all',
+ 'reconvert',
+# 'do_nothing',
+
+ 'select_first_candidate',
+ 'select_last_candidate',
+ 'select_next_candidate',
+ 'select_prev_candidate',
+ 'candidates_page_up',
+ 'candidates_page_down',
+
+ 'move_caret_first',
+ 'move_caret_last',
+ 'move_caret_forward',
+ 'move_caret_backward',
+
+ 'select_first_segment',
+ 'select_last_segment',
+ 'select_next_segment',
+ 'select_prev_segment',
+ 'shrink_segment',
+ 'expand_segment',
+ 'commit_first_segment',
+ 'commit_selected_segment',
+
+ 'select_candidates_1',
+ 'select_candidates_2',
+ 'select_candidates_3',
+ 'select_candidates_4',
+ 'select_candidates_5',
+ 'select_candidates_6',
+ 'select_candidates_7',
+ 'select_candidates_8',
+ 'select_candidates_9',
+ 'select_candidates_0',
+
+ 'convert_to_char_type_forward',
+ 'convert_to_char_type_backward',
+ 'convert_to_hiragana',
+ 'convert_to_katakana',
+ 'convert_to_half',
+ 'convert_to_half_katakana',
+ 'convert_to_wide_latin',
+ 'convert_to_latin',
+
+ 'dict_admin',
+ 'add_word',
+
+ 'start_setup',
+]
+
+_config = {
+ 'common': {
+ 'input_mode': 0,
+ 'typing_method': 0,
+ 'conversion_segment_mode': 0,
+
+ 'show-input-mode': True,
+ 'show-typing-method': False,
+ 'show-segment-mode': False,
+ 'show-dict-mode': True,
+ 'show-dict-config': False,
+ 'show-preferences': True,
+
+ 'period_style': 0,
+ 'symbol_style': 1,
+ 'ten_key_mode': 1,
+ 'behavior_on_focus_out': 0,
+ 'behavior_on_period': 0,
+
+ 'page_size': 10,
+ 'half_width_symbol': False,
+ 'half_width_number': False,
+ 'half_width_space': False,
+ 'latin_with_shift': True,
+
+ 'shortcut_type': 'default',
+
+ 'dict_admin_command': ['@KASUMI_EXEC_FILE@', 'kasumi'],
+ 'add_word_command': ['@KASUMI_EXEC_FILE@', 'kasumi', '-a'],
+ 'dict_config_icon': '@KASUMI_ICON_FILE@',
+ 'keyboard_layouts': [
+ 'default', 'jp', 'us',
+ # XKB options requires ibus 1.5.
+ 'jp[ctrl:swapcaps]', 'us[ctrl:swapcaps]',
+ 'jp[ctrl:swapcaps,compose:rctrl]',
+ 'us[ctrl:swapcaps,compose:rctrl]',
+ 'jp[japan:kana_lock]',
+ 'jp[japan:nicola_f_bs]',
+ 'jp[japan:nicola_f_bs,ctrl:swapcaps]',
+ 'jp[japan:hztg_escape]',
+ 'jp[japan:hztg_escape,ctrl:swapcaps]',
+ ],
+ },
+
+ 'romaji_typing_rule': {
+ 'method': 'default',
+ # The newkeys list is saved for every romaji_typing_rule/$method
+ # so that prefs.get_value_direct() is not used.
+ # prefs.fetch_section() doesn't get the keys if they exist
+ # in gconf only.
+ 'newkeys': [],
+ },
+
+ ##0 MS-IME
+ # http://www.filibeto.org/sun/lib/solaris10-docs/E19253-01/819-7844/appe-1-4/index.html
+ ##1 ATOK
+ # http://www.filibeto.org/sun/lib/solaris10-docs/E19253-01/819-7844/appe-1-3/index.html
+ ##2 Gairaigo http://ja.wikipedia.org/wiki/%E5%A4%96%E6%9D%A5%E8%AA%9E
+ ##3 ANSI/BSI Suggestions http://en.wikipedia.org/wiki/Katakana
+ ##4 Historical kana http://en.wikipedia.org/wiki/Romanization_of_Japanese
+ # Maybe we need a compatibility between MS-IME and ibus-anthy.
+ 'romaji_typing_rule/default': {
+ 'minus' : 'ー',
+ 'a' : 'あ',
+ 'i' : 'い',
+ 'u' : 'う',
+ 'e' : 'え',
+ 'o' : 'お',
+ 'x-a' : 'ぁ',
+ 'x-i' : 'ぃ',
+ 'x-u' : 'ぅ',
+ 'x-e' : 'ぇ',
+ 'x-o' : 'ぉ',
+ 'l-a' : 'ぁ',
+ 'l-i' : 'ぃ',
+ 'l-u' : 'ぅ',
+ 'l-e' : 'ぇ',
+ 'l-o' : 'ぉ',
+ 'w-h-a' : 'うぁ',
+ 'w-h-i' : 'うぃ',
+ 'w-h-e' : 'うぇ',
+ 'w-h-o' : 'うぉ',
+ 'w-y-a' : 'うゃ', ##2
+ 'w-y-u' : 'うゅ', ##2
+ 'w-y-o' : 'うょ', ##2
+ 'v-a' : 'ヴぁ',
+ 'v-i' : 'ヴぃ',
+ 'v-u' : 'ヴ',
+ 'v-e' : 'ヴぇ',
+ 'v-o' : 'ヴぉ',
+ 'v-y-a' : 'ヴゃ', ##2
+ 'v-y-u' : 'ヴゅ', ##2
+ 'v-y-e' : 'ヴぃぇ', ##2
+ 'v-y-o' : 'ヴょ', ##2
+ 'k-a' : 'か',
+ 'k-i' : 'き',
+ 'k-u' : 'く',
+ 'k-e' : 'け',
+ 'k-o' : 'こ',
+ 'l-k-a' : 'ヵ',
+ 'l-k-e' : 'ヶ',
+# 'x-k-a' : 'ゕ',
+ 'x-k-a' : 'ヵ',
+# 'x-k-e' : 'ゖ',
+ 'x-k-e' : 'ヶ',
+ 'g-a' : 'が',
+ 'g-i' : 'ぎ',
+ 'g-u' : 'ぐ',
+ 'g-e' : 'げ',
+ 'g-o' : 'ご',
+ 'k-y-a' : 'きゃ',
+ 'k-y-i' : 'きぃ',
+ 'k-y-u' : 'きゅ',
+ 'k-y-e' : 'きぇ',
+ 'k-y-o' : 'きょ',
+ 'k-w-a' : 'くぁ',
+ 'k-w-i' : 'くぃ', ##2
+ 'k-w-u' : 'くぅ', ##2
+ 'k-w-e' : 'くぇ', ##2
+ 'k-w-o' : 'くぉ', ##2
+ 'g-y-a' : 'ぎゃ',
+ 'g-y-i' : 'ぎぃ',
+ 'g-y-u' : 'ぎゅ',
+ 'g-y-e' : 'ぎぇ',
+ 'g-y-o' : 'ぎょ',
+ 'g-w-a' : 'ぐぁ',
+ 'g-w-i' : 'ぐぃ', ##2
+ 'g-w-u' : 'ぐぅ', ##2
+ 'g-w-e' : 'ぐぇ', ##2
+ 'g-w-o' : 'ぐぉ', ##2
+ 's-a' : 'さ',
+ 's-i' : 'し',
+ 's-u' : 'す',
+ 's-e' : 'せ',
+ 's-o' : 'そ',
+ 'z-a' : 'ざ',
+ 'z-i' : 'じ',
+ 'z-u' : 'ず',
+ 'z-e' : 'ぜ',
+ 'z-o' : 'ぞ',
+ 's-y-a' : 'しゃ',
+ 's-y-i' : 'しぃ',
+ 's-y-u' : 'しゅ',
+ 's-y-e' : 'しぇ',
+ 's-y-o' : 'しょ',
+ 's-h-a' : 'しゃ',
+ 's-h-i' : 'し',
+ 's-h-u' : 'しゅ',
+ 's-h-e' : 'しぇ',
+ 's-h-o' : 'しょ',
+ 'z-y-a' : 'じゃ',
+ 'z-y-i' : 'じぃ',
+ 'z-y-u' : 'じゅ',
+ 'z-y-e' : 'じぇ',
+ 'z-y-o' : 'じょ',
+ 'j-a' : 'じゃ',
+ 'j-y-a' : 'じゃ',
+ 'j-i' : 'じ',
+ 'j-y-i' : 'じぃ',
+ 'j-u' : 'じゅ',
+ 'j-y-u' : 'じゅ',
+ 'j-e' : 'じぇ',
+ 'j-y-e' : 'じぇ',
+ 'j-o' : 'じょ',
+ 'j-y-o' : 'じょ',
+ 's-w-i' : 'すぅぃ', ##2
+ 's-w-e' : 'すぇ', ##2
+ 'z-w-e' : 'ずぇ', ##2
+ 't-a' : 'た',
+ 't-i' : 'ち',
+ 't-u' : 'つ',
+ 't-s-u' : 'つ',
+ 't-e' : 'て',
+ 't-o' : 'と',
+ 'd-a' : 'だ',
+ 'd-i' : 'ぢ',
+ 'd-u' : 'づ',
+ 'd-e' : 'で',
+ 'd-o' : 'ど',
+ 'x-t-u' : 'っ',
+ 'x-t-s-u' : 'っ',
+ 'l-t-u' : 'っ',
+ 'l-t-s-u' : 'っ',
+ 't-y-a' : 'ちゃ',
+ 't-y-i' : 'ちぃ',
+ 't-y-u' : 'ちゅ',
+ 't-y-e' : 'ちぇ',
+ 't-y-o' : 'ちょ',
+ 'c-y-a' : 'ちゃ',
+ 'c-y-i' : 'ちぃ',
+ 'c-y-u' : 'ちゅ',
+ 'c-y-e' : 'ちぇ',
+ 'c-y-o' : 'ちょ',
+ 'c-h-a' : 'ちゃ',
+ 'c-h-i' : 'ち',
+ 'c-h-u' : 'ちゅ',
+ 'c-h-e' : 'ちぇ',
+ 'c-h-o' : 'ちょ',
+ 'd-y-a' : 'ぢゃ',
+ 'd-y-i' : 'ぢぃ',
+ 'd-y-u' : 'ぢゅ',
+ 'd-y-e' : 'ぢぇ',
+ 'd-y-o' : 'ぢょ',
+ 't-s-a' : 'つぁ',
+ 't-s-i' : 'つぃ',
+ 't-s-e' : 'つぇ',
+ 't-s-o' : 'つぉ',
+ 't-s-y-a' : 'つゃ', ##3
+ 't-s-y-u' : 'つゅ', ##3
+ 't-s-y-e' : 'つぃぇ', ##3
+ 't-s-y-o' : 'つょ', ##3
+ 'd-z-a' : 'づぁ', ##3
+ 'd-z-i' : 'づぃ', ##3
+ 'd-z-u' : 'づ', ##4
+ 'd-z-e' : 'づぇ', ##3
+ 'd-z-o' : 'づぉ', ##3
+ 'd-z-y-a' : 'づゃ', ##3
+ 'd-z-y-u' : 'づゅ', ##3
+ 'd-z-y-e' : 'づぃぇ', ##3
+ 'd-z-y-o' : 'づょ', ##3
+ 't-h-a' : 'てゃ',
+ 't-h-i' : 'てぃ',
+ 't-h-u' : 'てゅ',
+ 't-h-e' : 'てぇ',
+ 't-h-o' : 'てょ',
+ 't-w-u' : 'とぅ',
+ 'd-h-a' : 'でゃ',
+ 'd-h-i' : 'でぃ',
+ 'd-h-u' : 'でゅ',
+ 'd-h-e' : 'でぇ',
+ 'd-h-o' : 'でょ',
+ 'd-w-u' : 'どぅ',
+ 'n-a' : 'な',
+ 'n-i' : 'に',
+ 'n-u' : 'ぬ',
+ 'n-e' : 'ね',
+ 'n-o' : 'の',
+ 'n-y-a' : 'にゃ',
+ 'n-y-i' : 'にぃ',
+ 'n-y-u' : 'にゅ',
+ 'n-y-e' : 'にぇ',
+ 'n-y-o' : 'にょ',
+ 'h-a' : 'は',
+ 'h-i' : 'ひ',
+ 'h-u' : 'ふ',
+ 'h-e' : 'へ',
+ 'h-o' : 'ほ',
+ 'b-a' : 'ば',
+ 'b-i' : 'び',
+ 'b-u' : 'ぶ',
+ 'b-e' : 'べ',
+ 'b-o' : 'ぼ',
+ 'p-a' : 'ぱ',
+ 'p-i' : 'ぴ',
+ 'p-u' : 'ぷ',
+ 'p-e' : 'ぺ',
+ 'p-o' : 'ぽ',
+ 'h-y-a' : 'ひゃ',
+ 'h-y-i' : 'ひぃ',
+ 'h-y-u' : 'ひゅ',
+ 'h-y-e' : 'ひぇ',
+ 'h-y-o' : 'ひょ',
+ 'b-y-a' : 'びゃ',
+ 'b-y-i' : 'びぃ',
+ 'b-y-u' : 'びゅ',
+ 'b-y-e' : 'びぇ',
+ 'b-y-o' : 'びょ',
+ 'p-y-a' : 'ぴゃ',
+ 'p-y-i' : 'ぴぃ',
+ 'p-y-u' : 'ぴゅ',
+ 'p-y-e' : 'ぴぇ',
+ 'p-y-o' : 'ぴょ',
+ 'f-a' : 'ふぁ',
+ 'f-i' : 'ふぃ',
+ 'f-u' : 'ふ',
+ 'f-e' : 'ふぇ',
+ 'f-o' : 'ふぉ',
+ 'f-y-a' : 'ふゃ',
+ 'f-y-i' : 'ふぃ',
+ 'f-y-u' : 'ふゅ',
+ 'f-y-e' : 'ふぇ',
+ 'f-y-o' : 'ふょ',
+ 'b-w-a' : 'ぶぁ', ##2
+ 'b-w-e' : 'ぶぇ', ##2
+ 'b-w-o' : 'ぶぉ', ##2
+ 'p-w-a' : 'ぷぁ', ##2
+ 'p-w-e' : 'ぷぇ', ##2
+ 'p-w-o' : 'ぷぉ', ##2
+ 'm-a' : 'ま',
+ 'm-i' : 'み',
+ 'm-u' : 'む',
+ 'm-e' : 'め',
+ 'm-o' : 'も',
+ 'm-y-a' : 'みゃ',
+ 'm-y-i' : 'みぃ',
+ 'm-y-u' : 'みゅ',
+ 'm-y-e' : 'みぇ',
+ 'm-y-o' : 'みょ',
+ 'y-a' : 'や',
+ 'y-i' : 'い',
+ 'y-u' : 'ゆ',
+ 'y-e' : 'いぇ',
+ 'y-o' : 'よ',
+ 'l-y-a' : 'ゃ',
+ 'l-y-i' : 'ぃ',
+ 'l-y-u' : 'ゅ',
+ 'l-y-e' : 'ぇ',
+ 'l-y-o' : 'ょ',
+ 'x-y-a' : 'ゃ',
+ 'x-y-i' : 'ぃ',
+ 'x-y-u' : 'ゅ',
+ 'x-y-e' : 'ぇ',
+ 'x-y-o' : 'ょ',
+ 'r-a' : 'ら',
+ 'r-i' : 'り',
+ 'r-u' : 'る',
+ 'r-e' : 'れ',
+ 'r-o' : 'ろ',
+ 'r-y-a' : 'りゃ',
+ 'r-y-i' : 'りぃ',
+ 'r-y-u' : 'りゅ',
+ 'r-y-e' : 'りぇ',
+ 'r-y-o' : 'りょ',
+ 'w-a' : 'わ',
+ 'w-i' : 'うぃ',
+ 'w-u' : 'う',
+ 'w-e' : 'うぇ',
+ 'w-o' : 'を',
+ 'l-w-a' : 'ゎ',
+ 'x-w-a' : 'ゎ',
+ 'n-apostrophe' : 'ん',
+ 'n-n' : 'ん',
+ 'w-y-i' : 'ゐ',
+ 'w-y-e' : 'ゑ',
+ },
+
+ 'kana_typing_rule': {
+ 'method': 'jp',
+ 'newkeys': [],
+ },
+
+ 'kana_typing_rule/jp': {
+ # no modifiers keys
+ '1' : 'ぬ',
+ '2' : 'ふ',
+ '3' : 'あ',
+ '4' : 'う',
+ '5' : 'え',
+ '6' : 'お',
+ '7' : 'や',
+ '8' : 'ゆ',
+ '9' : 'よ',
+ '0' : 'わ',
+ 'minus' : 'ほ',
+ 'asciicircum' : 'へ',
+
+ 'q' : 'た',
+ 'w' : 'て',
+ 'e' : 'い',
+ 'r' : 'す',
+ 't' : 'か',
+ 'y' : 'ん',
+ 'u' : 'な',
+ 'i' : 'に',
+ 'o' : 'ら',
+ 'p' : 'せ',
+ 'at' : '゛',
+ 'bracketleft' : '゜',
+
+ 'a' : 'ち',
+ 's' : 'と',
+ 'd' : 'し',
+ 'f' : 'は',
+ 'g' : 'き',
+ 'h' : 'く',
+ 'j' : 'ま',
+ 'k' : 'の',
+ 'l' : 'り',
+ 'semicolon' : 'れ',
+ 'colon' : 'け',
+ 'bracketright' : 'む',
+
+ 'z' : 'つ',
+ 'x' : 'さ',
+ 'c' : 'そ',
+ 'v' : 'ひ',
+ 'b' : 'こ',
+ 'n' : 'み',
+ 'm' : 'も',
+ 'comma' : 'ね',
+ 'period' : 'る',
+ 'slash' : 'め',
+ # 'backslash' : 'ー',
+ 'backslash' : 'ろ',
+
+ # shift modifiered keys
+ 'exclam' : 'ぬ',
+ 'quotedbl' : 'ふ',
+ 'numbersign' : 'ぁ',
+ 'dollar' : 'ぅ',
+ 'percent' : 'ぇ',
+ 'ampersand' : 'ぉ',
+ 'apostrophe' : 'ゃ',
+ 'parenleft' : 'ゅ',
+ 'parenright' : 'ょ',
+ 'asciitilde' : 'を',
+ 'equal' : 'ゑ',
+ 'bar' : 'ー',
+
+ 'largeq' : 'た',
+ 'largew' : 'て',
+ 'largee' : 'ぃ',
+ 'larger' : 'す',
+ 'larget' : 'ヵ',
+ 'largey' : 'ん',
+ 'largeu' : 'な',
+ 'largei' : 'に',
+ 'largeo' : 'ら',
+ 'largep' : 'せ',
+ 'grave' : '゛',
+
+ 'braceleft' : '「',
+
+ 'largea' : 'ち',
+ 'larges' : 'と',
+ 'larged' : 'し',
+ 'largef' : 'ゎ',
+ 'largeg' : 'き',
+ 'largeh' : 'く',
+ 'largej' : 'ま',
+ 'largek' : 'の',
+ 'largel' : 'り',
+ 'plus' : 'れ',
+ 'asterisk' : 'ヶ',
+
+ 'braceright' : '」',
+
+ 'largez' : 'っ',
+ 'largex' : 'さ',
+ 'largec' : 'そ',
+ 'largev' : 'ゐ',
+ 'largeb' : 'こ',
+ 'largen' : 'み',
+ 'largem' : 'も',
+ 'less' : '、',
+ 'greater' : '。',
+
+ 'question' : '・',
+ 'underscore' : 'ろ',
+
+ 'yen' : 'ー',
+ },
+
+ 'kana_typing_rule/us': {
+ # no modifiers keys
+ 'grave' : 'ろ',
+ '1' : 'ぬ',
+ '2' : 'ふ',
+ '3' : 'あ',
+ '4' : 'う',
+ '5' : 'え',
+ '6' : 'お',
+ '7' : 'や',
+ '8' : 'ゆ',
+ '9' : 'よ',
+ '0' : 'わ',
+ 'minus' : 'ほ',
+ 'equal' : 'へ',
+
+ 'q' : 'た',
+ 'w' : 'て',
+ 'e' : 'い',
+ 'r' : 'す',
+ 't' : 'か',
+ 'y' : 'ん',
+ 'u' : 'な',
+ 'i' : 'に',
+ 'o' : 'ら',
+ 'p' : 'せ',
+ 'bracketleft' : '゛',
+ 'bracketright' : '゜',
+ # 'backslash' : 'ー',
+ 'backslash' : 'む',
+
+ 'a' : 'ち',
+ 's' : 'と',
+ 'd' : 'し',
+ 'f' : 'は',
+ 'g' : 'き',
+ 'h' : 'く',
+ 'j' : 'ま',
+ 'k' : 'の',
+ 'l' : 'り',
+ 'semicolon' : 'れ',
+ 'apostrophe' : 'け',
+
+ 'z' : 'つ',
+ 'x' : 'さ',
+ 'c' : 'そ',
+ 'v' : 'ひ',
+ 'b' : 'こ',
+ 'n' : 'み',
+ 'm' : 'も',
+ 'comma' : 'ね',
+ 'period' : 'る',
+ 'slash' : 'め',
+
+ # shift modifiered keys
+ 'asciitilde' : 'ろ',
+ 'exclam' : 'ぬ',
+ 'at' : 'ふ',
+ 'numbersign' : 'ぁ',
+ 'dollar' : 'ぅ',
+ 'percent' : 'ぇ',
+ 'asciicircum' : 'ぉ',
+ 'ampersand' : 'ゃ',
+ 'asterisk' : 'ゅ',
+ 'parenleft' : 'ょ',
+ 'parenright' : 'を',
+ 'underscore' : 'ー',
+ 'plus' : 'ゑ',
+
+ 'largeq' : 'た',
+ 'largew' : 'て',
+ 'largee' : 'ぃ',
+ 'larger' : 'す',
+ 'larget' : 'ヵ',
+ 'largey' : 'ん',
+ 'largeu' : 'な',
+ 'largei' : 'に',
+ 'largeo' : 'ら',
+ 'largep' : 'せ',
+ 'braceleft' : '「',
+
+ 'braceright' : '」',
+
+ 'bar' : 'む',
+
+ 'largea' : 'ち',
+ 'larges' : 'と',
+ 'larged' : 'し',
+ 'largef' : 'ゎ',
+ 'largeg' : 'き',
+ 'largeh' : 'く',
+ 'largej' : 'ま',
+ 'largek' : 'の',
+ 'largel' : 'り',
+ 'colon' : 'れ',
+ 'quotedbl' : 'ヶ',
+
+ 'largez' : 'っ',
+ 'largex' : 'さ',
+ 'largec' : 'そ',
+ 'largev' : 'ゐ',
+ 'largeb' : 'こ',
+ 'largen' : 'み',
+ 'largem' : 'も',
+ 'less' : '、',
+ 'greater' : '。',
+
+ 'question' : '・',
+ },
+ 'thumb': {
+ 'keyboard_layout_mode': True,
+ 'keyboard_layout': 0,
+ 'fmv_extension': 2,
+ 'handakuten': False,
+ 'rs': 'Henkan',
+ 'ls': 'Muhenkan',
+ 't1': 100,
+ 't2': 75,
+ },
+
+ 'thumb_typing_rule': {
+ 'method': 'base',
+ 'newkeys': [],
+ 'nicola_j_table_newkeys': [],
+ 'nicola_a_table_newkeys': [],
+ 'nicola_f_table_newkeys': [],
+ 'kb231_j_fmv_table_newkeys': [],
+ 'kb231_a_fmv_table_newkeys': [],
+ 'kb231_f_fmv_table_newkeys': [],
+ 'kb611_j_fmv_table_newkeys': [],
+ 'kb611_a_fmv_table_newkeys': [],
+ 'kb611_f_fmv_table_newkeys': [],
+ },
+
+ 'thumb_typing_rule/base': {
+ 'q' : ['。', '', 'ぁ'],
+ 'w' : ['か', 'が', 'え'],
+ 'e' : ['た', 'だ', 'り'],
+ 'r' : ['こ', 'ご', 'ゃ'],
+ 't' : ['さ', 'ざ', 'れ'],
+
+ 'y' : ['ら', 'よ', 'ぱ'],
+ 'u' : ['ち', 'に', 'ぢ'],
+ 'i' : ['く', 'る', 'ぐ'],
+ 'o' : ['つ', 'ま', 'づ'],
+ 'p' : [',', 'ぇ', 'ぴ'],
+ 'at' : ['、', '', ''],
+ 'bracketleft' : ['゛', '゜', ''],
+
+ 'a' : ['う', '', 'を'],
+ 's' : ['し', 'じ', 'あ'],
+ 'd' : ['て', 'で', 'な'],
+ 'f' : ['け', 'げ', 'ゅ'],
+ 'g' : ['せ', 'ぜ', 'も'],
+
+ 'h' : ['は', 'み', 'ば'],
+ 'j' : ['と', 'お', 'ど'],
+ 'k' : ['き', 'の', 'ぎ'],
+ 'l' : ['い', 'ょ', 'ぽ'],
+ 'semicolon' : ['ん', 'っ', ''],
+
+ 'z' : ['.', '', 'ぅ'],
+ 'x' : ['ひ', 'び', 'ー'],
+ 'c' : ['す', 'ず', 'ろ'],
+ 'v' : ['ふ', 'ぶ', 'や'],
+ 'b' : ['へ', 'べ', 'ぃ'],
+
+ 'n' : ['め', 'ぬ', 'ぷ'],
+ 'm' : ['そ', 'ゆ', 'ぞ'],
+ 'comma' : ['ね', 'む', 'ぺ'],
+ 'period' : ['ほ', 'わ', 'ぼ'],
+ 'slash' : ['・', 'ぉ', ''],
+
+ '1' : ['1', '', '?'],
+ '2' : ['2', '', '/'],
+ '4' : ['4', '', '「'],
+ '5' : ['5', '', '」'],
+
+ '6' : ['6', '[', ''],
+ '7' : ['7', ']', ''],
+ '8' : ['8', '(', ''],
+ '9' : ['9', ')', ''],
+ 'backslash' : ['¥', '', ''],
+ },
+
+ 'thumb_typing_rule/nicola_j_table': {
+ 'colon' : [':', '', ''],
+ 'at' : ['、', '', ''],
+ 'bracketleft' : ['゛', '゜', ''],
+ 'bracketright' : ['」', '', ''],
+ '8' : ['8', '(', ''],
+ '9' : ['9', ')', ''],
+ '0' : ['0', '', ''],
+ },
+
+ 'thumb_typing_rule/nicola_a_table': {
+ 'colon' : [':', '', ''],
+ 'at' : ['@', '', ''],
+ 'bracketleft' : ['、', '', ''],
+ 'bracketright' : ['゛', '゜', ''],
+ '8' : ['8', '', ''],
+ '9' : ['9', '(', ''],
+ '0' : ['0', ')', ''],
+ },
+
+ 'thumb_typing_rule/nicola_f_table': {
+ 'colon' : ['、', '', ''],
+ 'at' : ['@', '', ''],
+ 'bracketleft' : ['゛', '゜', ''],
+ 'bracketright' : ['」', '', ''],
+ '8' : ['8', '(', ''],
+ '9' : ['9', ')', ''],
+ '0' : ['0', '', ''],
+ },
+
+ 'thumb_typing_rule/kb231_j_fmv_table': {
+ '3' : ['3', '', '~'],
+ '0' : ['0', '『', ''],
+ 'minus' : ['-', '』', ''],
+ 'equal' : ['=', '', ''],
+ },
+
+ 'thumb_typing_rule/kb231_a_fmv_table': {
+ '3' : ['3', '', '~'],
+ '0' : ['0', ')', ''],
+ 'minus' : ['-', '『', ''],
+ 'equal' : ['=', '』', ''],
+ },
+
+ 'thumb_typing_rule/kb231_f_fmv_table': {
+ '3' : ['3', '', '~'],
+ '0' : ['0', '『', ''],
+ 'minus' : ['-', '』', ''],
+ 'equal' : ['=', '', ''],
+ },
+
+ 'thumb_typing_rule/kb611_j_fmv_table': {
+ 'grave' : ['‘', '', ''],
+ 'asciicircum' : ['々', '£', ''],
+ 'colon' : [':', '', ''],
+ 'at' : ['、', '¢', ''],
+ 'bracketleft' : ['゛', '゜', ''],
+ # keysyms are same and keycodes depend on the platforms.
+ #'¥' : [u'¥', u'¬', u''],
+ 'backslash' : ['¥', '¦', ''],
+ },
+
+ 'thumb_typing_rule/kb611_a_fmv_table': {
+ 'grave' : ['々', '', '£'],
+ 'colon' : [':', '', ''],
+ 'at' : ['@', '', ''],
+ 'bracketleft' : ['、', '¢', ''],
+ #'¥' : [u'¥', u'¬', u''],
+ 'backslash' : ['¥', '¦', ''],
+ },
+
+ 'thumb_typing_rule/kb611_f_fmv_table': {
+ 'grave' : ['‘', '', ''],
+ 'asciicircum' : ['々', '£', ''],
+ 'colon' : ['、', '¢', ''],
+ 'at' : ['@', '', ''],
+ 'bracketleft' : ['゛', '゜', ''],
+ #'¥' : [u'¥', u'¬', u''],
+ 'backslash' : ['¥', '¦', ''],
+ },
+
+ 'dict': {
+ 'zipcode': ['@pkgdatadir@/dicts/zipcode.t'],
+ 'symbol': ['@pkgdatadir@/dicts/symbol.t'],
+ 'oldchar': ['@pkgdatadir@/dicts/oldchar.t'],
+ 'era': ['@pkgdatadir@/dicts/era.t'],
+ 'files': [
+ '@pkgdatadir@/dicts/zipcode.t',
+ '@pkgdatadir@/dicts/symbol.t',
+ '@pkgdatadir@/dicts/oldchar.t',
+ '@pkgdatadir@/dicts/era.t',
+ ],
+ },
+
+ 'dict/file/default': {
+ 'embed': False,
+ 'single': True,
+ 'icon': None,
+ 'short_label': None,
+ 'long_label': None,
+ 'preview_lines': 30,
+ 'reverse': False,
+ 'is_system': False,
+ 'encoding': 'utf-8',
+ },
+
+ 'dict/file/embedded': {
+ 'embed': True,
+ 'single': True,
+ 'icon': None,
+ 'short_label': '般',
+ 'long_label': N_("General"),
+ 'preview_lines': 0,
+ 'reverse': False,
+ 'is_system': True,
+ },
+
+ 'dict/file/zipcode': {
+ 'embed': False,
+ 'single': True,
+ 'icon': None,
+ 'short_label': '〒',
+ 'long_label': N_("Zip Code Conversion"),
+ 'preview_lines': 30,
+ 'reverse': False,
+ 'is_system': True,
+ },
+
+ 'dict/file/symbol': {
+ 'embed': True,
+ 'single': False,
+ 'icon': None,
+ 'short_label': '記',
+ 'long_label': N_("Symbol"),
+ 'preview_lines': -1,
+ 'reverse': False,
+ 'is_system': True,
+ },
+
+ 'dict/file/oldchar': {
+ 'embed': False,
+ 'single': True,
+ 'icon': None,
+ 'short_label': '旧',
+ 'long_label': N_("Old Character Style"),
+ 'preview_lines': -1,
+ 'reverse': False,
+ 'is_system': True,
+ },
+ 'dict/file/era': {
+ 'embed': False,
+ 'single': True,
+ 'icon': None,
+ 'short_label': '年',
+ 'long_label': N_("Era"),
+ 'preview_lines': -1,
+ 'reverse': False,
+ 'is_system': True,
+ },
+}
+
+_shortcut_default = {
+ 'on_off': [@ON_OFF_KEYS@],
+ 'circle_input_mode': ['Ctrl+comma', 'Ctrl+less'],
+ # Removed Hiragana_Katakana key in circle_kana_mode for latin_with_shift.
+ 'circle_kana_mode': ['Ctrl+period', 'Ctrl+greater'],
+# 'cancel_pseudo_ascii_mode_key': ['Escape'],
+ 'circle_typing_method': ['Alt+Romaji', 'Ctrl+slash'],
+ 'circle_dict_method': ['Alt+Henkan'],
+
+ 'insert_space': ['space'],
+ 'insert_alternate_space': ['Shift+space'],
+ 'backspace': ['BackSpace', 'Ctrl+H'],
+ 'delete': ['Delete', 'Ctrl+D'],
+ 'commit': ['Return', 'KP_Enter', 'Ctrl+J', 'Ctrl+M'],
+ 'convert': ['space', 'KP_Space', 'Henkan'],
+ 'predict': ['Tab', 'ISO_Left_Tab'],
+ 'cancel': ['Escape', 'Ctrl+G'],
+ 'reconvert': ['Shift+Henkan'],
+
+ 'move_caret_first': ['Ctrl+A', 'Home'],
+ 'move_caret_last': ['Ctrl+E', 'End'],
+ 'move_caret_forward': ['Right', 'Ctrl+F'],
+ 'move_caret_backward': ['Left', 'Ctrl+B'],
+
+ 'select_first_segment': ['Ctrl+A', 'Home'],
+ 'select_last_segment': ['Ctrl+E', 'End'],
+ 'select_next_segment': ['Right', 'Ctrl+F'],
+ 'select_prev_segment': ['Left', 'Ctrl+B'],
+ 'shrink_segment': ['Shift+Left', 'Ctrl+I'],
+ 'expand_segment': ['Shift+Right', 'Ctrl+O'],
+ 'commit_first_segment': ['Shift+Down'],
+ 'commit_selected_segment': ['Ctrl+Down'],
+
+ 'select_first_candidate': ['Home'],
+ 'select_last_candidate': ['End'],
+ 'select_next_candidate': ['space', 'KP_Space', 'Tab', 'ISO_Left_Tab', 'Henkan', 'Down', 'KP_Add', 'Ctrl+N'],
+ 'select_prev_candidate': ['Shift+Tab', 'Shift+ISO_Left_Tab', 'Up', 'KP_Subtract', 'Ctrl+P'],
+ 'candidates_page_up': ['Page_Up'],
+ 'candidates_page_down': ['Page_Down', 'KP_Tab'],
+
+ 'select_candidates_1': ['1'],
+ 'select_candidates_2': ['2'],
+ 'select_candidates_3': ['3'],
+ 'select_candidates_4': ['4'],
+ 'select_candidates_5': ['5'],
+ 'select_candidates_6': ['6'],
+ 'select_candidates_7': ['7'],
+ 'select_candidates_8': ['8'],
+ 'select_candidates_9': ['9'],
+ 'select_candidates_0': ['0'],
+
+ 'convert_to_char_type_forward': ['Muhenkan'],
+ 'convert_to_hiragana': ['F6'],
+ 'convert_to_katakana': ['F7'],
+ 'convert_to_half': ['F8'],
+ 'convert_to_half_katakana': ['Shift+F8'],
+ 'convert_to_wide_latin': ['F9'],
+ 'convert_to_latin': ['F10'],
+
+ 'dict_admin': ['F11'],
+ 'add_word': ['F12'],
+
+ 'hiragana_for_latin_with_shift': ['Hiragana_Katakana'],
+}
+
+_config['shortcut/default'] = dict.fromkeys(_cmd_keys, [])
+_config['shortcut/default'].update(_shortcut_default)
+
+_shortcut_atok = {
+ 'on_off': ['Henkan', 'Eisu_toggle', 'Zenkaku_Hankaku'],
+ 'circle_input_mode': ['F10'],
+ 'hiragana_mode': ['Hiragana_Katakana'],
+ 'katakana_mode': ['Shift+Hiragana_Katakana'],
+ 'circle_typing_method': ['Romaji', 'Alt+Romaji'],
+ 'circle_dict_method': ['Alt+Henkan'],
+ 'convert': ['space', 'Henkan', 'Shift+space', 'Shift+Henkan'],
+ 'predict': ['Tab'],
+ 'cancel': ['Escape', 'BackSpace', 'Ctrl+H', 'Ctrl+bracketleft'],
+ 'commit': ['Return', 'Ctrl+M'],
+ 'reconvert': ['Shift+Henkan'],
+
+ 'insert_space': ['space'],
+ 'insert_alternate_space': ['Shift+space'],
+ 'backspace': ['BackSpace', 'Ctrl+H'],
+ 'delete': ['Delete', 'Ctrl+G'],
+
+ 'move_caret_backward': ['Left', 'Ctrl+K'],
+ 'move_caret_forward': ['Right', 'Ctrl+L'],
+ 'move_caret_first': ['Ctrl+Left'],
+ 'move_caret_last': ['Ctrl+Right'],
+
+ 'select_prev_segment': ['Shift+Left'],
+ 'select_next_segment': ['Shift+Right'],
+ 'select_first_segment': ['Ctrl+Left'],
+ 'select_last_segment': ['Ctrl+Right'],
+ 'expand_segment': ['Right', 'Ctrl+L'],
+ 'shrink_segment': ['Left', 'Ctrl+K'],
+ 'commit_selected_segment': ['Down', 'Ctrl+N'],
+
+ 'candidates_page_up': ['Shift+Henkan', 'Page_Up'],
+ 'candidates_page_down': ['Henkan', 'Page_Down'],
+ 'select_next_candidate': ['space', 'Tab', 'Henkan', 'Shift+space', 'Shift+Henkan'],
+ 'select_prev_candidate': ['Up'],
+
+ 'select_candidates_1': ['1'],
+ 'select_candidates_2': ['2'],
+ 'select_candidates_3': ['3'],
+ 'select_candidates_4': ['4'],
+ 'select_candidates_5': ['5'],
+ 'select_candidates_6': ['6'],
+ 'select_candidates_7': ['7'],
+ 'select_candidates_8': ['8'],
+ 'select_candidates_9': ['9'],
+ 'select_candidates_0': ['0'],
+
+ 'convert_to_hiragana': ['F6', 'Ctrl+U'],
+ 'convert_to_katakana': ['F7', 'Ctrl+I'],
+ 'convert_to_half': ['F8', 'Ctrl+O'],
+ 'convert_to_half_katakana': ['Shift+F8'],
+ 'convert_to_wide_latin': ['F9', 'Ctrl+P'],
+ 'convert_to_latin': ['F10', 'Ctrl+at'],
+
+ 'dict_admin': ['F11'],
+ 'add_word': ['Ctrl+F7'],
+
+ 'hiragana_for_latin_with_shift': ['Ctrl+J'],
+}
+
+_config['shortcut/atok'] = dict.fromkeys(_cmd_keys, [])
+_config['shortcut/atok'].update(_shortcut_atok)
+
+_shortcut_wnn = {
+ 'on_off': ['Shift+space'],
+ 'convert': ['space'],
+ 'predict': ['Ctrl+Q'],
+ 'cancel': ['Escape', 'Ctrl+G', 'Alt+Down', 'Muhenkan'],
+ 'commit': ['Ctrl+L', 'Ctrl+M', 'Ctrl+J', 'Return'],
+ 'insert_space': ['space'],
+ 'backspace': ['Ctrl+H', 'BackSpace'],
+ 'delete': ['Ctrl+D', 'Delete'],
+ 'circle_dict_method': ['Alt+Henkan'],
+
+ 'move_caret_backward': ['Ctrl+B', 'Left'],
+ 'move_caret_forward': ['Ctrl+F', 'Right'],
+ 'move_caret_first': ['Ctrl+A', 'Alt+Left'],
+ 'move_caret_last': ['Ctrl+E', 'Alt+Right'],
+
+ 'select_prev_segment': ['Ctrl+B', 'Left'],
+ 'select_next_segment': ['Ctrl+F', 'Right'],
+ 'select_first_segment': ['Ctrl+A', 'Alt+Left'],
+ 'select_last_segment': ['Ctrl+E', 'Alt+Right'],
+ 'expand_segment': ['Ctrl+O', 'F14'],
+ 'shrink_segment': ['Ctrl+I', 'F13'],
+
+ 'candidates_page_up': ['Tab'],
+ 'candidates_page_down': ['Shift+Tab'],
+ 'select_next_candidate': ['space', 'Ctrl+Q', 'Ctrl+P', 'Down'],
+ 'select_prev_candidate': ['Ctrl+N', 'Up'],
+
+ 'select_candidates_1': ['1'],
+ 'select_candidates_2': ['2'],
+ 'select_candidates_3': ['3'],
+ 'select_candidates_4': ['4'],
+ 'select_candidates_5': ['5'],
+ 'select_candidates_6': ['6'],
+ 'select_candidates_7': ['7'],
+ 'select_candidates_8': ['8'],
+ 'select_candidates_9': ['9'],
+ 'select_candidates_0': ['0'],
+
+ 'convert_to_hiragana': ['F6'],
+ 'convert_to_katakana': ['F7'],
+ 'convert_to_half': ['F8'],
+ 'convert_to_wide_latin': ['F9'],
+ 'convert_to_latin': ['F10'],
+
+ 'dict_admin': ['F11'],
+ 'add_word': ['F12'],
+
+ 'hiragana_for_latin_with_shift': ['Hiragana_Katakana'],
+}
+
+_config['shortcut/wnn'] = dict.fromkeys(_cmd_keys, [])
+_config['shortcut/wnn'].update(_shortcut_wnn)
+
diff --git a/setup/python3/ibus-setup-anthy.desktop.in.in b/setup/python3/ibus-setup-anthy.desktop.in.in
new file mode 100644
index 0000000..1dd35f9
--- /dev/null
+++ b/setup/python3/ibus-setup-anthy.desktop.in.in
@@ -0,0 +1,8 @@
+[Desktop Entry]
+_Name=IBus Anthy Setup
+_Comment=Set up IBus Anthy engine
+Exec=@libexecdir@/ibus-setup-anthy
+Icon=ibus-anthy
+NoDisplay=true
+Type=Application
+StartupNotify=true
diff --git a/setup/python3/ibus-setup-anthy.in b/setup/python3/ibus-setup-anthy.in
new file mode 100644
index 0000000..f8832fd
--- /dev/null
+++ b/setup/python3/ibus-setup-anthy.in
@@ -0,0 +1,28 @@
+#!/bin/sh
+# vim:set noet ts=4:
+#
+# ibus-tmpl - The Input Bus template project
+#
+# Copyright (c) 2007-2008 Peng Huang <shawn.p.huang@gmail.com>
+# Copyright (c) 2010-2013 Takao Fujiwara <takao.fujiwara1@gmail.com>
+# Copyright (c) 2007-2013 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+prefix=@prefix@
+datarootdir=@datarootdir@
+export IBUS_LOCALEDIR=@localedir@
+exec @PYTHON@ @prefix@/share/ibus-anthy/setup/main.py $@
+
diff --git a/setup/python3/main.py b/setup/python3/main.py
new file mode 100644
index 0000000..fec03a6
--- /dev/null
+++ b/setup/python3/main.py
@@ -0,0 +1,1729 @@
+# vim:set noet ts=4:
+#
+# ibus-anthy - The Anthy engine for IBus
+#
+# Copyright (c) 2007-2008 Peng Huang <shawn.p.huang@gmail.com>
+# Copyright (c) 2009 Hideaki ABE <abe.sendai@gmail.com>
+# Copyright (c) 2010-2014 Takao Fujiwara <takao.fujiwara1@gmail.com>
+# Copyright (c) 2007-2014 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+from os import environ, getuid, path
+import binascii
+import codecs
+import functools
+import locale
+import os, sys
+import xml.dom.minidom
+import gettext
+from gettext import dgettext
+
+from gi.repository import GLib
+
+# set_prgname before importing other modules to show the name in warning
+# messages when import modules are failed. E.g. Gtk.
+GLib.set_prgname('ibus-setup-anthy')
+
+from gi.repository import Gtk
+from gi.repository import Gdk
+from gi.repository import GdkX11
+from gi.repository import Pango
+from gi.repository import IBus
+
+import _config as config
+from anthyprefs import AnthyPrefs
+
+DOMAINNAME = 'ibus-anthy'
+_ = lambda a : dgettext('ibus-anthy', a)
+
+def l_to_s(l):
+ return str(sorted([str(s) for s in l])).replace('\'', '')
+
+def s_to_l(s):
+ return [] if s == '[]' else s[1:-1].replace(' ', '').split(',')
+
+
+class AnthySetup(object):
+ def __init__(self):
+ # Python's locale module doesn't provide all methods on some
+ # operating systems like FreeBSD
+ try:
+ locale.bindtextdomain(DOMAINNAME, config.LOCALEDIR)
+ locale.bind_textdomain_codeset(DOMAINNAME, 'UTF-8')
+ except AttributeError:
+ pass
+ gettext.bindtextdomain(DOMAINNAME, config.LOCALEDIR)
+ gettext.bind_textdomain_codeset(DOMAINNAME, 'UTF-8')
+
+ # IBus.Bus() calls ibus_bus_new().
+ # Gtk.Builder().add_from_file() also calls ibus_bus_new_async()
+ # via ibus_im_context_new().
+ # Then if IBus.Bus() is called after Gtk.Builder().add_from_file(),
+ # the connection delay would be happened without an async
+ # finish function.
+ ibus_address = IBus.get_address()
+ bus = None
+ if ibus_address != None:
+ bus = IBus.Bus(connect_async='True')
+
+ builder_file = path.join(path.dirname(__file__), 'setup.ui')
+ self.__builder = builder = Gtk.Builder()
+ builder.set_translation_domain(DOMAINNAME)
+ builder.add_from_file(builder_file)
+
+ toplevel = builder.get_object('main')
+
+ try:
+ gnome_control_center_xid = int(environ['GNOME_CONTROL_CENTER_XID'])
+ except:
+ gnome_control_center_xid = 0
+
+ if gnome_control_center_xid != 0:
+ def set_transient(obj, pspec):
+ window = toplevel.get_window()
+ if window == None:
+ return
+ parent_window = GdkX11.X11Window.foreign_new_for_display(Gdk.Display.get_default(),
+ gnome_control_center_xid)
+ if parent_window != None:
+ window.set_transient_for(parent_window)
+ toplevel.set_wmclass('gnome-control-center', 'Gnome-control-center')
+ toplevel.set_modal(True)
+ toplevel.set_type_hint(Gdk.WindowTypeHint.DIALOG)
+ toplevel.connect('notify::window', set_transient)
+
+ toplevel.show()
+
+ if ibus_address == None:
+ builder.connect_signals(self)
+ # self.__run_message_dialog needs self.__builder.
+ self.__run_message_dialog(_("ibus is not running."),
+ Gtk.MessageType.ERROR)
+ return
+
+ if bus.is_connected():
+ self.__init_bus_connected(bus)
+ else:
+ bus.connect('connected', self.__init_bus_connected)
+
+ def __init_bus_connected(self, bus):
+ self.__config = bus.get_config()
+ builder = self.__builder
+
+ self.__thumb_kb_layout_mode = None
+ self.__thumb_kb_layout = None
+ self.__japanese_ordered_dict = {}
+ self.prefs = prefs = AnthyPrefs(None, self.__config)
+
+ # glade 'icon_name' property has a custom scaling and it seems
+ # to be difficult to show the complicated small icon in metacity.
+ # This can add the pixbuf without scaling.
+ anthydir = path.dirname(path.dirname(__file__))
+ if not anthydir:
+ anthydir = '/usr/share/ibus-anthy'
+ icon_path = path.join(anthydir, 'icons', 'ibus-anthy.png')
+ if path.exists(icon_path):
+ builder.get_object('main').set_icon_from_file(icon_path)
+ else:
+ icon_path = 'ibus-anthy'
+ builder.get_object('main').set_icon_name(icon_path)
+
+ for name in ['input_mode', 'typing_method', 'conversion_segment_mode',
+ 'period_style', 'symbol_style', 'ten_key_mode',
+ 'behavior_on_focus_out', 'behavior_on_period',
+ 'half_width_symbol', 'half_width_number', 'half_width_space',
+ 'latin_with_shift',
+ 'thumb:keyboard_layout_mode', 'thumb:keyboard_layout',
+ 'thumb:fmv_extension', 'thumb:handakuten']:
+ section, key = self.__get_section_key(name)
+ builder.get_object(name).set_active(prefs.get_value(section, key))
+
+ tv = builder.get_object('menu_visible:treeview')
+ ls = Gtk.ListStore(str, bool, str)
+ tv.set_model(ls)
+
+ column = Gtk.TreeViewColumn(' ')
+ renderer = Gtk.CellRendererToggle()
+ renderer.set_radio(False)
+ renderer.connect('toggled', self.__renderer_toggled_cb, ls)
+ column.pack_start(renderer, False)
+ column.set_cell_data_func(renderer,
+ self.__toggle_menu_visible_cell_cb,
+ 1)
+ tv.append_column(column)
+
+ column = Gtk.TreeViewColumn(_("Menu label"))
+ renderer = Gtk.CellRendererText()
+ column.pack_start(renderer, False)
+ column.set_cell_data_func(renderer,
+ self.__text_menu_visible_cell_cb,
+ 2)
+ tv.append_column(column)
+
+ self.__append_menus_in_model()
+
+ l = ['default', 'atok', 'wnn']
+ s_type = prefs.get_value('common', 'shortcut_type')
+ s_type = s_type if s_type in l else 'default'
+ builder.get_object('shortcut_type').set_active(l.index(s_type))
+
+ builder.get_object('page_size').set_value(prefs.get_value('common',
+ 'page_size'))
+
+ tv = builder.get_object('shortcut')
+ tv.append_column(Gtk.TreeViewColumn(_("Command"),
+ Gtk.CellRendererText(), text=0))
+ renderer = Gtk.CellRendererText()
+ renderer.set_property('ellipsize', Pango.EllipsizeMode.END)
+ tv.append_column(Gtk.TreeViewColumn(_("Shortcut"),
+ renderer, text=1))
+ tv.get_selection().connect_after('changed',
+ self.on_selection_changed, 0)
+ ls = Gtk.ListStore(str, str)
+ sec = 'shortcut/' + s_type
+ for k in self.prefs.keys(sec):
+ ls.append([k, l_to_s(self.prefs.get_value(sec, k))])
+ tv.set_model(ls)
+
+ self.__keymap = None
+ GLib.idle_add(self.__update_keymap_label,
+ priority = GLib.PRIORITY_LOW)
+
+ self.__thumb_kb_layout_mode = builder.get_object('thumb:keyboard_layout_mode')
+ self.__thumb_kb_layout = builder.get_object('thumb:keyboard_layout')
+ self.__set_thumb_kb_label()
+
+ for name in ['thumb:ls', 'thumb:rs']:
+ section, key = self.__get_section_key(name)
+ builder.get_object(name).set_text(prefs.get_value(section, key))
+
+ tv = builder.get_object('es:treeview')
+ tv.append_column(Gtk.TreeViewColumn('', Gtk.CellRendererText(), text=0))
+ tv.get_selection().connect_after('changed',
+ self.on_selection_changed, 1)
+ tv.set_model(Gtk.ListStore(str))
+
+ key = 'dict_admin_command'
+ cli = self.__get_dict_cli_from_list(prefs.get_value('common', key))
+ name = 'dict:entry_edit_dict_command'
+ builder.get_object(name).set_text(cli)
+ key = 'add_word_command'
+ cli = self.__get_dict_cli_from_list(prefs.get_value('common', key))
+ name = 'dict:entry_add_word_command'
+ builder.get_object(name).set_text(cli)
+
+ tv = builder.get_object('dict:view')
+
+ column = Gtk.TreeViewColumn(' ')
+ renderer = Gtk.CellRendererText()
+ column.pack_start(renderer, False)
+ column.set_cell_data_func(renderer, self.__text_cell_data_cb, 1)
+ tv.append_column(column)
+
+ column = Gtk.TreeViewColumn(_("Description"))
+ renderer = Gtk.CellRendererText()
+ column.pack_start(renderer, False)
+ column.set_cell_data_func(renderer, self.__text_cell_data_cb, 2)
+ column.set_expand(True)
+ tv.append_column(column)
+
+ # Translators: "Embd" is an abbreviation of "embedded".
+ column = Gtk.TreeViewColumn(_("Embd"))
+ renderer = Gtk.CellRendererToggle()
+ renderer.set_radio(False)
+ column.pack_start(renderer, False)
+ column.set_cell_data_func(renderer, self.__toggle_cell_data_cb, 3)
+ tv.append_column(column)
+
+ # Translators: "Sgl" is an abbreviation of "single".
+ column = Gtk.TreeViewColumn(_("Sgl"))
+ renderer = Gtk.CellRendererToggle()
+ renderer.set_radio(False)
+ column.pack_start(renderer, False)
+ column.set_cell_data_func(renderer, self.__toggle_cell_data_cb, 4)
+ tv.append_column(column)
+
+ '''
+ Unfortunately reverse conversion is too slow.
+ # Translators: "Rev" is an abbreviation of "reverse".
+ column = Gtk.TreeViewColumn(_("Rev"))
+ renderer = Gtk.CellRendererToggle()
+ renderer.set_radio(False)
+ column.pack_start(renderer, False)
+ column.set_cell_data_func(renderer, self.__toggle_cell_data_cb, 5)
+ tv.append_column(column)
+ '''
+
+ ls = Gtk.ListStore(str, str, str, bool, bool, bool)
+ tv.set_model(ls)
+ self.__append_dicts_in_model()
+
+ self.__init_japanese_sort()
+ self.__init_about_vbox(icon_path)
+
+ builder.connect_signals(self)
+
+ def __init_japanese_sort(self):
+ japanese_ordered_dict = {}
+ japanese_ordered_list = self.prefs.get_japanese_ordered_list()
+ for index, c in enumerate(japanese_ordered_list):
+ japanese_ordered_dict[c] = index
+ self.__japanese_ordered_dict = japanese_ordered_dict;
+
+ def __init_about_vbox(self, icon_path):
+ about_dialog = self.__builder.get_object('about_dialog')
+ about_vbox = self.__builder.get_object('about_vbox')
+ about_dialog.set_version(self.prefs.get_version())
+ if icon_path != None:
+ if icon_path[0] == '/':
+ image = Gtk.Image.new_from_file(icon_path)
+ about_dialog.set_logo(image.get_pixbuf())
+ else:
+ icon_theme = Gtk.IconTheme.get_default()
+ try:
+ pixbuf = icon_theme.load_icon(icon_path, 48, 0)
+ about_dialog.set_logo(pixbuf)
+ except Exception as err:
+ print('Not found icon', str(err), file=sys.stderr)
+ print('Need to run gtk-update-icon-cache', file=sys.stderr)
+ content_area = about_dialog.get_content_area()
+ list = content_area.get_children()
+ vbox = list[0]
+ for w in vbox.get_children():
+ old_parent = w.props.parent
+ w.unparent()
+ w.emit('parent-set', old_parent)
+ about_vbox.pack_start(w, False, False, 0)
+
+ def __get_userhome(self):
+ if 'HOME' not in environ:
+ import pwd
+ userhome = pwd.getpwuid(getuid()).pw_dir
+ else:
+ userhome = environ['HOME']
+ userhome = userhome.rstrip('/')
+ return userhome
+
+ def __get_section_key(self, name):
+ i = name.find(':')
+ if i > 0:
+ section = name[:i]
+ key = name[i + 1:]
+ else:
+ section = 'common'
+ key = name
+ return (section, key)
+
+ def __run_message_dialog(self, message, type=Gtk.MessageType.INFO):
+ dlg = Gtk.MessageDialog(parent=self.__builder.get_object('main'),
+ flags=Gtk.DialogFlags.MODAL,
+ message_type=type,
+ buttons=Gtk.ButtonsType.OK,
+ message_format=message)
+ dlg.run()
+ dlg.destroy()
+
+ def __japanese_tuple_sort(self, a, b):
+ if a[1] == b[1]:
+ # http://docs.python.org/3.0/whatsnew/3.0.html#ordering-comparisons
+ return (a[0] > b[0]) - (a[0] < b[0])
+ elif a[1] in self.__japanese_ordered_dict and \
+ b[1] in self.__japanese_ordered_dict:
+ return self.__japanese_ordered_dict[a[1]] - \
+ self.__japanese_ordered_dict[b[1]]
+ elif a[1] not in self.__japanese_ordered_dict and \
+ b[1] in self.__japanese_ordered_dict:
+ return 1
+ elif a[1] in self.__japanese_ordered_dict and \
+ b[1] not in self.__japanese_ordered_dict:
+ return -1
+ else:
+ return (a[1] > b[1]) - (a[1] < b[1])
+
+ def __japanese_thumb_sort(self, a, b):
+ # http://docs.python.org/3.0/whatsnew/3.0.html#ordering-comparisons
+ return (a[0] > b[0]) - (a[0] < b[0])
+
+ def __renderer_toggled_cb(self, renderer, path, model):
+ prefs = self.prefs
+ enabled = not model[path][1]
+ model[path][1] = enabled
+ key = model[path][0]
+ prefs.set_value('common', key, enabled)
+ self.__builder.get_object('btn_apply').set_sensitive(True)
+
+ def __toggle_menu_visible_cell_cb(self, column, renderer, model, iter, id):
+ l = self.__builder.get_object('menu_visible:treeview').get_model()
+ active = l.get_value(iter, id)
+ renderer.set_property('active', active)
+
+ def __text_menu_visible_cell_cb(self, column, renderer, model, iter, id):
+ l = self.__builder.get_object('menu_visible:treeview').get_model()
+ text = l.get_value(iter, id)
+ renderer.set_property('text', text)
+
+ def __append_menus_in_model(self):
+ prefs = self.prefs
+ l = self.__builder.get_object('menu_visible:treeview').get_model()
+ l.append(['show-input-mode',
+ prefs.get_value('common', 'show-input-mode'),
+ _("Input mode")])
+ l.append(['show-typing-method',
+ prefs.get_value('common', 'show-typing-method'),
+ _("Typing method")])
+ l.append(['show-segment-mode',
+ prefs.get_value('common', 'show-segment-mode'),
+ _("Segment mode")])
+ l.append(['show-dict-mode',
+ prefs.get_value('common', 'show-dict-mode'),
+ _("Dictionary mode")])
+ l.append(['show-dict-config',
+ prefs.get_value('common', 'show-dict-config'),
+ _("Dictionary - Anthy")])
+ l.append(['show-preferences',
+ prefs.get_value('common', 'show-preferences'),
+ _("Preferences - Anthy")])
+
+ def __get_romaji_treeview_custom_key_table(self, method):
+ prefs = self.prefs
+ rule = {}
+ ls = Gtk.ListStore(str, str, str)
+ tv = self.__builder.get_object('treeview_custom_key_table')
+ section_base = 'romaji_typing_rule'
+ section = section_base + '/' + prefs.str(method)
+ for key in prefs.keys(section):
+ key = prefs.str(key)
+ value = prefs.get_value(section, key)
+ ch = prefs.typing_from_config_key(key)
+ if ch == '':
+ continue
+ # config.set_value(key, None) is not supported.
+ if value != None and value != '':
+ rule[ch] = prefs.str(value)
+ for key in prefs.get_value(section_base, 'newkeys'):
+ key = prefs.str(key)
+ value = self.prefs.get_value_direct(section, key)
+ ch = prefs.typing_from_config_key(key)
+ if ch == '':
+ continue
+ # config.set_value(key, None) is not supported.
+ if value != None and value != '':
+ rule[ch] = prefs.str(value)
+ for key, value in sorted(list(rule.items()), \
+ key = functools.cmp_to_key(self.__japanese_tuple_sort)):
+ ls.append(['romaji', key, value])
+ tv.append_column(Gtk.TreeViewColumn(_(_("Input Chars")),
+ Gtk.CellRendererText(), text=1))
+ tv.append_column(Gtk.TreeViewColumn(_(_("Output Chars")),
+ Gtk.CellRendererText(), text=2))
+ tv.set_model(ls)
+ return tv
+
+ def __get_kana_treeview_custom_key_table(self, method):
+ prefs = self.prefs
+ rule = {}
+ ls = Gtk.ListStore(str, str, str)
+ tv = self.__builder.get_object('treeview_custom_key_table')
+ section_base = 'kana_typing_rule'
+ section = section_base + '/' + prefs.str(method)
+ for key in prefs.keys(section):
+ key = prefs.str(key)
+ value = prefs.get_value(section, key)
+ ch = prefs.typing_from_config_key(key)
+ if ch == '':
+ continue
+ # config.set_value(key, None) is not supported.
+ if value != None and value != '':
+ rule[ch] = prefs.str(value)
+ for key in prefs.get_value(section_base, 'newkeys'):
+ key = prefs.str(key)
+ value = self.prefs.get_value_direct(section, key)
+ ch = prefs.typing_from_config_key(key)
+ if ch == '':
+ continue
+ # config.set_value(key, None) is not supported.
+ if value != None and value != '':
+ rule[ch] = prefs.str(value)
+ for key, value in sorted(list(rule.items()), \
+ key = functools.cmp_to_key(self.__japanese_tuple_sort)):
+ ls.append(['kana', key, value])
+ tv.append_column(Gtk.TreeViewColumn(_(_("Input Chars")),
+ Gtk.CellRendererText(), text=1))
+ tv.append_column(Gtk.TreeViewColumn(_(_("Output Chars")),
+ Gtk.CellRendererText(), text=2))
+ tv.set_model(ls)
+ return tv
+
+ def __get_thumb_treeview_custom_key_table(self, method):
+ prefs = self.prefs
+ rule = {}
+ ls = Gtk.ListStore(str, str, str, str, str)
+ tv = self.__builder.get_object('treeview_custom_key_table')
+ section_base = 'thumb_typing_rule'
+ section = section_base + '/' + prefs.str(method)
+ for key in prefs.keys(section):
+ key = prefs.str(key)
+ value = prefs.get_value(section, key)
+ ch = prefs.typing_from_config_key(key)
+ if ch == '':
+ continue
+ # config.set_value(key, None) is not supported.
+ if value != None and len(value) == 3 and \
+ ((value[0] != None and value[0] != '') or \
+ (value[1] != None and value[1] != '') or \
+ (value[2] != None and value[2] != '')):
+ rule[ch] = {}
+ rule[ch][0] = prefs.str(value[0])
+ rule[ch][1] = prefs.str(value[1])
+ rule[ch][2] = prefs.str(value[2])
+ for key in prefs.get_value(section_base, 'newkeys'):
+ key = prefs.str(key)
+ value = self.prefs.get_value_direct(section, key)
+ ch = prefs.typing_from_config_key(key)
+ if ch == '':
+ continue
+ # config.set_value(key, None) is not supported.
+ if value != None and len(value) == 3 and \
+ ((value[0] != None and value[0] != '') or \
+ (value[1] != None and value[1] != '') or \
+ (value[2] != None and value[2] != '')):
+ rule[ch] = {}
+ rule[ch][0] = prefs.str(value[0])
+ rule[ch][1] = prefs.str(value[1])
+ rule[ch][2] = prefs.str(value[2])
+ for key, value in sorted(list(rule.items()), \
+ key = functools.cmp_to_key(self.__japanese_thumb_sort)):
+ ls.append(['thumb', key, value[0], value[2], value[1]])
+ tv.append_column(Gtk.TreeViewColumn(_(_("Input")),
+ Gtk.CellRendererText(), text=1))
+ tv.append_column(Gtk.TreeViewColumn(_(_("Single")),
+ Gtk.CellRendererText(), text=2))
+ tv.append_column(Gtk.TreeViewColumn(_(_("Left")),
+ Gtk.CellRendererText(), text=3))
+ tv.append_column(Gtk.TreeViewColumn(_(_("Right")),
+ Gtk.CellRendererText(), text=4))
+ tv.set_model(ls)
+ return tv
+
+ def __show_dialog_custom_key_table_extention(self, mode):
+ hbox_combo = self.__builder.get_object('hbox_for_combobox_custom_key_table')
+ label_left = self.__builder.get_object('label_left_thumb_shift_custom_key')
+ entry_left = self.__builder.get_object('entry_left_thumb_shift_custom_key')
+ label_right = self.__builder.get_object('label_right_thumb_shift_custom_key')
+ entry_right = self.__builder.get_object('entry_right_thumb_shift_custom_key')
+ if mode == 'thumb':
+ hbox_combo.show()
+ label_left.show()
+ entry_left.show()
+ label_right.show()
+ entry_right.show()
+ elif mode == 'kana':
+ hbox_combo.show()
+ label_left.hide()
+ entry_left.hide()
+ label_right.hide()
+ entry_right.hide()
+ else:
+ hbox_combo.hide()
+ label_left.hide()
+ entry_left.hide()
+ label_right.hide()
+ entry_right.hide()
+
+ def __connect_dialog_custom_key_table_buttons(self, mode):
+ tv = self.__builder.get_object('treeview_custom_key_table')
+ tv.get_selection().connect_after('changed',
+ self.on_selection_custom_key_table_changed, 0)
+ entry = self.__builder.get_object('entry_input_custom_key')
+ entry.connect('changed', self.on_entry_custom_key_changed, mode)
+ entry = self.__builder.get_object('entry_output_custom_key')
+ entry.connect('changed', self.on_entry_custom_key_changed, mode)
+ entry = self.__builder.get_object('entry_left_thumb_shift_custom_key')
+ entry.connect('changed', self.on_entry_custom_key_changed, mode)
+ entry = self.__builder.get_object('entry_right_thumb_shift_custom_key')
+ entry.connect('changed', self.on_entry_custom_key_changed, mode)
+ button = self.__builder.get_object('button_add_custom_key')
+ button.set_sensitive(False)
+ button.connect('clicked', self.on_btn_add_custom_key, mode)
+ button = self.__builder.get_object('button_remove_custom_key')
+ button.set_sensitive(False)
+ button.connect('clicked', self.on_btn_remove_custom_key, tv)
+
+ def __disconnect_dialog_custom_key_table_buttons(self):
+ tv = self.__builder.get_object('treeview_custom_key_table')
+ combobox = self.__builder.get_object('combobox_custom_key_table')
+ if tv != None:
+ for column in tv.get_columns():
+ tv.remove_column(column)
+ for child in tv.get_children():
+ tv.remove(child)
+ entry = self.__builder.get_object('entry_input_custom_key')
+ entry.disconnect_by_func(self.on_entry_custom_key_changed)
+ entry.set_text('')
+ entry = self.__builder.get_object('entry_output_custom_key')
+ entry.disconnect_by_func(self.on_entry_custom_key_changed)
+ entry.set_text('')
+ entry = self.__builder.get_object('entry_left_thumb_shift_custom_key')
+ entry.disconnect_by_func(self.on_entry_custom_key_changed)
+ entry = self.__builder.get_object('entry_right_thumb_shift_custom_key')
+ entry.disconnect_by_func(self.on_entry_custom_key_changed)
+ button = self.__builder.get_object('button_add_custom_key')
+ button.disconnect_by_func(self.on_btn_add_custom_key)
+ button = self.__builder.get_object('button_remove_custom_key')
+ button.disconnect_by_func(self.on_btn_remove_custom_key)
+ combobox.clear()
+ combobox.disconnect_by_func(self.on_cb_custom_key_table_changed)
+
+ def __run_dialog_custom_key_table(self, mode):
+ prefs = self.prefs
+ dlg = self.__builder.get_object('dialog_custom_key_table')
+ label = self.__builder.get_object('label_custom_key_table')
+ label_output = self.__builder.get_object('label_output_custom_key')
+ list_labels = []
+ if mode == 'romaji':
+ dlg.set_title(_("Customize Romaji Key Table"))
+ label.set_label(_("_Romaji Key Table:"))
+ label_output.set_label(_("_Output Chars"))
+ list_labels = [['default', _("Default")]]
+ self.__show_dialog_custom_key_table_extention(mode)
+ elif mode == 'kana':
+ dlg.set_title(_("Customize Kana Key Table"))
+ label.set_label(_("_Kana Key Table:"))
+ label_output.set_label(_("_Output Chars"))
+ list_labels = [['jp', _("Japanese Keyboard Layout")],
+ ['us', _("U.S. Keyboard Layout")]]
+ self.__show_dialog_custom_key_table_extention(mode)
+ elif mode == 'thumb':
+ dlg.set_title(_("Customize Thumb Shift Key Table"))
+ label.set_label(_("_Thumb Shift Key Table:"))
+ label_output.set_label(_("Single _Output Chars"))
+ list_labels = [['base', _("Base")],
+ ['nicola_j_table', _("NICOLA-J key extension")],
+ ['nicola_a_table', _("NICOLA-A key extension")],
+ ['nicola_f_table', _("NICOLA-F key extension")],
+ ['kb231_j_fmv_table', _("FMV KB231-J key extension")],
+ ['kb231_a_fmv_table', _("FMV KB231-A key extension")],
+ ['kb231_f_fmv_table', _("FMV KB231-F key extension")],
+ ['kb611_j_fmv_table', _("FMV KB611-J key extension")],
+ ['kb611_a_fmv_table', _("FMV KB611-A key extension")],
+ ['kb611_f_fmv_table', _("FMV KB611-F key extension")],
+ ]
+ self.__show_dialog_custom_key_table_extention(mode)
+ ls = Gtk.ListStore(str, str)
+ for s in list_labels:
+ ls.append([s[1], s[0]])
+ renderer = Gtk.CellRendererText()
+ combobox = self.__builder.get_object('combobox_custom_key_table')
+ combobox.pack_start(renderer, True)
+ combobox.add_attribute(renderer, 'text', 0)
+ combobox.set_model(ls)
+
+ tv = None
+ if mode == 'romaji':
+ method = prefs.get_value('romaji_typing_rule', 'method')
+ if method == None:
+ method = 'default'
+ tv = self.__get_romaji_treeview_custom_key_table(method)
+ if mode == 'kana':
+ method = prefs.get_value('kana_typing_rule', 'method')
+ if method == None:
+ method = 'jp'
+ tv = self.__get_kana_treeview_custom_key_table(method)
+ if mode == 'thumb':
+ method = prefs.get_value('thumb_typing_rule', 'method')
+ if method == None:
+ method = 'base'
+ tv = self.__get_thumb_treeview_custom_key_table(method)
+
+ self.__connect_dialog_custom_key_table_buttons(mode)
+
+ id = 0
+ # thumb uses all tables so the default is always 0.
+ if mode != 'thumb':
+ for index, labels in enumerate(list_labels):
+ if labels[0] == method:
+ id = index
+ break
+ combobox.set_active(id)
+ combobox.connect('changed', self.on_cb_custom_key_table_changed, mode)
+
+ id = dlg.run()
+ dlg.hide()
+
+ self.__disconnect_dialog_custom_key_table_buttons()
+
+ def __set_thumb_kb_label(self):
+ if self.__thumb_kb_layout_mode == None or \
+ self.__thumb_kb_layout == None:
+ return
+ section, key = self.__get_section_key(
+ Gtk.Buildable.get_name(self.__thumb_kb_layout_mode))
+ layout_mode = self.prefs.get_value(section, key)
+ if layout_mode:
+ self.__thumb_kb_layout.set_sensitive(False)
+ else:
+ self.__thumb_kb_layout.set_sensitive(True)
+
+ def __get_dict_cli_from_list(self, cli_list):
+ cli_str = cli_list[0]
+ if len(cli_list) <= 2:
+ return cli_str
+ cli_str = cli_str + ' ' + ' '.join(cli_list[2:])
+ return cli_str
+
+ def __get_quoted_id(self, file):
+ id = file
+ has_mbcs = False
+
+ for i in range(0, len(id)):
+ if ord(id[i]) >= 0x7f:
+ has_mbcs = True
+ break
+ if has_mbcs:
+ id = str(binascii.hexlify(id.encode()), 'ascii')
+
+ if id.find('/') >=0:
+ id = id[id.rindex('/') + 1:]
+ if id.find('.') >=0:
+ id = id[:id.rindex('.')]
+
+ if id.startswith('0x'):
+ id = str(binascii.hexlify(id.encode()), 'ascii')
+ has_mbcs = True
+ if has_mbcs:
+ id = '0x' + id
+ return id
+
+ def __get_dict_file_from_id(self, selected_id):
+ files = self.prefs.get_value('dict', 'files')
+ retval = None
+
+ for file in files:
+ id = self.__get_quoted_id(file)
+ # The selected_id is already quoted.
+ if selected_id == id:
+ retval = file
+ break
+ return retval
+
+ def __is_system_dict_file_from_id(self, selected_id):
+ prefs = self.prefs
+ section = 'dict/file/' + selected_id
+ key = 'is_system'
+
+ if key not in prefs.keys(section):
+ return False
+ return prefs.get_value(section, key)
+
+ def __append_dict_id_in_model(self, id, is_gettext):
+ prefs = self.prefs
+ section = 'dict/file/' + id
+ # user value is dbus.String
+ prefs.set_value(section, 'short_label',
+ prefs.str(prefs.get_value(section, 'short_label')))
+ prefs.set_value(section, 'long_label',
+ prefs.str(prefs.get_value(section, 'long_label')))
+ short_label = prefs.get_value(section, 'short_label')
+ long_label = prefs.get_value(section, 'long_label')
+ embed = prefs.get_value(section, 'embed')
+ single = prefs.get_value(section, 'single')
+ reverse = prefs.get_value(section, 'reverse')
+ if is_gettext:
+ long_label = _(long_label)
+ l = self.__builder.get_object('dict:view').get_model()
+ l.append([id, short_label, long_label, embed, single, reverse])
+
+ def __append_dicts_in_model(self):
+ prefs = self.prefs
+ for file in prefs.get_value('dict', 'files'):
+ if not path.exists(file):
+ continue
+ id = self.__get_quoted_id(file)
+ section = 'dict/file/' + id
+ if section not in prefs.sections():
+ self.__fetch_dict_values(section)
+ is_system_dict = self.__is_system_dict_file_from_id(id)
+ self.__append_dict_id_in_model(id, is_system_dict)
+
+ def __append_user_dict_from_dialog(self, file, id, new):
+ files = self.prefs.get_value('dict', 'files')
+
+ if new:
+ if file in files:
+ self.__run_message_dialog(_("Your choosed file has already been added: ") + file,
+ Gtk.MessageType.ERROR)
+ return
+ if not path.exists(file):
+ self.__run_message_dialog(_("The file you have chosen does not exist: ") + file,
+ Gtk.MessageType.ERROR)
+ return
+ if path.isdir(file):
+ self.__run_message_dialog(_("Your choosed file is a directory: " + file),
+ Gtk.MessageType.ERROR)
+ return
+ if file.startswith(self.__get_userhome() + '/.anthy'):
+ self.__run_message_dialog(_("You cannot add dictionaries in the anthy private directory: " + file),
+ Gtk.MessageType.ERROR)
+ return
+
+ if new:
+ id = self.__get_quoted_id(file)
+ if id == None or id == '':
+ self.__run_message_dialog(_("Your file path is not good: ") + file,
+ Gtk.MessageType.ERROR)
+ return
+
+ single = self.__builder.get_object('dict:single').get_active()
+ embed = self.__builder.get_object('dict:embed').get_active()
+ reverse = self.__builder.get_object('dict:reverse').get_active()
+ short_label = self.__builder.get_object('dict:short_entry').get_text()
+ if len(short_label) > 1:
+ short_label = short_label[0]
+ long_label = self.__builder.get_object('dict:long_entry').get_text()
+
+ if new:
+ files.append(file)
+ self.prefs.set_value('dict', 'files', files)
+
+ if short_label == None or short_label == '':
+ short_label = id[0]
+ if long_label == None or long_label == '':
+ long_label = id
+ self.__update_dict_values(new, id, short_label, long_label, embed, single, reverse)
+ self.__builder.get_object('btn_apply').set_sensitive(True)
+ files = []
+
+ def __init_dict_chooser_dialog(self):
+ self.__builder.get_object('dict:single').set_active(True)
+ self.__builder.get_object('dict:embed').set_active(False)
+ self.__builder.get_object('dict:reverse').set_active(False)
+ short_entry = self.__builder.get_object('dict:short_entry')
+ short_entry.set_text('')
+ short_entry.set_editable(True)
+ long_entry = self.__builder.get_object('dict:long_entry')
+ long_entry.set_text('')
+ long_entry.set_editable(True)
+
+ def __get_selected_dict_id(self):
+ l, it = self.__builder.get_object('dict:view').get_selection().get_selected()
+
+ if not it:
+ return None
+ return l.get_value(it, 0)
+
+ def __set_selected_dict_to_dialog(self):
+ selected_id = self.__get_selected_dict_id()
+ if selected_id == None:
+ return None
+
+ is_system_dict = self.__is_system_dict_file_from_id(selected_id)
+
+ prefs = self.prefs
+ section = 'dict/file/' + selected_id
+ short_label = prefs.get_value(section, 'short_label')
+ long_label = prefs.get_value(section, 'long_label')
+ embed = prefs.get_value(section, 'embed')
+ single = prefs.get_value(section, 'single')
+ reverse = prefs.get_value(section, 'reverse')
+
+ if len(short_label) > 1:
+ short_label = short_label[0]
+ self.__builder.get_object('dict:single').set_active(single)
+ self.__builder.get_object('dict:embed').set_active(embed)
+ self.__builder.get_object('dict:reverse').set_active(reverse)
+ short_entry = self.__builder.get_object('dict:short_entry')
+ short_entry.set_text(short_label)
+ long_entry = self.__builder.get_object('dict:long_entry')
+ if is_system_dict:
+ short_entry.set_editable(False)
+ long_entry.set_text(_(long_label))
+ long_entry.set_editable(False)
+ else:
+ short_entry.set_editable(True)
+ long_entry.set_text(long_label)
+ long_entry.set_editable(True)
+
+ return selected_id
+
+ def __fetch_dict_values(self, section):
+ prefs = self.prefs
+ prefs.set_new_section(section)
+ prefs.set_new_key(section, 'short_label')
+ prefs.fetch_item(section, 'short_label')
+ # user value is dbus.String
+ prefs.set_value(section, 'short_label',
+ prefs.str(prefs.get_value(section, 'short_label')))
+ prefs.set_new_key(section, 'long_label')
+ prefs.fetch_item(section, 'long_label')
+ prefs.set_value(section, 'long_label',
+ prefs.str(prefs.get_value(section, 'long_label')))
+ prefs.set_new_key(section, 'embed')
+ prefs.fetch_item(section, 'embed')
+ prefs.set_new_key(section, 'single')
+ prefs.fetch_item(section, 'single')
+ prefs.set_new_key(section, 'reverse')
+ prefs.fetch_item(section, 'reverse')
+
+ def __update_dict_values(self, new, id, short_label, long_label, embed, single, reverse):
+ prefs = self.prefs
+ section = 'dict/file/' + id
+ if section not in prefs.sections():
+ prefs.set_new_section(section)
+
+ is_system_dict = self.__is_system_dict_file_from_id(id)
+ if is_system_dict:
+ if 'short_label' in prefs.keys(section):
+ short_label = prefs.get_value(section, 'short_label')
+ if 'long_label' in prefs.keys(section):
+ long_label = prefs.get_value(section, 'long_label')
+
+ if new:
+ l = self.__builder.get_object('dict:view').get_model()
+ l.append([id, short_label, long_label, embed, single, reverse])
+ else:
+ l, i = self.__builder.get_object('dict:view').get_selection().get_selected()
+ if i :
+ l[i] = [id, short_label, long_label, embed, single, reverse]
+
+ key = 'short_label'
+ prefs.set_value(section, key, short_label)
+ key = 'long_label'
+ prefs.set_value(section, key, long_label)
+ key = 'embed'
+ prefs.set_value(section, key, embed)
+ key = 'single'
+ prefs.set_value(section, key, single)
+ key = 'reverse'
+ prefs.set_value(section, key, reverse)
+
+ def __text_cell_data_cb(self, column, renderer, model, iter, id):
+ l = self.__builder.get_object('dict:view').get_model()
+ text = l.get_value(iter, id)
+ renderer.set_property('text', text)
+
+ def __toggle_cell_data_cb(self, column, renderer, model, iter, id):
+ l = self.__builder.get_object('dict:view').get_model()
+ active = l.get_value(iter, id)
+ renderer.set_property('active', active)
+
+ def __resync_engine_file(self):
+ user_config = path.join(self.__get_userhome(), '.config',
+ 'ibus-anthy', 'engines.xml')
+ system_config = path.join(config.PKGDATADIR, 'engine', 'default.xml')
+ if not path.exists(user_config):
+ return
+ if not path.exists(system_config):
+ os.unlink(user_config)
+ return
+
+ # path.getmtime depends on the build time rather than install time.
+ def __get_engine_file_version(engine_file):
+ version_str = ''
+ dom = xml.dom.minidom.parse(engine_file)
+ elements = dom.getElementsByTagName('version')
+ nodes = []
+ if len(elements) > 0:
+ nodes = elements[0].childNodes
+ if len(nodes) > 0:
+ version_str = nodes[0].data
+ if version_str != '':
+ version_str = version_str.strip()
+ return version_str
+
+ user_config_version = __get_engine_file_version(user_config)
+ system_config_version = __get_engine_file_version(system_config)
+ if system_config_version > user_config_version:
+ import shutil
+ shutil.copyfile(system_config, user_config)
+
+ def __get_engine_file(self):
+ user_config = path.join(self.__get_userhome(), '.config',
+ 'ibus-anthy', 'engines.xml')
+ system_config = path.join(config.PKGDATADIR, 'engine', 'default.xml')
+ engine_file = None
+ for f in [user_config, system_config]:
+ if path.exists(f):
+ engine_file = f
+ break
+ if engine_file == None:
+ self.__run_message_dialog(_("The engine xml file does not exist: ") + system_config,
+ Gtk.MessageType.ERROR)
+ return None
+ return engine_file
+
+ def __get_keymap(self):
+ keymap = ''
+ layout = ''
+ variant = ''
+ option = ''
+ engine_file = self.__get_engine_file()
+ if engine_file == None:
+ return None
+
+ dom = xml.dom.minidom.parse(engine_file)
+ nodes = dom.getElementsByTagName('layout')[0].childNodes
+ if len(nodes) > 0:
+ layout = nodes[0].data
+ if layout != '':
+ keymap = layout.strip()
+ nodes = dom.getElementsByTagName('layout_variant')[0].childNodes
+ if len(nodes) > 0:
+ variant = nodes[0].data
+ if variant != '':
+ keymap += '(' + varaint.strip() + ')'
+ nodes = dom.getElementsByTagName('layout_option')[0].childNodes
+ if len(nodes) > 0:
+ option = nodes[0].data
+ if option != '':
+ keymap += '[' + option.strip() + ']'
+ return keymap
+
+ def __parse_keymap(self, keymap):
+ layout = None
+ variant = None
+ option = None
+
+ length = keymap.find('(')
+ if length >= 0:
+ if layout == None:
+ layout = keymap[0:length]
+ keymap = keymap[length + 1:]
+ length = keymap.find(')')
+ if length > 0:
+ variant = keymap[0:length]
+ keymap = keymap[length + 1:]
+ else:
+ print('Invalid keymap', keymap, file=sys.stderr)
+ return ('', '', '')
+ length = keymap.find('[')
+ if length >= 0:
+ if layout == None:
+ layout = keymap[0:length]
+ keymap = keymap[length + 1:]
+ length = keymap.find(']')
+ if length > 0:
+ option = keymap[0:length]
+ keymap = keymap[length + 1:]
+ else:
+ print('Invalid keymap', keymap, file=sys.stderr)
+ return ('', '', '')
+
+ if layout == None:
+ layout = keymap
+ if layout == None:
+ layout = ''
+ if variant == None:
+ variant = ''
+ if option == None:
+ option = ''
+ return (layout, variant, option)
+
+ def __save_keymap(self):
+ engine_file = self.__get_engine_file()
+ if engine_file == None:
+ return None
+
+ (layout, variant, option) = self.__parse_keymap(self.__keymap)
+
+ dom = xml.dom.minidom.parse(engine_file)
+ nodes = dom.getElementsByTagName('layout')[0].childNodes
+ if len(nodes) == 0:
+ nodes.append(dom.createTextNode(layout))
+ else:
+ nodes[0].data = layout
+ nodes = dom.getElementsByTagName('layout_variant')[0].childNodes
+ if len(nodes) == 0:
+ nodes.append(dom.createTextNode(variant))
+ else:
+ nodes[0].data = variant
+ nodes = dom.getElementsByTagName('layout_option')[0].childNodes
+ if len(nodes) == 0:
+ nodes.append(dom.createTextNode(option))
+ else:
+ nodes[0].data = option
+ nodes = dom.getElementsByTagName('symbol')[0].childNodes
+ user_config = path.join(self.__get_userhome(), '.config',
+ 'ibus-anthy', 'engines.xml')
+ dir = path.dirname(user_config)
+ if not path.exists(dir):
+ os.makedirs(dir, 0o700)
+ # io.open() causes TypeError for unicode.
+ f = codecs.open(user_config, 'w', 'utf-8')
+ dom.writexml(f, '', '', '', 'utf-8')
+ f.close()
+ os.chmod(user_config, 0o600)
+ self.__keymap = None
+ self.__run_message_dialog(_("Anthy keyboard layout is changed. "
+ "Please restart ibus to reload the layout."))
+
+ def __update_keymap_label(self):
+ self.__resync_engine_file()
+ prefs = self.prefs
+ keymap = self.__get_keymap()
+ if keymap == None:
+ return
+ if keymap == '':
+ keymap = 'default'
+ keymap_list = prefs.get_value('common', 'keyboard_layouts')
+ if keymap != None and not keymap in keymap_list:
+ keymap_list.append(keymap)
+ index = -1
+ if keymap != None:
+ index = keymap_list.index(keymap)
+ model = Gtk.ListStore(str)
+ for k in keymap_list:
+ if k == 'default':
+ k = _("Default")
+ model.append([k])
+ combobox = self.__builder.get_object('keymap:combobox_custom_table')
+ combobox.set_model(model)
+ combobox.set_active(0)
+ if index >= 0:
+ combobox.set_active(index)
+ combobox.connect_after('changed',
+ self.on_cb_keymap_changed,
+ 0)
+
+ def __save_preferences(self):
+ self.prefs.commit_all()
+ if self.__keymap != None:
+ self.__save_keymap()
+
+ def on_selection_changed(self, widget, id):
+ set_sensitive = lambda a, b: self.__builder.get_object(a).set_sensitive(b)
+ flg = True if widget.get_selected()[1] else False
+ for name in [['btn_default', 'btn_edit'], ['es:button_refresh', 'es:button_del']][id]:
+ set_sensitive(name, flg)
+
+ def on_selection_custom_key_table_changed(self, widget, id):
+ l, i = widget.get_selected()
+ # if 'combobox_custom_key_table' is changed,
+ # 'treeview_custom_key_table' also receives this signal
+ # but no selection.
+ if i == None:
+ return
+ button = self.__builder.get_object('button_remove_custom_key')
+ button.set_sensitive(True)
+
+ def on_main_delete(self, widget, event):
+ self.on_btn_cancel_clicked(widget)
+ return True
+
+ def on_btn_ok_clicked(self, widget):
+ if self.__builder.get_object('btn_apply').get_state() == \
+ Gtk.StateType.INSENSITIVE:
+ Gtk.main_quit()
+ return True
+ dlg = self.__builder.get_object('quit_check')
+ dlg.set_markup('<big><b>%s</b></big>' % _("Confirmation"))
+ dlg.format_secondary_text(
+ _("You are about to close the setup dialog, is that OK?"))
+ id = dlg.run()
+ dlg.hide()
+ if id == Gtk.ResponseType.YES:
+ self.__save_preferences()
+ Gtk.main_quit()
+ return True
+
+ def on_btn_cancel_clicked(self, widget):
+ if self.__builder.get_object('btn_apply').get_state() == \
+ Gtk.StateType.INSENSITIVE:
+ Gtk.main_quit()
+ return True
+ dlg = self.__builder.get_object('quit_check_without_save')
+ dlg.set_markup('<big><b>%s</b></big>' % _("Notice!"))
+ dlg.format_secondary_text(
+ _("You are about to close the setup dialog without saving your changes, is that OK?"))
+ id = dlg.run()
+ dlg.hide()
+ if id == Gtk.ResponseType.YES:
+ Gtk.main_quit()
+ return True
+
+ def on_btn_apply_clicked(self, widget):
+ self.__save_preferences()
+ widget.set_sensitive(False)
+
+ def on_cb_changed(self, widget):
+ section, key = self.__get_section_key(Gtk.Buildable.get_name(widget))
+ self.prefs.set_value(section, key, widget.get_active())
+ self.__builder.get_object('btn_apply').set_sensitive(True)
+
+ def on_cb_keymap_changed(self, widget, id):
+ it = widget.get_active()
+ model = widget.get_model()
+ keymap = model[it][0]
+ if keymap == _("Default"):
+ keymap = 'default'
+ if self.__keymap == keymap:
+ return
+ self.__keymap = keymap
+ self.__builder.get_object('btn_apply').set_sensitive(True)
+
+ def on_cb_custom_key_table_changed(self, widget, user_data):
+ prefs = self.prefs
+ tv = self.__builder.get_object('treeview_custom_key_table')
+ mode = user_data
+ id = widget.get_active()
+ model = widget.get_model()
+ method = model[id][1]
+ if tv != None:
+ for column in tv.get_columns():
+ tv.remove_column(column)
+ for child in tv.get_children():
+ tv.remove(child)
+ if mode == 'romaji':
+ tv = self.__get_romaji_treeview_custom_key_table(method)
+ elif mode == 'kana':
+ prefs.set_value('kana_typing_rule', 'method', method)
+ self.__builder.get_object('btn_apply').set_sensitive(True)
+ tv = self.__get_kana_treeview_custom_key_table(method)
+ elif mode == 'thumb':
+ # thumb uses all tables so do not save the method.
+ tv = self.__get_thumb_treeview_custom_key_table(method)
+
+ def on_sb_changed(self, widget):
+ section, key = self.__get_section_key(Gtk.Buildable.get_name(widget))
+ self.prefs.set_value(section, key, widget.get_value_as_int())
+ self.__builder.get_object('btn_apply').set_sensitive(True)
+
+ def on_ck_toggled(self, widget):
+ section, key = self.__get_section_key(Gtk.Buildable.get_name(widget))
+ self.prefs.set_value(section, key, widget.get_active())
+ self.__builder.get_object('btn_apply').set_sensitive(True)
+ if self.__thumb_kb_layout_mode and \
+ Gtk.Buildable.get_name(widget) == \
+ Gtk.Buildable.get_name(self.__thumb_kb_layout_mode):
+ self.__set_thumb_kb_label()
+
+ def on_btn_edit_clicked(self, widget):
+ ls, it = self.__builder.get_object('shortcut').get_selection().get_selected()
+ m = self.__builder.get_object('es:treeview').get_model()
+ m.clear()
+ for s in s_to_l(ls.get(it, 1)[0]):
+ m.append([s])
+ self.__builder.get_object('es:entry').set_text('')
+ for w in ['es:checkbutton_ctrl', 'es:checkbutton_alt', 'es:checkbutton_shift']:
+ self.__builder.get_object(w).set_active(False)
+ dlg = self.__builder.get_object('edit_shortcut')
+ id = dlg.run()
+ dlg.hide()
+ if id == Gtk.ResponseType.OK:
+ new = l_to_s([m[i][0] for i in range(len(m))])
+ if new != ls.get(it, 1)[0]:
+ sec = self._get_shortcut_sec()
+ self.prefs.set_value(sec, ls.get(it, 0)[0], s_to_l(new))
+ ls.set(it, 1, new)
+ self.__builder.get_object('btn_apply').set_sensitive(True)
+
+ def on_btn_default_clicked(self, widget):
+ ls, it = self.__builder.get_object('shortcut').get_selection().get_selected()
+ sec = self._get_shortcut_sec()
+ new = l_to_s(self.prefs.default[sec][ls.get(it, 0)[0]])
+ if new != ls.get(it, 1)[0]:
+ self.prefs.set_value(sec, ls.get(it, 0)[0], s_to_l(new))
+ ls.set(it, 1, new)
+ self.__builder.get_object('btn_apply').set_sensitive(True)
+
+ def on_btn_romaji_custom_table_clicked(self, widget):
+ self.__run_dialog_custom_key_table('romaji')
+
+ def on_btn_kana_custom_table_clicked(self, widget):
+ self.__run_dialog_custom_key_table('kana')
+
+ def on_btn_thumb_custom_table_clicked(self, widget):
+ self.__run_dialog_custom_key_table('thumb')
+
+ def on_btn_add_custom_key(self, widget, user_data):
+ prefs = self.prefs
+ input = self.__builder.get_object('entry_input_custom_key')
+ output = self.__builder.get_object('entry_output_custom_key')
+ left = self.__builder.get_object('entry_left_thumb_shift_custom_key')
+ right = self.__builder.get_object('entry_right_thumb_shift_custom_key')
+ model = self.__builder.get_object('treeview_custom_key_table').get_model()
+ combobox = self.__builder.get_object('combobox_custom_key_table')
+ id = combobox.get_active()
+ model_combobox = combobox.get_model()
+ method = model_combobox[id][1]
+ type = user_data
+ section_base = None
+ key = input.get_text()
+ value = output.get_text()
+ left_text = left.get_text()
+ right_text = right.get_text()
+
+ if key == None:
+ self.__run_message_dialog(_("Please specify Input Chars"))
+ return
+ elif value == None:
+ self.__run_message_dialog(_("Please specify Output Chars"))
+ return
+ elif type == 'thumb' and left_text == None:
+ self.__run_message_dialog(_("Please specify Left Thumb Shift Chars"))
+ return
+ elif type == 'thumb' and right_text == None:
+ self.__run_message_dialog(_("Please specify Right Thumb Shift Chars"))
+ return
+
+ if type == 'romaji':
+ section_base = 'romaji_typing_rule'
+ model.append([type, key, value])
+ elif type == 'kana':
+ section_base = 'kana_typing_rule'
+ model.append([type, key, value])
+ elif type == 'thumb':
+ section_base = 'thumb_typing_rule'
+ model.append([type, key, value, left_text, right_text])
+ if section_base == None:
+ self.__run_message_dialog(_("Your custom key is not assigned in any sections. Maybe a bug."))
+ return
+ gkey = prefs.typing_to_config_key(key)
+ if gkey == '':
+ return
+ key = gkey
+ section = section_base + '/' + method
+ if key not in prefs.keys(section):
+ # ibus does not support gconf_client_all_entries().
+ # prefs.fetch_section() doesn't get the keys if they exist
+ # in gconf only.
+ # Use newkeys for that way.
+ newkeys = prefs.get_value(section_base, 'newkeys')
+ if key not in newkeys:
+ newkeys.append(key)
+ prefs.set_value(section_base, 'newkeys', newkeys)
+ if type != 'thumb':
+ prefs.set_value(section, key, value)
+ else:
+ prefs.set_value(section, key, [value, right_text, left_text])
+ left.set_text('')
+ right.set_text('')
+ input.set_text('')
+ output.set_text('')
+ self.__builder.get_object('btn_apply').set_sensitive(True)
+
+ def on_btn_remove_custom_key(self, widget, user_data):
+ prefs = self.prefs
+ combobox = self.__builder.get_object('combobox_custom_key_table')
+ id = combobox.get_active()
+ model_combobox = combobox.get_model()
+ method = model_combobox[id][1]
+ tv = user_data
+ l, i = tv.get_selection().get_selected()
+ type = l[i][0]
+ key = l[i][1]
+ section_base = None
+ if type == 'romaji':
+ section_base = 'romaji_typing_rule'
+ elif type == 'kana':
+ section_base = 'kana_typing_rule'
+ elif type == 'thumb':
+ section_base = 'thumb_typing_rule'
+ if section_base == None:
+ self.__run_message_dialog(_("Your custom key is not assigned in any sections. Maybe a bug."))
+ return
+ section = section_base + '/' + method
+ newkeys = prefs.get_value(section_base, 'newkeys')
+ gkey = prefs.typing_to_config_key(key)
+ if gkey == '':
+ return
+ key = gkey
+ if key in newkeys:
+ newkeys.remove(key)
+ prefs.set_value(section_base, 'newkeys', newkeys)
+ # config.set_value(key, None) is not supported.
+ if type != 'thumb':
+ prefs.set_value(section, key, '')
+ else:
+ prefs.set_value(section, key, ['', '', ''])
+ l.remove(i)
+ widget.set_sensitive(False)
+ self.__builder.get_object('btn_apply').set_sensitive(True)
+
+ def on_btn_thumb_key_clicked(self, widget):
+ if Gtk.Buildable.get_name(widget) == 'thumb:button_ls':
+ entry = 'thumb:ls'
+ elif Gtk.Buildable.get_name(widget) == 'thumb:button_rs':
+ entry = 'thumb:rs'
+ else:
+ return
+ text = self.__builder.get_object(entry).get_text()
+ tv = self.__builder.get_object('es:treeview')
+ m = tv.get_model()
+ m.clear()
+ if text != None:
+ m.append([text])
+ i = m.get_iter_first()
+ tv.get_selection().select_iter(i)
+ self.__builder.get_object('es:entry').set_text('')
+ self.__builder.get_object('es:button_add').hide()
+ self.__builder.get_object('es:button_refresh').show()
+ self.__builder.get_object('es:button_del').hide()
+ for w in ['es:checkbutton_ctrl', 'es:checkbutton_alt', 'es:checkbutton_shift']:
+ self.__builder.get_object(w).set_active(False)
+ dlg = self.__builder.get_object('edit_shortcut')
+ id = dlg.run()
+ dlg.hide()
+ self.__builder.get_object('es:button_add').show()
+ self.__builder.get_object('es:button_refresh').hide()
+ self.__builder.get_object('es:button_del').show()
+ if id == Gtk.ResponseType.OK:
+ l, i = tv.get_selection().get_selected()
+ new = l[i][0]
+ if new != text:
+ section, key = self.__get_section_key(entry)
+ self.prefs.set_value(section, key, new)
+ self.__builder.get_object(entry).set_text(new)
+ self.__builder.get_object('btn_apply').set_sensitive(True)
+
+ def on_btn_dict_command_clicked(self, widget):
+ if Gtk.Buildable.get_name(widget) == 'dict:btn_edit_dict_command':
+ key = 'dict_admin_command'
+ elif Gtk.Buildable.get_name(widget) == 'dict:btn_add_word_command':
+ key = 'add_word_command'
+ else:
+ return
+ command = self.prefs.get_value('common', key)
+ if not path.exists(command[0]):
+ self.__run_message_dialog(_("Your file does not exist: ") + command[0],
+ Gtk.MessageType.ERROR)
+ return
+ os.spawnl(os.P_NOWAIT, *command)
+
+ def on_btn_dict_add_clicked(self, widget):
+ file = None
+ id = None
+
+ if Gtk.Buildable.get_name(widget) == 'dict:btn_add':
+ dlg = Gtk.FileChooserDialog(title=_("Open Dictionary File"),
+ parent=self.__builder.get_object('main'),
+ action=Gtk.FileChooserAction.OPEN,
+ buttons=(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
+ Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
+ if Gtk.Buildable.get_name(widget) == 'dict:btn_edit':
+ dlg = Gtk.Dialog(title=_("Edit Dictionary File"),
+ parent=self.__builder.get_object('main'),
+ flags=Gtk.DialogFlags.MODAL,
+ buttons=(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
+ Gtk.STOCK_OK, Gtk.ResponseType.OK))
+
+ vbox = self.__builder.get_object('dict:add_extra_vbox')
+ if Gtk.Buildable.get_name(widget) == 'dict:btn_add':
+ # Need to init for the second time
+ self.__init_dict_chooser_dialog()
+ dlg.set_extra_widget(vbox)
+ if Gtk.Buildable.get_name(widget) == 'dict:btn_edit':
+ id = self.__set_selected_dict_to_dialog()
+ if id == None:
+ self.__run_message_dialog(_("Your choosed file is not correct."),
+ Gtk.MessageType.ERROR)
+ return
+ parent_vbox = dlg.vbox
+ parent_vbox.add(vbox)
+ vbox.show_all()
+
+ if dlg.run() == Gtk.ResponseType.OK:
+ if Gtk.Buildable.get_name(widget) == 'dict:btn_add':
+ file = dlg.get_filename()
+ if file[0] != '/':
+ dir = dlg.get_current_folder()
+ file = dir + '/' + file
+ self.__append_user_dict_from_dialog(file, None, True)
+ elif Gtk.Buildable.get_name(widget) == 'dict:btn_edit':
+ self.__append_user_dict_from_dialog(None, id, False)
+ dlg.hide()
+ vbox.unparent()
+
+ def on_btn_dict_delete_clicked(self, widget):
+ l, i = self.__builder.get_object('dict:view').get_selection().get_selected()
+
+ if not i:
+ return
+ selected_id = l.get_value(i, 0)
+
+ if selected_id == None:
+ return
+ if self.__is_system_dict_file_from_id(selected_id):
+ self.__run_message_dialog(_("You cannot delete the system dictionary."),
+ Gtk.MessageType.ERROR)
+ return
+
+ file = self.__get_dict_file_from_id(selected_id)
+ if file != None:
+ files = self.prefs.get_value('dict', 'files')
+ files.remove(file)
+ self.prefs.set_value('dict', 'files', files)
+ self.__builder.get_object('btn_apply').set_sensitive(True)
+ l.remove(i)
+ return
+
+ l.remove(i)
+
+ def on_btn_dict_view_clicked(self, widget):
+ dict_file = None
+ selected_id = self.__get_selected_dict_id()
+ if selected_id == None:
+ return
+
+ dict_file = self.__get_dict_file_from_id(selected_id)
+ if dict_file == None:
+ self.__run_message_dialog(_("Your file is not good."),
+ Gtk.MessageType.ERROR)
+ return
+ if not path.exists(dict_file):
+ self.__run_message_dialog(_("Your file does not exist: ") + dict_file,
+ Gtk.MessageType.ERROR)
+ return
+
+ if dict_file == None:
+ return
+
+ # The selected id is already quoted.
+ section = 'dict/file/' + selected_id
+ if 'preview_lines' not in self.prefs.keys(section):
+ section = 'dict/file/default'
+ nline = self.prefs.get_value(section, 'preview_lines')
+
+ section = 'dict/file/' + selected_id
+ if 'encoding' not in self.prefs.keys(section):
+ section = 'dict/file/default'
+ encoding = self.prefs.get_value(section, 'encoding')
+
+ lines = '';
+ for i, line in enumerate(list(codecs.open(dict_file, 'r', 'utf-8'))):
+ if nline >= 0 and i >= nline:
+ break;
+ lines = lines + line
+ if encoding != None and encoding != 'utf-8':
+ lines = str(lines, encoding)
+
+ dlg = Gtk.Dialog(title=_("View Dictionary File"),
+ parent=self.__builder.get_object('main'),
+ flags=Gtk.DialogFlags.MODAL,
+ buttons=(Gtk.STOCK_OK, Gtk.ResponseType.OK))
+ buffer = Gtk.TextBuffer()
+ buffer.set_text (lines)
+ text_view = Gtk.TextView.new_with_buffer(buffer)
+ text_view.set_editable(False)
+ sw = Gtk.ScrolledWindow()
+ sw.add(text_view)
+ sw.set_min_content_height(400)
+ parent_vbox = dlg.vbox
+ parent_vbox.add(sw)
+ sw.show_all()
+ dlg.set_default_size(500, 500)
+ dlg.run()
+ dlg.destroy()
+
+ def on_btn_dict_order_clicked(self, widget):
+ dict_file = None
+ l, it = self.__builder.get_object('dict:view').get_selection().get_selected()
+
+ if not it:
+ return
+ selected_path = l.get_path(it)
+ selected_id = l.get_value(it, 0)
+ index = selected_path.get_indices()[0]
+
+ if Gtk.Buildable.get_name(widget) == 'dict:btn_up':
+ if index <= 0:
+ return
+ next_path = (index - 1, )
+ elif Gtk.Buildable.get_name(widget) == 'dict:btn_down':
+ if index + 1 >= len(l):
+ return
+ next_path = (index + 1, )
+ next_it = l.get_iter(next_path)
+ if next_it:
+ l.swap(it, next_it)
+
+ dict_file = self.__get_dict_file_from_id(selected_id)
+ files = self.prefs.get_value('dict', 'files')
+
+ if dict_file == None:
+ return
+
+ i = files.index(dict_file)
+ if Gtk.Buildable.get_name(widget) == 'dict:btn_up':
+ if i <= 0:
+ return
+ next_i = i - 1
+ elif Gtk.Buildable.get_name(widget) == 'dict:btn_down':
+ if i + 1 >= len(dict_file):
+ return
+ next_i = i + 1
+ f = files[i]
+ files[i] = files[next_i]
+ files[next_i] = f
+ self.prefs.set_value('dict', 'files', files)
+ self.__builder.get_object('btn_apply').set_sensitive(True)
+
+ def _get_shortcut_sec(self):
+ l = ['default', 'atok', 'wnn']
+ iter = self.__builder.get_object('shortcut_type').get_active_iter()
+ model = self.__builder.get_object('shortcut_type').get_model()
+ s_type = model[iter][0].lower()
+ return 'shortcut/' + (s_type if s_type in l else 'default')
+
+ def on_shortcut_type_changed(self, widget):
+ ls = self.__builder.get_object('shortcut').get_model()
+ ls.clear()
+
+ sec = self._get_shortcut_sec()
+ for k in self.prefs.keys(sec):
+ ls.append([k, l_to_s(self.prefs.get_value(sec, k))])
+
+ section, key = self.__get_section_key(Gtk.Buildable.get_name(widget))
+ self.prefs.set_value(section, key, sec[len('shortcut/'):])
+ self.__builder.get_object('btn_apply').set_sensitive(True)
+
+ def on_shortcut_key_release_event(self, widget, event):
+ if event.hardware_keycode in [36, 65]:
+ self.on_btn_edit_clicked(None)
+
+ def on_shortcut_click_event(self, widget, event):
+ if event.type == Gdk.EventType._2BUTTON_PRESS:
+ widget.dc = True
+ elif event.type == Gdk.EventType.BUTTON_RELEASE:
+ if hasattr(widget, 'dc') and widget.dc:
+ self.on_btn_edit_clicked(None)
+ widget.dc = False
+
+ def on_key_input_dialog_key_press_event(self, widget, event):
+ widget.e = (event.keyval, event.get_state())
+ return True
+
+ def on_key_input_dialog_key_release_event(self, widget, event):
+ widget.response(Gtk.ResponseType.OK)
+ return True
+
+ def on_entry_custom_key_changed(self, widget, user_data):
+ mode = user_data
+ input = self.__builder.get_object('entry_input_custom_key')
+ output = self.__builder.get_object('entry_output_custom_key')
+ left = self.__builder.get_object('entry_left_thumb_shift_custom_key')
+ right = self.__builder.get_object('entry_right_thumb_shift_custom_key')
+ button = self.__builder.get_object('button_add_custom_key')
+ if mode != 'thumb':
+ if input.get_text() != '' and output.get_text() != '':
+ button.set_sensitive(True)
+ else:
+ button.set_sensitive(False)
+ else:
+ if input.get_text() != '' and output.get_text() != '' and \
+ left.get_text() != '' and right.get_text() != '':
+ button.set_sensitive(True)
+ else:
+ button.set_sensitive(False)
+
+ def on_entry_dict_command_changed(self, widget):
+ if not widget.get_text():
+ return
+ list = widget.get_text().split()
+ if list[0][0] == '/':
+ if len(list) == 1:
+ list.append(list[0][list[0].rfind('/') + 1:])
+ else:
+ list.insert(1, list[0][list[0].rfind('/') + 1:])
+ else:
+ if len(list) == 1:
+ list[0] = '/usr/bin/' + list[0]
+ else:
+ list.insert(0, '/usr/bin/' + list[0])
+ list[1] = list[1][list[1].rfind('/') + 1:]
+ if Gtk.Buildable.get_name(widget) == 'dict:entry_edit_dict_command':
+ key = 'dict_admin_command'
+ elif Gtk.Buildable.get_name(widget) == 'dict:entry_add_word_command':
+ key = 'add_word_command'
+ else:
+ return
+ self.prefs.set_value('common', key, list)
+ self.__builder.get_object('btn_apply').set_sensitive(True)
+
+ def on_es_entry_changed(self, widget):
+ if not widget.get_text():
+ self.__builder.get_object('es:button_add').set_sensitive(False)
+ else:
+ self.__builder.get_object('es:button_add').set_sensitive(True)
+
+ def on_es_button_run_input_clicked(self, widget):
+ dlg = self.__builder.get_object('key_input_dialog')
+ dlg.set_markup('<big><b>%s</b></big>' % _("Please press a key (or a key combination)"))
+ dlg.format_secondary_text(_("The dialog will be closed when the key is released"))
+ id = dlg.run()
+ dlg.hide()
+ if id == Gtk.ResponseType.OK:
+ key, state = dlg.e
+ if (state & (IBus.ModifierType.CONTROL_MASK | IBus.ModifierType.MOD1_MASK) and
+ ord('a') <= key <= ord('z')):
+ key = ord(chr(key).upper())
+ self.__builder.get_object('es:entry').set_text(IBus.keyval_name(key))
+
+ for w, i in [('es:checkbutton_ctrl', IBus.ModifierType.CONTROL_MASK),
+ ('es:checkbutton_alt', IBus.ModifierType.MOD1_MASK),
+ ('es:checkbutton_shift', IBus.ModifierType.SHIFT_MASK)]:
+ self.__builder.get_object(w).set_active(True if state & i else False)
+
+ def on_es_button_add_clicked(self, widget):
+ s = self.__builder.get_object('es:entry').get_text()
+ if not s or not IBus.keyval_from_name(s):
+ dlg = self.__builder.get_object('invalid_keysym')
+ dlg.set_markup('<big><b>%s</b></big>' % _("Invalid keysym"))
+ dlg.format_secondary_text(_("This keysym is not valid"))
+ dlg.run()
+ dlg.hide()
+ return True
+ for w, m in [('es:checkbutton_ctrl', 'Ctrl+'),
+ ('es:checkbutton_alt', 'Alt+'),
+ ('es:checkbutton_shift', 'Shift+')]:
+ if self.__builder.get_object(w).get_active():
+ s = m + s
+ l = self.__builder.get_object('es:treeview').get_model()
+ for i in range(len(l)):
+ if l[i][0] == s:
+ return True
+ l.append([s])
+
+ def on_es_button_refresh_clicked(self, widget):
+ s = self.__builder.get_object('es:entry').get_text()
+ if not s or not IBus.keyval_from_name(s):
+ dlg = self.__builder.get_object('invalid_keysym')
+ dlg.set_markup('<big><b>%s</b></big>' % _("Invalid keysym"))
+ dlg.format_secondary_text(_("This keysym is not valid"))
+ dlg.run()
+ dlg.hide()
+ return True
+ for w, m in [('es:checkbutton_ctrl', 'Ctrl+'),
+ ('es:checkbutton_alt', 'Alt+'),
+ ('es:checkbutton_shift', 'Shift+')]:
+ if self.__builder.get_object(w).get_active():
+ s = m + s
+ tv = self.__builder.get_object('es:treeview')
+ l, i = tv.get_selection().get_selected()
+ l[i][0] = s
+ return True
+
+ def on_es_button_del_clicked(self, widget):
+ tv = self.__builder.get_object('es:treeview')
+ l, i = tv.get_selection().get_selected()
+ if i:
+ l.remove(i)
+
+ def run(self):
+ Gtk.main()
+
+if __name__ == '__main__':
+ AnthySetup().run()
+
diff --git a/setup/python3/prefs.py b/setup/python3/prefs.py
new file mode 100644
index 0000000..a4af88d
--- /dev/null
+++ b/setup/python3/prefs.py
@@ -0,0 +1,273 @@
+# vim:set noet ts=4:
+#
+# ibus-anthy - The Anthy engine for IBus
+#
+# Copyright (c) 2007-2008 Peng Huang <shawn.p.huang@gmail.com>
+# Copyright (c) 2009 Hideaki ABE <abe.sendai@gmail.com>
+# Copyright (c) 2010-2014 Takao Fujiwara <takao.fujiwara1@gmail.com>
+# Copyright (c) 2007-2014 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+import sys
+
+from gi.repository import GLib
+from gi.repository import IBus
+
+class Prefs(object):
+ _prefix = 'engine/dummy'
+
+ def __init__(self, bus=None, config=None):
+ self.default = {}
+ self.modified = {}
+ self.new = {}
+ self.__no_key_warning = False
+
+ # self._config is used by AnthyPrefs .
+ self._config = config if config else \
+ bus.get_config() if bus else \
+ IBus.Bus().get_config()
+
+ # ibus_config_get_values enhances the performance.
+ self.__has_config_get_values = False
+
+ if self._config != None:
+ self.__has_config_get_values = hasattr(self._config, 'get_values')
+ else:
+ self.printerr(
+ 'ibus-config is not running or bus address is not correct.')
+
+ def __log_handler(self, domain, level, message, data):
+ if not data:
+ return
+ GLib.log_default_handler(domain, level, message, '')
+
+ def variant_to_value(self, variant):
+ if type(variant) != GLib.Variant:
+ return variant
+ type_string = variant.get_type_string()
+ if type_string == 's':
+ return variant.get_string()
+ elif type_string == 'i':
+ return variant.get_int32()
+ elif type_string == 'b':
+ return variant.get_boolean()
+ elif type_string == 'as':
+ # Use unpack() instead of dup_strv() in python.
+ # In the latest pygobject3 3.3.4 or later, g_variant_dup_strv
+ # returns the allocated strv but in the previous release,
+ # it returned the tuple of (strv, length)
+ return variant.unpack()
+ else:
+ self.printerr('Unknown variant type: %s' % type_string)
+ sys.abrt()
+ return variant
+
+ def set_no_key_warning(self, no_key_warning):
+ if no_key_warning and hasattr(IBus, 'unset_log_handler'):
+ self.__no_key_warning = True
+ else:
+ self.__no_key_warning = False
+
+ def keys(self, section):
+ return list(self.default[section].keys())
+
+ def sections(self):
+ return list(self.default.keys())
+
+ def set_new_section(self, section):
+ self.default.setdefault(section, {})
+
+ def set_new_key(self, section, key):
+ self.default[section].setdefault(key)
+
+ def get_value(self, section, key):
+ try:
+ return self.new[section][key]
+ except:
+ try:
+ return self.modified[section][key]
+ except:
+ return self.default[section][key]
+
+ def get_value_direct(self, section, key, default=None):
+ if self._config == None:
+ return default
+
+ s = section
+ section = '/'.join(
+ [s for s in '/'.join([self._prefix, section]).split('/') if s])
+ try:
+ if self.__no_key_warning:
+ IBus.set_log_handler(False)
+ variant = self._config.get_value(section, key)
+ if self.__no_key_warning:
+ IBus.unset_log_handler()
+ return self.variant_to_value(variant)
+ except:
+ return default
+
+ def set_value(self, section, key, value):
+ if section not in self.sections():
+ self.set_new_section(section)
+ if key not in self.keys(section):
+ self.set_new_key(section, key)
+ self.default[section][key]
+ self.new.setdefault(section, {})[key] = value
+
+ def fetch_all(self):
+ for s in self.sections():
+ self.fetch_section(s)
+
+ def fetch_section(self, section):
+ if self._config == None:
+ return
+
+ if not self.__has_config_get_values:
+ for k in self.keys(section):
+ self.fetch_item(section, k)
+ return
+
+ s = '/'.join(
+ [s for s in '/'.join([self._prefix, section]).split('/') if s])
+ variant = self._config.get_values(s)
+ for key in list(variant.keys()):
+ v = variant[key]
+ self.modified.setdefault(section, {})[key] = v if v != [''] else []
+ # FIXME: ibus-dconf converts the keys.
+ if section == 'common':
+ self.fetch_item(section, 'show-input-mode')
+ self.fetch_item(section, 'show-typing-method')
+ self.fetch_item(section, 'show-segment-mode')
+ self.fetch_item(section, 'show-dict-mode')
+ self.fetch_item(section, 'show-dict-config')
+ self.fetch_item(section, 'show-preferences')
+
+ def fetch_item(self, section, key, readonly=False):
+ if self._config == None:
+ return
+
+ s = '/'.join(
+ [s for s in '/'.join([self._prefix, section]).split('/') if s])
+ try:
+ v = None
+ # gobject-introspection has a bug.
+ # https://bugzilla.gnome.org/show_bug.cgi?id=670509
+ # GLib.log_set_handler("IBUS", GLib.LogLevelFlags.LEVEL_MASK,
+ # self.__log_handler, False)
+ if self.__no_key_warning:
+ IBus.set_log_handler(False)
+ variant = self._config.get_value(s, key)
+ if self.__no_key_warning:
+ IBus.unset_log_handler()
+ v = self.variant_to_value(variant)
+ except:
+ v = None
+ if readonly:
+ return v != None
+ if v != None:
+ self.modified.setdefault(section, {})[key] = v if v != [''] else []
+ return True
+
+ def commit_all(self):
+ for s in list(self.new.keys()):
+ self.commit_section(s)
+
+ def commit_section(self, section):
+ if section in self.new:
+ for k in list(self.new[section].keys()):
+ self.commit_item(section, k)
+
+ def commit_item(self, section, key):
+ if section in self.new and key in self.new[section]:
+ s = '/'.join(
+ [s for s in '/'.join([self._prefix, section]).split('/') if s])
+ v = self.new[section][key]
+ if v == []:
+ v = ['']
+ variant = None
+ if type(v) == str:
+ variant = GLib.Variant.new_string(v)
+ elif type(v) == int:
+ variant = GLib.Variant.new_int32(v)
+ elif type(v) == bool:
+ variant = GLib.Variant.new_boolean(v)
+ elif type(v) == list:
+ variant = GLib.Variant.new_strv(v)
+ if variant == None:
+ self.printerr('Unknown value type: %s' % type(v))
+ sys.abrt()
+ if self._config != None:
+ self._config.set_value(s, key, variant)
+ self.modified.setdefault(section, {})[key] = v
+ del(self.new[section][key])
+
+ def undo_all(self):
+ self.new.clear()
+
+ def undo_section(self, section):
+ try:
+ del(self.new[section])
+ except:
+ pass
+
+ def undo_item(self, section, key):
+ try:
+ del(self.new[section][key])
+ except:
+ pass
+
+ def set_default_all(self):
+ for s in self.sections():
+ self.set_default_section(s)
+
+ def set_default_section(self, section):
+ for k in self.keys(section):
+ self.set_default_item(section, k)
+
+ def set_default_item(self, section, key):
+ try:
+ if key in self.modified[section] or key in self.new[section]:
+ self.new[section][key] = self.default[section][key]
+ except:
+ pass
+
+ # Convert DBus.String to str
+ # sys.getdefaultencoding() == 'utf-8' with pygtk2 but
+ # sys.getdefaultencoding() == 'ascii' with gi gtk3
+ # so the simple str(unicode_string) causes an error and need to use
+ # unicode_string.encode('utf-8') instead.
+ def str(self, uni):
+ if uni == None:
+ return None
+ if type(uni) == str:
+ return uni
+ return str(uni)
+
+ # The simple unicode(string) causes an error and need to use
+ # unicode(string, 'utf-8') instead.
+ def unicode(self, string):
+ if string == None:
+ return None
+ return string
+
+ # If the parent process exited, the std io/out/error will be lost.
+ @staticmethod
+ def printerr(sentence):
+ try:
+ print(sentence, file=sys.stderr)
+ except IOError:
+ pass
+
diff --git a/setup/python3/setup.ui b/setup/python3/setup.ui
new file mode 100644
index 0000000..d9ec626
--- /dev/null
+++ b/setup/python3/setup.ui
@@ -0,0 +1,2813 @@
+<?xml version="1.0"?>
+<interface>
+ <object class="GtkAdjustment" id="adjustment1">
+ <property name="upper">10</property>
+ <property name="lower">0</property>
+ <property name="page_increment">0</property>
+ <property name="step_increment">1</property>
+ <property name="page_size">0</property>
+ <property name="value">10</property>
+ </object>
+ <object class="GtkListStore" id="model1">
+ <columns>
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">Hiragana</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Katakana</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Halfwidth Katakana</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Latin</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Wide Latin</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="model51">
+ <columns>
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">NICOLA-J</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">NICOLA-A</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">NICOLA-F</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="model11">
+ <columns>
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">None</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">FMV KB231 key extension</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">FMV KB611 key extension</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="model2">
+ <columns>
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">Romaji</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Kana</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Thumb shift</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="model3">
+ <columns>
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">Multiple segment</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Single segment</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Immediate conversion (multiple segment)</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Immediate conversion (single segment)</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="model4">
+ <columns>
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">Keep numpad codes</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Convert characters</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="model5">
+ <columns>
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0">&#x300C;&#x300D;&#xFF0F;</col>
+ </row>
+ <row>
+ <col id="0">&#x300C;&#x300D;&#x30FB;</col>
+ </row>
+ <row>
+ <col id="0">&#xFF3B;&#xFF3D;&#xFF0F;</col>
+ </row>
+ <row>
+ <col id="0">&#xFF3B;&#xFF3D;&#x30FB;</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="model6">
+ <columns>
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0">&#x3001;&#x3002;</col>
+ </row>
+ <row>
+ <col id="0">&#xFF0C;&#xFF0E;</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="model7">
+ <columns>
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">Do nothing</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Automatically convert</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="model8">
+ <columns>
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">Clear</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Commit</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Hold</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="model9">
+ <columns>
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">Default</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">ATOK</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Wnn</col>
+ </row>
+ </data>
+ </object>
+ <!-- interface-requires gtk+ 2.16 -->
+ <!-- interface-naming-policy toplevel-contextual -->
+ <object class="GtkDialog" id="main">
+ <property name="visible">False</property>
+ <property name="title" translatable="yes">Setup - IBus-Anthy</property>
+ <property name="type_hint">dialog</property>
+ <signal handler="on_main_delete" name="delete_event"/>
+ <child internal-child="vbox">
+ <object class="GtkVBox" id="dialog-vbox1">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkNotebook" id="notebook1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="border_width">6</property>
+ <child>
+ <object class="GtkVBox" id="vbox1">
+ <property name="visible">True</property>
+ <property name="border_width">8</property>
+ <child>
+ <object class="GtkFrame" id="frame11">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment" id="alignment11">
+ <property name="visible">True</property>
+ <property name="top_padding">8</property>
+ <property name="bottom_padding">8</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkTable" id="table11">
+ <property name="visible">True</property>
+ <property name="n_rows">3</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">8</property>
+ <property name="row_spacing">4</property>
+ <child>
+ <object class="GtkLabel" id="label101">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Input Mode:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">input_mode</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="input_mode">
+ <property name="visible">True</property>
+ <signal handler="on_cb_changed" name="changed"/>
+ <property name="model">model1</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer1"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label102">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Typing Method:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">typing_method</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="typing_method">
+ <property name="visible">True</property>
+ <signal handler="on_cb_changed" name="changed"/>
+ <property name="model">model2</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer2"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label103">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Conversion _Mode:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">conversion_segment_mode</property>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="conversion_segment_mode">
+ <property name="visible">True</property>
+ <signal handler="on_cb_changed" name="changed"/>
+ <property name="model">model3</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer3"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label151">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;Initial Setting&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame12">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment" id="alignment12">
+ <property name="visible">True</property>
+ <property name="top_padding">8</property>
+ <property name="bottom_padding">8</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkVBox" id="vbox12">
+ <property name="visible">True</property>
+ <property name="border_width">4</property>
+ <property name="spacing">4</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow12">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="height_request">200</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="menu_visible:treeview">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label152">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;Menu Visibility on Status Icon&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">General</property>
+ <property name="mnemonic_widget">vbox1</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox2">
+ <property name="visible">True</property>
+ <property name="border_width">8</property>
+ <child>
+ <object class="GtkFrame" id="frame21">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment" id="alignment21">
+ <property name="visible">True</property>
+ <property name="top_padding">8</property>
+ <property name="bottom_padding">8</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkTable" id="table21">
+ <property name="visible">True</property>
+ <property name="n_rows">5</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">8</property>
+ <property name="row_spacing">4</property>
+ <child>
+ <object class="GtkLabel" id="label104">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Period Style:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">period_style</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label105">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Symbo_l Style:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">symbol_style</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label106">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Numpad _Key Type:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">ten_key_mode</property>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="ten_key_mode">
+ <property name="visible">True</property>
+ <signal handler="on_cb_changed" name="changed"/>
+ <property name="model">model4</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer4"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="symbol_style">
+ <property name="visible">True</property>
+ <signal handler="on_cb_changed" name="changed"/>
+ <property name="model">model5</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer5"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="period_style">
+ <property name="visible">True</property>
+ <signal handler="on_cb_changed" name="changed"/>
+ <property name="model">model6</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer6"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label107">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Behavior on Period:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">behavior_on_period</property>
+ </object>
+ <packing>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label108">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Behavior on _Focus Out:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">behavior_on_focus_out</property>
+ </object>
+ <packing>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="behavior_on_period">
+ <property name="visible">True</property>
+ <signal handler="on_cb_changed" name="changed"/>
+ <property name="model">model7</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer7"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="behavior_on_focus_out">
+ <property name="visible">True</property>
+ <signal handler="on_cb_changed" name="changed"/>
+ <property name="model">model8</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer8"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label201">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;Behavior&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame22">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment" id="alignment22">
+ <property name="visible">True</property>
+ <property name="top_padding">8</property>
+ <property name="bottom_padding">8</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkTable" id="table22">
+ <property name="visible">True</property>
+ <property name="n_rows">4</property>
+ <property name="column_spacing">8</property>
+ <property name="row_spacing">4</property>
+ <child>
+ <object class="GtkHBox" id="hbox4">
+ <property name="visible">True</property>
+ <property name="spacing">8</property>
+ <child>
+ <object class="GtkLabel" id="label109">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Candidate _Window Page Size:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">page_size</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="page_size">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">adjustment1</property>
+ <property name="climb_rate">0.97999999999999998</property>
+ <signal handler="on_sb_changed" name="value_changed"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="half_width_symbol">
+ <property name="label" translatable="yes">Convert _symbols with the one column width</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <signal handler="on_ck_toggled" name="toggled"/>
+ <accelerator key="S" modifiers="GDK_MOD1_MASK" signal="grab_focus"/>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="half_width_number">
+ <property name="label" translatable="yes">Convert _numbers with the one column width</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <signal handler="on_ck_toggled" name="toggled"/>
+ <accelerator key="N" modifiers="GDK_MOD1_MASK" signal="grab_focus"/>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="half_width_space">
+ <property name="label" translatable="yes">Con_vert spaces with the one column width</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <signal handler="on_ck_toggled" name="toggled"/>
+ <accelerator key="v" modifiers="GDK_MOD1_MASK" signal="activate"/>
+ </object>
+ <packing>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="latin_with_shift">
+ <property name="label" translatable="yes">Swi_tch “Hiragana” and “Latin” with Shift key and Hiragana–Katakana key in preedit</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <signal handler="on_ck_toggled" name="toggled"/>
+ <accelerator key="t" modifiers="GDK_MOD1_MASK" signal="activate"/>
+ </object>
+ <packing>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label211">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;Other&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Conversion</property>
+ <property name="mnemonic_widget">vbox2</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox3">
+ <property name="visible">True</property>
+ <property name="border_width">4</property>
+ <property name="spacing">4</property>
+ <child>
+ <object class="GtkHBox" id="hbox1">
+ <property name="visible">True</property>
+ <property name="spacing">8</property>
+ <child>
+ <object class="GtkLabel" id="label21">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Shortcut Type:</property>
+ <property name="use_underline">True</property>
+ <property name="wrap_mode">word-char</property>
+ <property name="mnemonic_widget">shortcut_type</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="padding">1</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="shortcut_type">
+ <property name="visible">True</property>
+ <signal handler="on_shortcut_type_changed" name="changed"/>
+ <property name="model">model9</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer9"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow31">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="shortcut">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <signal handler="on_shortcut_click_event" name="button_press_event"/>
+ <signal handler="on_shortcut_click_event" name="button_release_event"/>
+ <signal handler="on_shortcut_key_release_event" name="key_release_event"/>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHButtonBox" id="hbuttonbox31">
+ <property name="visible">True</property>
+ <property name="spacing">4</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="btn_default">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <signal handler="on_btn_default_clicked" name="clicked"/>
+ <child>
+ <object class="GtkAlignment" id="alignment31">
+ <property name="visible">True</property>
+ <property name="xscale">0</property>
+ <property name="yscale">0</property>
+ <child>
+ <object class="GtkHBox" id="hbox5">
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ <child>
+ <object class="GtkImage" id="image1">
+ <property name="visible">True</property>
+ <property name="stock">gtk-undo</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label27">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">De_fault</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="btn_edit">
+ <property name="label">gtk-edit</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_stock">True</property>
+ <signal handler="on_btn_edit_clicked" name="clicked"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Key Binding</property>
+ <property name="mnemonic_widget">vbox3</property>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="vbox4">
+ <property name="visible">True</property>
+ <property name="border_width">8</property>
+ <property name="spacing">4</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkFrame" id="frame41">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment" id="alignment41">
+ <property name="visible">True</property>
+ <property name="top_padding">0</property>
+ <property name="bottom_padding">8</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkBox" id="vbox41">
+ <property name="visible">True</property>
+ <property name="border_width">4</property>
+ <property name="spacing">4</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkTable" id="table41">
+ <property name="visible">True</property>
+ <property name="n_rows">2</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">8</property>
+ <property name="row_spacing">4</property>
+ <child>
+ <object class="GtkLabel" id="label402">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Romaji Key Table:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">romaji:button_custom_table</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <!-- The fill need to be True so that
+ GtkTable do not have extra space
+ in y axis. -->
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="romaji:button_custom_table">
+ <property name="label">...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <signal handler="on_btn_romaji_custom_table_clicked" name="clicked"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label401">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;Romaji&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <!-- The fill need to be True so that
+ GtkTable do not have extra space
+ in y axis. -->
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame42">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment" id="alignment42">
+ <property name="visible">True</property>
+ <property name="top_padding">0</property>
+ <property name="bottom_padding">8</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkBox" id="vbox42">
+ <property name="visible">True</property>
+ <property name="border_width">4</property>
+ <property name="spacing">4</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkTable" id="table42">
+ <property name="visible">True</property>
+ <property name="n_rows">2</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">8</property>
+ <property name="row_spacing">4</property>
+ <child>
+ <object class="GtkLabel" id="label412">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Kana Key Table:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">kana:button_custom_table</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <!-- The fill need to be True so that
+ GtkTable do not have extra space
+ in y axis. -->
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="kana:button_custom_table">
+ <property name="label">...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <signal handler="on_btn_kana_custom_table_clicked" name="clicked"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label411">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;Kana&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <!-- The fill need to be True so that
+ GtkTable do not have extra space
+ in y axis. -->
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame43">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment" id="alignment43">
+ <property name="visible">True</property>
+ <property name="top_padding">0</property>
+ <property name="bottom_padding">8</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkBox" id="vbox43">
+ <property name="visible">True</property>
+ <property name="border_width">4</property>
+ <property name="spacing">4</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkTable" id="table43">
+ <property name="visible">True</property>
+ <property name="n_rows">2</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">8</property>
+ <property name="row_spacing">4</property>
+ <child>
+ <object class="GtkLabel" id="label422">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Keyboad _layout:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">keymap:combobox_custom_table</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <!-- The fill need to be True so that
+ GtkTable do not have extra space
+ in y axis. -->
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="keymap:combobox_custom_table">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer330"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label421">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;Keyboard layout&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <!-- The fill need to be True so that
+ GtkTable do not have extra space
+ in y axis. -->
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Typing Method</property>
+ <property name="mnemonic_widget">vbox4</property>
+ </object>
+ <packing>
+ <property name="position">3</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="vbox5">
+ <property name="visible">True</property>
+ <property name="border_width">8</property>
+ <property name="spacing">4</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkFrame" id="frame51">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment" id="alignment5">
+ <property name="visible">True</property>
+ <property name="top_padding">8</property>
+ <property name="bottom_padding">8</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkBox" id="vbox51">
+ <property name="visible">True</property>
+ <property name="border_width">4</property>
+ <property name="spacing">4</property>
+ <property name="orientation">vertical</property>
+ <child>
+
+ <object class="GtkTable" id="table51">
+ <property name="visible">True</property>
+ <property name="n_rows">2</property>
+ <property name="n_columns">3</property>
+ <property name="column_spacing">8</property>
+ <property name="row_spacing">4</property>
+ <child>
+ <object class="GtkLabel" id="label28">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="use_underline">True</property>
+ <property name="label" translatable="yes">_Left Thumb Shift Key:</property>
+ <property name="mnemonic_widget">thumb:ls</property>
+ </object>
+ <packing>
+ <!-- The fill need to be True so that
+ GtkTable do not have extra space
+ in y axis. -->
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="thumb:ls">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">False</property>
+ </object>
+ <packing>
+ <property name="y_options">GTK_FILL</property>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="thumb:button_ls">
+ <property name="label">...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <signal handler="on_btn_thumb_key_clicked" name="clicked"/>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label29">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="use_underline">True</property>
+ <property name="label" translatable="yes">Right _Thumb Shift Key:</property>
+ <property name="mnemonic_widget">thumb:rs</property>
+ </object>
+ <packing>
+ <property name="y_options">GTK_FILL</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="thumb:rs">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">False</property>
+ </object>
+ <packing>
+ <property name="y_options">GTK_FILL</property>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="thumb:button_rs">
+ <property name="label">...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <signal handler="on_btn_thumb_key_clicked" name="clicked"/>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <!-- The fill need to be True so that
+ GtkTable do not have extra space
+ in y axis. -->
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="thumb:keyboard_layout_mode">
+ <property name="label" translatable="yes">Adjust _input method layout to system keyboard layout</property>
+ <property name="tooltip_text" translatable="yes">Adjust IM layout to XKB layout</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <signal handler="on_ck_toggled" name="toggled"/>
+ <accelerator key="I" modifiers="GDK_MOD1_MASK" signal="grab_focus"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox51">
+ <property name="visible">True</property>
+ <property name="spacing">8</property>
+ <child>
+ <object class="GtkLabel" id="label30">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="use_underline">True</property>
+ <property name="label" translatable="yes">Input _Method Layout:</property>
+ <property name="mnemonic_widget">thumb:keyboard_layout</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="thumb:keyboard_layout">
+ <property name="visible">True</property>
+ <signal handler="on_cb_changed" name="changed"/>
+ <property name="model">model51</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer10"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox52">
+ <property name="visible">True</property>
+ <property name="spacing">8</property>
+ <child>
+ <object class="GtkImage" id="image2">
+ <property name="visible">True</property>
+ <property name="stock">gtk-dialog-info</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label31">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="wrap">True</property>
+ <property name="label" translatable="yes">Restart IBus when you change the keyboard layout</property>
+ <property name="tooltip_text" translatable="yes">Restart IBus when you change XKB</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox11">
+ <property name="visible">True</property>
+ <property name="spacing">8</property>
+ <child>
+ <object class="GtkLabel" id="label33">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="use_underline">True</property>
+ <property name="label" translatable="yes">_Additional Key Arrangement:</property>
+ <property name="mnemonic_widget">thumb:fmv_extension</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="thumb:fmv_extension">
+ <property name="visible">True</property>
+ <property name="tooltip_text" translatable="yes">'&#xFF5E;', '&#x300E;', '&#xA2;', '&#xA3;' and so on can be output with Thumb Shift key</property>
+ <signal handler="on_cb_changed" name="changed"/>
+ <property name="model">model11</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer11"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox53">
+ <property name="visible">True</property>
+ <property name="spacing">8</property>
+ <child>
+ <object class="GtkImage" id="image4">
+ <property name="visible">True</property>
+ <property name="stock">gtk-dialog-info</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label34">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="wrap">True</property>
+ <property name="label" translatable="yes">You do not have to reconfigure the system keyboard layout for "Additional Key Arrangement" since this option changes input method layout only in case input method is turned on.</property>
+ <property name="tooltip_text" translatable="yes">You do not have to reconfigure XKB since this option changes IM layout only with IM on.</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="thumb:handakuten">
+ <property name="label" translatable="yes">_Enable semi-voiced sound mark with Shift key</property>
+ <property name="tooltip_text" translatable="yes">Seion + Shift can output Handakuon</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <signal handler="on_ck_toggled" name="toggled"/>
+ <accelerator key="E" modifiers="GDK_MOD1_MASK" signal="grab_focus"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">6</property>
+ </packing>
+
+ </child>
+ <child>
+ <object class="GtkTable" id="table52">
+ <property name="visible">True</property>
+ <property name="n_rows">2</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">8</property>
+ <property name="row_spacing">4</property>
+ <child>
+ <object class="GtkLabel" id="label35">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Thumb _Shift Key Table:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">thumb:button_custom_table</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <!-- The fill need to be True so that
+ GtkTable do not have extra space
+ in y axis. -->
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="thumb:button_custom_table">
+ <property name="label">...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <signal handler="on_btn_thumb_custom_table_clicked" name="clicked"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <!-- The fill need to be True so that
+ GtkTable do not have extra space
+ in y axis. -->
+ <property name="fill">True</property>
+ <property name="position">7</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label36">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;Thumb Shift Layout&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Thumb Shift</property>
+ <property name="mnemonic_widget">vbox5</property>
+ </object>
+ <packing>
+ <property name="position">4</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox6">
+ <property name="visible">True</property>
+ <property name="border_width">8</property>
+ <property name="spacing">4</property>
+ <child>
+ <object class="GtkFrame" id="frame61">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment" id="alignment61">
+ <property name="visible">True</property>
+ <property name="top_padding">4</property>
+ <property name="left_padding">0</property>
+ <child>
+ <object class="GtkVBox" id="vbox61">
+ <property name="visible">True</property>
+ <property name="border_width">4</property>
+ <property name="spacing">4</property>
+ <child>
+ <object class="GtkTable" id="table61">
+ <property name="visible">True</property>
+ <property name="n_rows">2</property>
+ <property name="n_columns">3</property>
+ <property name="column_spacing">8</property>
+ <property name="row_spacing">4</property>
+ <child>
+ <object class="GtkLabel" id="label601">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Edit Dictionary Command:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">dict:entry_edit_dict_command</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <!-- The fill need to be True so that
+ GtkTable do not have extra space
+ in y axis. -->
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="dict:entry_edit_dict_command">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <signal handler="on_entry_dict_command_changed" name="changed"/>
+ </object>
+ <packing>
+ <!-- The fill need to be True so that
+ GtkTable do not have extra space
+ in y axis. -->
+ <property name="y_options">GTK_FILL</property>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="dict:btn_edit_dict_command">
+ <property name="label">...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <signal handler="on_btn_dict_command_clicked" name="clicked"/>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <!-- The fill need to be True so that
+ GtkTable do not have extra space
+ in y axis. -->
+ <property name="y_options">GTK_FILL</property>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label602">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Add Word Command:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">dict:entry_add_word_command</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <!-- The fill need to be True so that
+ GtkTable do not have extra space
+ in y axis. -->
+ <property name="y_options">GTK_FILL</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="dict:entry_add_word_command">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <signal handler="on_entry_dict_command_changed" name="changed"/>
+ </object>
+ <packing>
+ <!-- The fill need to be True so that
+ GtkTable do not have extra space
+ in y axis. -->
+ <property name="y_options">GTK_FILL</property>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="dict:btn_add_word_command">
+ <property name="label">...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <signal handler="on_btn_dict_command_clicked" name="clicked"/>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <!-- The fill need to be True so that
+ GtkTable do not have extra space
+ in y axis. -->
+ <property name="y_options">GTK_FILL</property>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <!-- The fill need to be True so that
+ GtkTable do not have extra space
+ in y axis. -->
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label60">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;Default Dictionary Configuration&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame71">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment" id="alignment71">
+ <property name="visible">True</property>
+ <property name="top_padding">4</property>
+ <property name="left_padding">0</property>
+ <child>
+ <object class="GtkVBox" id="vbox71">
+ <property name="visible">True</property>
+ <property name="border_width">4</property>
+ <property name="spacing">4</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow71">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="height_request">220</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="dict:view">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHButtonBox" id="hbuttonbox71">
+ <property name="visible">True</property>
+ <property name="spacing">4</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="dict:btn_view">
+ <property name="label" translatable="yes">_View</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <signal handler="on_btn_dict_view_clicked" name="clicked"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="dict:btn_add">
+ <property name="label">gtk-add</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_stock">True</property>
+ <signal handler="on_btn_dict_add_clicked" name="clicked"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="dict:btn_edit">
+ <property name="label">gtk-edit</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_stock">True</property>
+ <signal handler="on_btn_dict_add_clicked" name="clicked"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="dict:btn_delete">
+ <property name="label">gtk-delete</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_stock">True</property>
+ <signal handler="on_btn_dict_delete_clicked" name="clicked"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHButtonBox" id="hbuttonbox72">
+ <property name="visible">True</property>
+ <property name="spacing">4</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="dict:btn_up">
+ <property name="label">gtk-go-up</property>
+ <property name="tooltip_text" translatable="yes">You can change the order on language bar</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_stock">True</property>
+ <signal handler="on_btn_dict_order_clicked" name="clicked"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="dict:btn_down">
+ <property name="label">gtk-go-down</property>
+ <property name="tooltip_text" translatable="yes">You can change the order on language bar</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_stock">True</property>
+ <signal handler="on_btn_dict_order_clicked" name="clicked"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label71">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;Extended Dictionaries&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Dictionary</property>
+ <property name="mnemonic_widget">vbox6</property>
+ </object>
+ <packing>
+ <property name="position">5</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="about_vbox">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="border_width">10</property>
+ <property name="spacing">6</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label7">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">About</property>
+ <property name="mnemonic_widget">about_vbox</property>
+ </object>
+ <packing>
+ <property name="position">6</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child internal-child="action_area">
+ <object class="GtkHButtonBox" id="dialog-action_area1">
+ <property name="visible">True</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="btn_apply">
+ <property name="label">gtk-apply</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_stock">True</property>
+ <signal handler="on_btn_apply_clicked" name="clicked"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="btn_cancel">
+ <property name="label">gtk-cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_stock">True</property>
+ <signal handler="on_btn_cancel_clicked" name="clicked"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="btn_ok">
+ <property name="label">gtk-ok</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_stock">True</property>
+ <signal handler="on_btn_ok_clicked" name="clicked"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-10">btn_apply</action-widget>
+ <action-widget response="-6">btn_cancel</action-widget>
+ <action-widget response="-5">btn_ok</action-widget>
+ </action-widgets>
+ </object>
+ <object class="GtkDialog" id="edit_shortcut">
+ <property name="width_request">340</property>
+ <property name="height_request">300</property>
+ <property name="title" translatable="yes">Edit Shortcut</property>
+ <property name="modal">True</property>
+ <property name="type_hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkVBox" id="dialog-vbox2">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkVBox" id="vbox101">
+ <property name="visible">True</property>
+ <property name="border_width">5</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow101">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="border_width">1</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="es:treeview">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="headers_visible">False</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox101">
+ <property name="visible">True</property>
+ <property name="spacing">8</property>
+ <child>
+ <object class="GtkLabel" id="label1001">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Key Code:</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="es:entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <signal handler="on_es_entry_changed" name="changed"/>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="es:button_run_input">
+ <property name="label">...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <signal handler="on_es_button_run_input_clicked" name="clicked"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox102">
+ <property name="visible">True</property>
+ <property name="spacing">8</property>
+ <child>
+ <object class="GtkLabel" id="label1002">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Modifier:</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox103">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkCheckButton" id="es:checkbutton_alt">
+ <property name="label" translatable="yes">A_lternate</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="es:checkbutton_ctrl">
+ <property name="label" translatable="yes">Co_ntrol</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="es:checkbutton_shift">
+ <property name="label" translatable="yes">_Shift</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHButtonBox" id="hbuttonbox101">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="es:button_add">
+ <property name="label">gtk-add</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_stock">True</property>
+ <signal handler="on_es_button_add_clicked" name="clicked"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="es:button_refresh">
+ <property name="label">gtk-refresh</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_stock">True</property>
+ <signal handler="on_es_button_refresh_clicked" name="clicked"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="es:button_del">
+ <property name="label">gtk-delete</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_stock">True</property>
+ <signal handler="on_es_button_del_clicked" name="clicked"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child internal-child="action_area">
+ <object class="GtkHButtonBox" id="dialog-action_area2">
+ <property name="visible">True</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="cancelbutton101">
+ <property name="label">gtk-cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="okbutton101">
+ <property name="label">gtk-ok</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-6">cancelbutton101</action-widget>
+ <action-widget response="-5">okbutton101</action-widget>
+ </action-widgets>
+ </object>
+ <object class="GtkDialog" id="dialog_custom_key_table">
+ <property name="width_request">400</property>
+ <property name="height_request">470</property>
+ <property name="title"/>
+ <property name="modal">True</property>
+ <property name="type_hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkVBox" id="dialog-vbox3">
+ <property name="visible">True</property>
+ <property name="border_width">5</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkHBox" id="hbox_for_combobox_custom_key_table">
+ <property name="visible">True</property>
+ <property name="border_width">5</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label_custom_key_table">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label"/>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">combobox_custom_key_table</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="combobox_custom_key_table">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox301">
+ <property name="visible">True</property>
+ <property name="border_width">5</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow301">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="border_width">1</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="treeview_custom_key_table">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVButtonBox" id="vbutton301">
+ <property name="visible">True</property>
+ <property name="layout_style">start</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label3001">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Input Characters</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">entry_input_custom_key</property>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="entry_input_custom_key">
+ <property name="visible">True</property>
+ <property name="width-chars">3</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_output_custom_key">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Output Characters</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">entry_output_custom_key</property>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="entry_output_custom_key">
+ <property name="visible">True</property>
+ <property name="width-chars">3</property>
+ </object>
+ <packing>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_left_thumb_shift_custom_key">
+ <property name="visible">False</property>
+ <property name="label" translatable="yes">_Left Thumb Shift</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">entry_left_thumb_shift_custom_key</property>
+ </object>
+ <packing>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="entry_left_thumb_shift_custom_key">
+ <property name="visible">False</property>
+ <property name="width-chars">3</property>
+ </object>
+ <packing>
+ <property name="position">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_right_thumb_shift_custom_key">
+ <property name="visible">False</property>
+ <property name="label" translatable="yes">_Right Thumb Shift</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">entry_right_thumb_shift_custom_key</property>
+ </object>
+ <packing>
+ <property name="position">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="entry_right_thumb_shift_custom_key">
+ <property name="visible">False</property>
+ <property name="width-chars">3</property>
+ </object>
+ <packing>
+ <property name="position">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="button_add_custom_key">
+ <property name="visible">True</property>
+ <property name="label">gtk-add</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="position">8</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="button_remove_custom_key">
+ <property name="visible">True</property>
+ <property name="label">gtk-remove</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="position">9</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child internal-child="action_area">
+ <object class="GtkHButtonBox" id="dialog-action_area3">
+ <property name="visible">True</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="closebutton301">
+ <property name="visible">True</property>
+ <property name="label">gtk-close</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="use_stock">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="0">closebutton301</action-widget>
+ </action-widgets>
+ </object>
+ <object class="GtkMessageDialog" id="quit_check">
+ <property name="border_width">5</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="window_position">center-on-parent</property>
+ <property name="type_hint">dialog</property>
+ <property name="skip_taskbar_hint">True</property>
+ <property name="message_type">question</property>
+ <property name="buttons">yes-no</property>
+ <property name="text">Confirmation</property>
+ <property name="secondary_text">You are about to close the setup dialog, is that OK?</property>
+ <child internal-child="vbox">
+ <object class="GtkVBox" id="dialog-vbox6">
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ <child internal-child="action_area">
+ <object class="GtkHButtonBox" id="dialog-action_area6">
+ <property name="visible">True</property>
+ <property name="layout_style">end</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <object class="GtkMessageDialog" id="quit_check_without_save">
+ <property name="border_width">5</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="window_position">center-on-parent</property>
+ <property name="type_hint">dialog</property>
+ <property name="skip_taskbar_hint">True</property>
+ <property name="message_type">warning</property>
+ <property name="buttons">yes-no</property>
+ <property name="text">Notice!</property>
+ <property name="secondary_text">You are about to close the setup dialog without saving your changes, is that OK?</property>
+ <child internal-child="vbox">
+ <object class="GtkVBox" id="dialog-vbox7">
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ <child internal-child="action_area">
+ <object class="GtkHButtonBox" id="dialog-action_area7">
+ <property name="visible">True</property>
+ <property name="layout_style">end</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <object class="GtkMessageDialog" id="key_input_dialog">
+ <property name="border_width">5</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="window_position">center-on-parent</property>
+ <property name="type_hint">dialog</property>
+ <property name="skip_taskbar_hint">True</property>
+ <property name="buttons">cancel</property>
+ <property name="text">Please press a key (or a key combination)</property>
+ <property name="secondary_text">The dialog will be closed when the key is released</property>
+ <signal handler="on_key_input_dialog_key_press_event" name="key_press_event"/>
+ <signal handler="on_key_input_dialog_key_release_event" name="key_release_event"/>
+ <child internal-child="vbox">
+ <object class="GtkVBox" id="dialog-vbox8">
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ <child internal-child="action_area">
+ <object class="GtkHButtonBox" id="dialog-action_area8">
+ <property name="visible">True</property>
+ <property name="layout_style">end</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <object class="GtkMessageDialog" id="invalid_keysym">
+ <property name="border_width">5</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="window_position">center-on-parent</property>
+ <property name="type_hint">dialog</property>
+ <property name="skip_taskbar_hint">True</property>
+ <property name="message_type">warning</property>
+ <property name="buttons">ok</property>
+ <property name="text">Invalid keysym</property>
+ <property name="secondary_text">This keysym is not valid</property>
+ <child internal-child="vbox">
+ <object class="GtkVBox" id="dialog-vbox9">
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ <child internal-child="action_area">
+ <object class="GtkHButtonBox" id="dialog-action_area9">
+ <property name="visible">True</property>
+ <property name="layout_style">end</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <object class="GtkVBox" id="dict:add_extra_vbox">
+ <property name="visible">True</property>
+ <property name="no_show_all">True</property>
+ <property name="spacing">10</property>
+ <child>
+ <object class="GtkTable" id="table1000">
+ <property name="visible">True</property>
+ <property name="n_rows">2</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">8</property>
+ <property name="row_spacing">4</property>
+ <child>
+ <object class="GtkLabel" id="label10001">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Short Label:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">dict:short_entry</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="dict:short_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="max-length">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label10002">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Description:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">dict:long_entry</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"/>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="dict:long_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="dict:single">
+ <property name="label" translatable="yes">_Use your dictionary alone with switching dictionaries</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="active">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="dict:embed">
+ <property name="label" translatable="yes">_Embed your dictionary in the system dictionary</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <!-- Unfortunatelly reverse conversion is too slow. -->
+ <object class="GtkCheckButton" id="dict:reverse">
+ <property name="label" translatable="yes">Enable the _reverse conversion</property>
+ <property name="visible">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <object class="GtkAboutDialog" id="about_dialog">
+ <property name="program-name">IBus-Anthy</property>
+ <property name="copyright">Copyright © 2007–2008 Peng Huang
+Copyright © 2009 Hideaki ABE
+Copyright © 2009–2013 Takao Fujiwara
+Copyright © 2007–2013 Red Hat, Inc.</property>
+ <property name="comments" translatable="yes">The Anthy engine for the IBus input platform</property>
+ <property name="license">GPL</property>
+ <property name="website">http://code.google.com/p/ibus/</property>
+ <property name="authors">Takao Fujiwara &lt;takao.fujiwara1@gmail.com&gt;</property>
+ <property name="translator-credits" translatable="yes">translator_credits</property>
+ <property name="logo-icon-name"/>
+ <property name="wrap-license">True</property>
+ </object>
+</interface>