diff --git a/engine/engine.py b/engine/engine.py index c5841cb..56e5b28 100644 --- a/engine/engine.py +++ b/engine/engine.py @@ -22,6 +22,7 @@ import os from os import path +from locale import getpreferredencoding import sys import gobject import ibus @@ -96,6 +97,7 @@ class Engine(ibus.EngineBase): __setup_pid = 0 __prefs = None __keybind = {} + __thumb = None def __init__(self, bus, object_path): super(Engine, self).__init__(bus, object_path) @@ -105,8 +107,10 @@ class Engine(ibus.EngineBase): self.__context._set_encoding(anthy.ANTHY_UTF8_ENCODING) # init state + self.__idle_id = 0 self.__input_mode = INPUT_MODE_HIRAGANA self.__prop_dict = {} + self.__is_utf8 = (getpreferredencoding().lower() == "utf-8") # self.__lookup_table = ibus.LookupTable(page_size=9, round=True) size = self.__prefs.get_value('common', 'page_size') @@ -130,7 +134,6 @@ class Engine(ibus.EngineBase): self.__preedit_ja_string = jastring.JaString(Engine.__typing_mode) self.__convert_chars = u"" self.__cursor_pos = 0 - self.__need_update = False self.__convert_mode = CONV_MODE_OFF self.__segments = list() self.__lookup_table.clean() @@ -138,6 +141,11 @@ class Engine(ibus.EngineBase): self._MM = 0 self._SS = 0 self._H = 0 + self._RMM = 0 + self._RSS = 0 + if self.__idle_id != 0: + gobject.source_remove(self.__idle_id) + self.__idle_id = 0 def __init_props(self): anthy_props = ibus.PropList() @@ -485,6 +493,8 @@ class Engine(ibus.EngineBase): return True self.__prop_dict[prop_name].set_state(state) self.update_property(self.__prop_dict[prop_name]) + if prop_name == u"TypingMode.ThumbShift": + self._reset_thumb() mode, label = typing_modes[prop_name] @@ -526,6 +536,12 @@ class Engine(ibus.EngineBase): elif mode == 1: self.__on_key_return() + def do_destroy(self): + if self.__idle_id != 0: + gobject.source_remove(self.__idle_id) + self.__idle_id = 0 + super(Engine,self).do_destroy() + # begine convert def __begin_anthy_convert(self): if self.__convert_mode == CONV_MODE_ANTHY: @@ -562,6 +578,15 @@ class Engine(ibus.EngineBase): def __end_convert(self): self.__end_anthy_convert() + def __candidate_cb(self, candidate): + if not self.__is_utf8: + return + for key in 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(candidate)) + def __fill_lookup_table(self): if self.__convert_mode == CONV_MODE_PREDICTION: seg_stat = anthy.anthy_prediction_stat() @@ -573,7 +598,7 @@ class Engine(ibus.EngineBase): buf = self.__context.get_prediction(i) candidate = unicode(buf, "utf-8") self.__lookup_table.append_candidate(ibus.Text(candidate)) - + self.__candidate_cb(candidate) return # get segment stat @@ -586,13 +611,14 @@ class Engine(ibus.EngineBase): buf = self.__context.get_segment(self.__cursor_pos, i) candidate = unicode(buf, "utf-8") self.__lookup_table.append_candidate(ibus.Text(candidate)) + self.__candidate_cb(candidate) def __invalidate(self): - if self.__need_update: + if self.__idle_id != 0: return - self.__need_update = True - gobject.idle_add(self.__update, priority = gobject.PRIORITY_LOW) + self.__idle_id = gobject.idle_add(self.__update, + priority = gobject.PRIORITY_LOW) # def __get_preedit(self): def __get_preedit(self, commit=False): @@ -699,11 +725,11 @@ class Engine(ibus.EngineBase): self.__lookup_table_visible) def __update(self): - self.__need_update = False 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(): @@ -956,7 +982,7 @@ class Engine(ibus.EngineBase): self.__invalidate() return True - def __on_key_common(self, keyval): + def __on_key_common(self, keyval, state=0): if self.__input_mode == INPUT_MODE_LATIN: # Input Latin chars @@ -981,6 +1007,13 @@ class Engine(ibus.EngineBase): 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 & modifier.SHIFT_MASK) != 0 + else: + shift = False + self.__preedit_ja_string.set_shift(shift) self.__preedit_ja_string.insert(unichr(keyval)) self.__invalidate() return True @@ -1024,6 +1057,9 @@ class Engine(ibus.EngineBase): cls.__prefs.set_value(base_sec, name, value) if name == 'shortcut_type': cls.__keybind = cls._mk_keybind() + elif base_sec == 'thumb': + cls.__prefs.set_value(base_sec, name, value) + cls._reset_thumb() elif base_sec: cls.__prefs.set_value(base_sec, name, value) else: @@ -1056,6 +1092,15 @@ class Engine(ibus.EngineBase): 'alt+' in s and modifier.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 & (modifier.CONTROL_MASK | modifier.MOD1_MASK): @@ -1067,12 +1112,12 @@ class Engine(ibus.EngineBase): return repr([int(state), int(keyval)]) def process_key_event_thumb(self, keyval, keycode, state): - import gtk - import thumb + if self.__thumb == None: + self._reset_thumb() def on_timeout(keyval): if self._MM: - insert(thumb.table[self._MM][self._SS]) + insert(self.__thumb.get_char(self._MM)[self._SS]) else: cmd_exec([0, RS(), LS()][self._SS]) self._H = None @@ -1089,6 +1134,7 @@ class Engine(ibus.EngineBase): def insert(keyval): try: + self._MM = self._SS = 0 ret = self.__on_key_common(ord(keyval)) if (keyval in u',.、。' and self.__prefs.get_value('common', 'behavior_on_period')): @@ -1109,16 +1155,16 @@ class Engine(ibus.EngineBase): return False def RS(): - return self.__prefs.get_value('common', 'thumb_rs') + return self.__thumb.get_rs() def LS(): - return self.__prefs.get_value('common', 'thumb_ls') + return self.__thumb.get_ls() def T1(): - return self.__prefs.get_value('common', 'thumb_t1') + return self.__thumb.get_t1() def T2(): - return self.__prefs.get_value('common', 'thumb_t2') + return self.__thumb.get_t2() state = state & (modifier.SHIFT_MASK | modifier.CONTROL_MASK | @@ -1132,12 +1178,16 @@ class Engine(ibus.EngineBase): if state & modifier.RELEASE_MASK: if keyval == self._MM: if stop(): - insert(thumb.table[self._MM][self._SS]) + 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: @@ -1147,35 +1197,50 @@ class Engine(ibus.EngineBase): start(T1()) elif self._MM: stop() - insert(thumb.table[self._MM][1 if keyval == RS() else 2]) + 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: - self._SS = 1 if keyval == RS() else 2 - start(T1()) - elif keyval in thumb.table.keys() and state == 0: + 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(thumb.table[self._MM][self._SS]) + insert(self.__thumb.get_char(self._MM)[self._SS]) start(T2()) self._MM = keyval elif self._SS: stop() - insert(thumb.table[keyval][self._SS]) + self._RMM = keyval + self._RSS = self._SS + insert(self.__thumb.get_char(keyval)[self._SS]) else: - if cmd_exec(keyval, state): - return True - start(T2()) - self._MM = keyval + 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(thumb.table[self._MM][self._SS]) + 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 & (modifier.CONTROL_MASK | modifier.MOD1_MASK) == 0: - insert(thumb.shift_table.get(keyval, unichr(keyval))) + if state & modifier.SHIFT_MASK: + insert(self.__thumb.get_shift_char(keyval, unichr(keyval))) + elif self._SS == 0: + insert(unichr(keyval)) else: if not self.__preedit_ja_string.is_empty(): return True @@ -1220,7 +1285,7 @@ class Engine(ibus.EngineBase): keyval = keysyms.asciitilde elif keyval == keysyms.backslash and keycode in [132-8, 133-8]: keyval = keysyms.yen - ret = self.__on_key_common(keyval) + ret = self.__on_key_common(keyval, state) if (unichr(keyval) in u',.' and self.__prefs.get_value('common', 'behavior_on_period')): return self.__cmd_convert(keyval, state) diff --git a/engine/jastring.py b/engine/jastring.py index 306691e..7aa2ff2 100644 --- a/engine/jastring.py +++ b/engine/jastring.py @@ -55,11 +55,15 @@ class JaString: def reset(self): self.__cursor = 0 self.__segments = list() + self.__shift = False def set_mode(self, mode): self.__mode = mode self.reset() + def set_shift(self, shift): + self.__shift = shift + def insert(self, c): segment_before = None segment_after = None @@ -70,14 +74,21 @@ class JaString: if self.__cursor < len(self.__segments): segment_after = self.__segments[self.__cursor] if segment_before and not segment_before.is_finished(): - new_segments = segment_before.append(c) + if type(segment_before) == romaji.RomajiSegment: + new_segments = segment_before.append(c, self.__shift) + else: + new_segments = segment_before.append(c) elif segment_after and not segment_after.is_finished(): - new_segments = segment_after.prepend(c) + if type(segment_after) == romaji.RomajiSegment: + new_segments = segment_after.prepend(c, self.__shift) + else: + new_segments = segment_after.prepend(c) else: if c != u"\0" and c != u"": if self.__mode == TYPING_MODE_ROMAJI: - new_segments = [romaji.RomajiSegment(c)] + new_segments = [romaji.RomajiSegment(c, u"", self.__shift)] 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)] @@ -126,7 +137,9 @@ class JaString: ret = '' for c in s: c = c if not period else PeriodTable.get(c, c) - c = c if not symbol else SymbolTable[symbol].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 diff --git a/engine/romaji.py b/engine/romaji.py index 12c6656..3deb8f9 100644 --- a/engine/romaji.py +++ b/engine/romaji.py @@ -28,8 +28,8 @@ def romaji_correction_rule_get(k, d): return (u'ん', k[1:2]) if k[0:1] == u'n' and not k[1:2] in u"aiueony'" else d class RomajiSegment(segment.Segment): - def __init__(self, enchars=u"", jachars=u""): - if not jachars: + def __init__(self, enchars=u"", jachars=u"", shift=False): + if not jachars and not shift: jachars = romaji_typing_rule.get(enchars, None) if jachars == None: jachars = symbol_rule.get(enchars, u"") @@ -38,13 +38,16 @@ class RomajiSegment(segment.Segment): def is_finished(self): return self._jachars != u"" - def append(self, enchar): + def append(self, enchar, shift=False): if self.is_finished(): if enchar == u"" and enchar == u"\0": return [] return [RomajiSegment(enchar)] text = self._enchars + enchar + if shift: + self._enchars = text + return [] jachars = romaji_typing_rule.get(text, None) if jachars == None: @@ -98,7 +101,7 @@ class RomajiSegment(segment.Segment): self._enchars = text return [] - def prepend(self, enchar): + def prepend(self, enchar, shift=False): if enchar == u"" or enchar == u"\0": return [] @@ -106,6 +109,10 @@ class RomajiSegment(segment.Segment): return [RomajiSegment(enchar)] text = enchar + self._enchars + if shift: + self._enchars = text + return [] + jachars = romaji_typing_rule.get(text, None) if jachars == None: jachars = symbol_rule.get(text, None) diff --git a/engine/tables.py b/engine/tables.py index 2ea67e0..a86a26a 100644 --- a/engine/tables.py +++ b/engine/tables.py @@ -38,12 +38,6 @@ romaji_typing_rule = { u"lu" : u"ぅ", u"le" : u"ぇ", u"lo" : u"ぉ", -# u"xka" : u"ゕ", - u"xka" : u"ヵ", -# u"xke" : u"ゖ", - u"xke" : u"ヶ", - u"wi" : u"うぃ", - u"we" : u"うぇ", u"wha" : u"うぁ", u"whi" : u"うぃ", u"whe" : u"うぇ", @@ -58,6 +52,12 @@ romaji_typing_rule = { u"ku" : u"く", u"ke" : u"け", u"ko" : u"こ", + u"lka" : u"ヵ", + u"lke" : u"ヶ", +# u"xka" : u"ゕ", + u"xka" : u"ヵ", +# u"xke" : u"ゖ", + u"xke" : u"ヶ", u"ga" : u"が", u"gi" : u"ぎ", u"gu" : u"ぐ", @@ -68,11 +68,13 @@ romaji_typing_rule = { u"kyu" : u"きゅ", u"kye" : u"きぇ", u"kyo" : u"きょ", + u"kwa" : u"くぁ", u"gya" : u"ぎゃ", u"gyi" : u"ぎぃ", u"gyu" : u"ぎゅ", u"gye" : u"ぎぇ", u"gyo" : u"ぎょ", + u"gwa" : u"ぐぁ", u"sa" : u"さ", u"si" : u"し", u"su" : u"す", @@ -128,6 +130,11 @@ romaji_typing_rule = { u"tyu" : u"ちゅ", u"tye" : u"ちぇ", u"tyo" : u"ちょ", + u"cya" : u"ちゃ", + u"cyi" : u"ちぃ", + u"cyu" : u"ちゅ", + u"cye" : u"ちぇ", + u"cyo" : u"ちょ", u"cha" : u"ちゃ", u"chi" : u"ち", u"chu" : u"ちゅ", @@ -139,6 +146,7 @@ romaji_typing_rule = { u"dye" : u"ぢぇ", u"dyo" : u"ぢょ", u"tsa" : u"つぁ", + u"tsi" : u"つぃ", u"tse" : u"つぇ", u"tso" : u"つぉ", u"tha" : u"てゃ", @@ -146,11 +154,13 @@ romaji_typing_rule = { u"thu" : u"てゅ", u"the" : u"てぇ", u"tho" : u"てょ", + u"twu" : u"とぅ", u"dha" : u"でゃ", u"dhi" : u"でぃ", u"dhu" : u"でゅ", u"dhe" : u"でぇ", u"dho" : u"でょ", + u"dwu" : u"どぅ", u"na" : u"な", u"ni" : u"に", u"nu" : u"ぬ", @@ -211,15 +221,21 @@ romaji_typing_rule = { u"myu" : u"みゅ", u"mye" : u"みぇ", u"myo" : u"みょ", - u"lya" : u"ゃ", - u"xya" : u"ゃ", u"ya" : u"や", - u"lyu" : u"ゅ", - u"xyu" : u"ゅ", + u"yi" : u"い", u"yu" : u"ゆ", + u"ye" : u"いぇ", + u"yo" : u"よ", + u"lya" : u"ゃ", + u"lyi" : u"ぃ", + u"lyu" : u"ゅ", + u"lye" : u"ぇ", u"lyo" : u"ょ", + u"xya" : u"ゃ", + u"xyi" : u"ぃ", + u"xyu" : u"ゅ", + u"xye" : u"ぇ", u"xyo" : u"ょ", - u"yo" : u"よ", u"ra" : u"ら", u"ri" : u"り", u"ru" : u"る", @@ -230,9 +246,13 @@ romaji_typing_rule = { u"ryu" : u"りゅ", u"rye" : u"りぇ", u"ryo" : u"りょ", - u"xwa" : u"ゎ", u"wa" : u"わ", + u"wi" : u"うぃ", + u"wu" : u"う", + u"we" : u"うぇ", u"wo" : u"を", + u"lwa" : u"ゎ", + u"xwa" : u"ゎ", u"n'" : u"ん", u"nn" : u"ん", u"wyi" : u"ゐ", @@ -337,6 +357,11 @@ romaji_correction_rule = { u"n." : (u"ん", u"."), } +# EUC-JP and SJIS do not have the chars +romaji_utf8_rule = { + u"ヴ" : (u"ゔ"), +} + # a port of 101kana.sty from scim-anthy kana_typing_rule = { # no modifiers keys diff --git a/engine/thumb.py b/engine/thumb.py index b678cda..8c4baff 100644 --- a/engine/thumb.py +++ b/engine/thumb.py @@ -21,12 +21,20 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -import gtk -import gobject -import time +__all__ = ( + "ThumbShiftKeyboard", + "ThumbShiftSegment", + ) +from ibus import keysyms +from ibus import modifier import segment +try: + from gtk.gdk import get_default_root_window +except ImportError: + get_default_root_window = lambda : None + _table = { 'q': [u'。', u'', u'ぁ'], @@ -76,6 +84,88 @@ _table = { '7': [u'7', u']', u''], '8': [u'8', u'(', u''], '9': [u'9', u')', u''], + '\\': [u'¥', u'', u''], +} + +_nicola_j_table = { + ':': [u':', u'', u''], + '@': [u'、', u'', u''], + '[': [u'゛', u'゜', u''], + ']': [u'」', u'', u''], + '8': [u'8', u'(', u''], + '9': [u'9', u')', u''], + '0': [u'0', u'', u''], +} + +_nicola_a_table = { + ':': [u':', u'', u''], + '@': [u'@', u'', u''], + '[': [u'、', u'', u''], + ']': [u'゛', u'゜', u''], + '8': [u'8', u'', u''], + '9': [u'9', u'(', u''], + '0': [u'0', u')', u''], +} + +_nicola_f_table = { + ':': [u'、', u'', u''], + '@': [u'@', u'', u''], + '[': [u'゛', u'゜', u''], + ']': [u'」', u'', u''], + '8': [u'8', u'(', u''], + '9': [u'9', u')', u''], + '0': [u'0', u'', u''], +} + +_kb231_j_fmv_table = { + '3': [u'3', u'', u'~'], + '0': [u'0', u'『', u''], + '-': [u'-', u'』', u''], + '=': [u'=', u'', u''], +} + +_kb231_a_fmv_table = { + '3': [u'3', u'', u'~'], + '0': [u'0', u')', u''], + '-': [u'-', u'『', u''], + '=': [u'=', u'』', u''], +} + +_kb231_f_fmv_table = { + '3': [u'3', u'', u'~'], + '0': [u'0', u'『', u''], + '-': [u'-', u'』', u''], + '=': [u'=', u'', u''], +} + +_kb611_j_fmv_table = { + '`': [u'‘', u'', u''], + '^': [u'々', u'£', u''], + ':': [u':', u'', u''], + '@': [u'、', u'¢', u''], + '[': [u'゛', u'゜', u''], + # keysyms are same and keycodes depend on the platforms. + #'¥': [u'¥', u'¬', u''], + '\\': [u'¥', u'¦', u''], +} + +_kb611_a_fmv_table = { + '`': [u'々', u'', u'£'], + ':': [u':', u'', u''], + '@': [u'@', u'', u''], + '[': [u'、', u'¢', u''], + #'¥': [u'¥', u'¬', u''], + '\\': [u'¥', u'¦', u''], +} + +_kb611_f_fmv_table = { + '`': [u'‘', u'', u''], + '^': [u'々', u'£', u''], + ':': [u'、', u'¢', u''], + '@': [u'@', u'', u''], + '[': [u'゛', u'゜', u''], + #'¥': [u'¥', u'¬', u''], + '\\': [u'¥', u'¦', u''], } _shift_table = { @@ -87,7 +177,6 @@ _shift_table = { } table = {} -shift_table = {} r_table = {} for k in _table.keys(): @@ -95,10 +184,6 @@ for k in _table.keys(): for c in _table[k]: r_table[c] = k -for k in _shift_table.keys(): - shift_table[ord(k)] = _shift_table[k] - r_table[_shift_table[k]] = k - kana_voiced_consonant_rule = { u"か゛" : u"が", u"き゛" : u"ぎ", @@ -129,6 +214,208 @@ kana_voiced_consonant_rule = { _UNFINISHED_HIRAGANA = set(u"かきくけこさしすせそたちつてとはひふへほ") +class ThumbShiftKeyboard: + def __init__(self, prefs=None): + self.__prefs = prefs + self.__table = table + self.__r_table = r_table + 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 + if self.__prefs != None: + self.reset() + self.__reset_shift_table(False) + + def __init_layout_table(self): + if self.__table != {}: + self.__table.clear() + if self.__r_table != {}: + self.__r_table.clear() + for k in _table.keys(): + self.__table[ord(k)] = _table[k] + for c in _table[k]: + self.__r_table[c] = k + + def __reset_layout_table(self, init, j_table, a_table, f_table): + if init: + self.__init_layout_table() + sub_table = None + if self.__layout == 0: + sub_table = j_table + elif self.__layout == 1: + sub_table = a_table + elif self.__layout == 2: + sub_table = f_table + if sub_table == None: + return + for k in sub_table.keys(): + self.__table[ord(unicode(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_a_table, + _nicola_f_table) + if self.__fmv_extension == 0: + return + if self.__fmv_extension >= 1: + self.__reset_layout_table(False, + _kb231_j_fmv_table, + _kb231_a_fmv_table, + _kb231_f_fmv_table) + if self.__fmv_extension >= 2: + self.__reset_layout_table(False, + _kb611_j_fmv_table, + _kb611_a_fmv_table, + _kb611_f_fmv_table) + + def __reset_shift_table(self, init): + self.__reset_extension_table(init) + if self.__handakuten: + for k in _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 _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 = keysyms.name_to_keycode(s.split('+')[-1]) + s = s.lower() + state = ('shift+' in s and modifier.SHIFT_MASK or 0) | ( + 'ctrl+' in s and modifier.CONTROL_MASK or 0) | ( + 'alt+' in s and modifier.MOD1_MASK or 0) + return (keyval, state) + + def __get_xkb_layout(self): + root_window = get_default_root_window() + if not root_window: + return 0 + prop = root_window.property_get("_XKB_RULES_NAMES")[2] + list = prop.split('\0') + layout = 0 + for data in 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 + + def reset(self): + s = self.__prefs.get_value('thumb', 'ls') + ls, state = self.__s_to_key_raw(s) + if ls == 0xffffff: + ls = keysyms.Muhenkan + self.set_ls(ls) + + s = self.__prefs.get_value('thumb', 'rs') + rs, state = self.__s_to_key_raw(s) + if rs == 0xffffff: + rs = keysyms.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) + + 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 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 self.__table.keys() + + def get_r_char(self, key, fallback=None): + return self.__r_table.get(key, fallback) + + def get_r_chars(self): + return 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 self.__shift_table.keys() + + class ThumbShiftSegment(segment.Segment): def __init__(self, enchars=u"", jachars=u""): diff --git a/ibus-anthy.spec.in b/ibus-anthy.spec.in index ada402b..23e25fb 100644 --- a/ibus-anthy.spec.in +++ b/ibus-anthy.spec.in @@ -20,6 +20,7 @@ BuildRequires: swig BuildRequires: pkgconfig BuildRequires: intltool +Requires: pygtk2 >= 2.15.2 Requires: ibus >= 1.2.0.20100111 Requires: anthy %if %enable_kasumi diff --git a/setup/anthyprefs.py b/setup/anthyprefs.py index 9af9ba4..5444bab 100644 --- a/setup/anthyprefs.py +++ b/setup/anthyprefs.py @@ -170,11 +170,17 @@ _config = { 'dict_admin_command': ['/usr/bin/kasumi', 'kasumi'], 'add_word_command': ['/usr/bin/kasumi', 'kasumi', '-a'], - - 'thumb_rs': gtk.keysyms.Henkan, - 'thumb_ls': gtk.keysyms.Muhenkan, - 'thumb_t1': 100, - 'thumb_t2': 75, + }, + + 'thumb': { + 'keyboard_layout_mode': True, + 'keyboard_layout': 0, + 'fmv_extension': 2, + 'handakuten': False, + 'rs': 'Henkan', + 'ls': 'Muhenkan', + 't1': 100, + 't2': 75, } } diff --git a/setup/main.py b/setup/main.py index 1da35f7..5921d24 100644 --- a/setup/main.py +++ b/setup/main.py @@ -24,7 +24,7 @@ from os import path, getenv import gtk import pango from gtk import glade -from ibus import keysyms, modifier +from ibus import keysyms, modifier, Bus from gettext import dgettext, bindtextdomain from anthyprefs import AnthyPrefs @@ -41,7 +41,10 @@ def s_to_l(s): class AnthySetup(object): def __init__(self): - self.prefs = prefs = AnthyPrefs() + self.__config = Bus().get_config() + self.__thumb_kb_layout_mode = None + self.__thumb_kb_layout = None + self.prefs = prefs = AnthyPrefs(None, self.__config) localedir = getenv("IBUS_LOCALEDIR") bindtextdomain("ibus-anthy", localedir) @@ -63,8 +66,11 @@ class AnthySetup(object): for name in ['input_mode', 'typing_method', 'period_style', 'symbol_style', 'ten_key_mode', 'behavior_on_focus_out', 'behavior_on_period', - 'half_width_symbol', 'half_width_number', 'half_width_space']: - xml.get_widget(name).set_active(prefs.get_value('common', name)) + 'half_width_symbol', 'half_width_number', 'half_width_space', + 'thumb:keyboard_layout_mode', 'thumb:keyboard_layout', + 'thumb:fmv_extension', 'thumb:handakuten']: + section, key = self.__get_section_key(name) + xml.get_widget(name).set_active(prefs.get_value(section, key)) l = ['default', 'atok', 'wnn'] s_type = prefs.get_value('common', 'shortcut_type') @@ -89,6 +95,14 @@ class AnthySetup(object): ls.append([k, l_to_s(self.prefs.get_value(sec, k))]) tv.set_model(ls) + self.__thumb_kb_layout_mode = xml.get_widget('thumb:keyboard_layout_mode') + self.__thumb_kb_layout = xml.get_widget('thumb:keyboard_layout') + self.__set_thumb_kb_label() + + for name in ['thumb:ls', 'thumb:rs']: + section, key = self.__get_section_key(name) + xml.get_widget(name).set_text(prefs.get_value(section, key)) + tv = xml.get_widget('treeview2') tv.append_column(gtk.TreeViewColumn('', gtk.CellRendererText(), text=0)) tv.get_selection().connect_after('changed', @@ -97,6 +111,32 @@ class AnthySetup(object): xml.signal_autoconnect(self) + 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 __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(self.__thumb_kb_layout_mode.name) + 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) + if layout_mode and \ + not self.__config.get_value('general', 'use_system_keyboard_layout', True): + self.xml.get_widget('thumb:warning_hbox').show() + else: + self.xml.get_widget('thumb:warning_hbox').hide() + def on_selection_changed(self, widget, id): set_sensitive = lambda a, b: self.xml.get_widget(a).set_sensitive(b) flg = True if widget.get_selected()[1] else False @@ -139,16 +179,22 @@ class AnthySetup(object): widget.set_sensitive(False) def on_cb_changed(self, widget): - self.prefs.set_value('common', widget.name, widget.get_active()) + section, key = self.__get_section_key(widget.name) + self.prefs.set_value(section, key, widget.get_active()) self.xml.get_widget('btn_apply').set_sensitive(True) def on_sb_changed(self, widget): - self.prefs.set_value('common', widget.name, widget.get_value_as_int()) + section, key = self.__get_section_key(widget.name) + self.prefs.set_value(section, key, widget.get_value_as_int()) self.xml.get_widget('btn_apply').set_sensitive(True) def on_ck_toggled(self, widget): - self.prefs.set_value('common', widget.name, widget.get_active()) + section, key = self.__get_section_key(widget.name) + self.prefs.set_value(section, key, widget.get_active()) self.xml.get_widget('btn_apply').set_sensitive(True) + if self.__thumb_kb_layout_mode and \ + widget.name == self.__thumb_kb_layout_mode.name: + self.__set_thumb_kb_label() def on_btn_edit_clicked(self, widget): ls, it = self.xml.get_widget('shortcut').get_selection().get_selected() @@ -179,6 +225,41 @@ class AnthySetup(object): ls.set(it, 1, new) self.xml.get_widget('btn_apply').set_sensitive(True) + def on_btn_thumb_key_clicked(self, widget): + if widget.name == 'thumb:button_ls': + entry = 'thumb:ls' + elif widget.name == 'thumb:button_rs': + entry = 'thumb:rs' + else: + return + text = self.xml.get_widget(entry).get_text() + m = self.xml.get_widget('treeview2').get_model() + m.clear() + if text != None: + m.append([text]) + i = m.get_iter_first() + self.xml.get_widget('treeview2').get_selection().select_iter(i) + self.xml.get_widget('entry2').set_text('') + self.xml.get_widget('button4').hide() + self.xml.get_widget('button5').show() + self.xml.get_widget('button6').hide() + for w in ['checkbutton6', 'checkbutton7', 'checkbutton8']: + self.xml.get_widget(w).set_active(False) + dlg = self.xml.get_widget('edit_shortcut') + id = dlg.run() + dlg.hide() + self.xml.get_widget('button4').show() + self.xml.get_widget('button5').hide() + self.xml.get_widget('button6').show() + if id == gtk.RESPONSE_OK: + l, i = self.xml.get_widget('treeview2').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.xml.get_widget(entry).set_text(new) + self.xml.get_widget('btn_apply').set_sensitive(True) + def _get_shortcut_sec(self): l = ['default', 'atok', 'wnn'] s_type = self.xml.get_widget('shortcut_type').get_active_text().lower() @@ -195,7 +276,8 @@ class AnthySetup(object): for k in self.prefs.keys(sec): ls.append([k, l_to_s(self.prefs.get_value(sec, k))]) - self.prefs.set_value('common', widget.name, sec[len('shortcut/'):]) + section, key = self.__get_section_key(widget.name) + self.prefs.set_value(section, key, sec[len('shortcut/'):]) self.xml.get_widget('btn_apply').set_sensitive(True) def on_shortcut_key_release_event(self, widget, event): @@ -262,6 +344,24 @@ class AnthySetup(object): return True l.append([s]) + def on_button5_clicked(self, widget): + s = self.xml.get_widget('entry2').get_text() + if not s or not keysyms.name_to_keycode(s): + dlg = self.xml.get_widget('invalid_keysym') + dlg.set_markup('%s' % _('Invalid keysym')) + dlg.format_secondary_text(_('This keysym is not valid')) + dlg.run() + dlg.hide() + return True + for w, m in [('checkbutton6', 'Ctrl+'), + ('checkbutton7', 'Alt+'), + ('checkbutton8', 'Shift+')]: + if self.xml.get_widget(w).get_active(): + s = m + s + l, i = self.xml.get_widget('treeview2').get_selection().get_selected() + l[i][0] = s + return True + def on_button6_clicked(self, widget): l, i = self.xml.get_widget('treeview2').get_selection().get_selected() if i: diff --git a/setup/setup.glade b/setup/setup.glade index f068938..39fc754 100644 --- a/setup/setup.glade +++ b/setup/setup.glade @@ -460,7 +460,7 @@ Hold True 8 - + True _Shortcut Type: True @@ -612,6 +612,373 @@ Wnn + + True + 8 + 4 + + + True + 0 + none + + + True + 8 + 8 + 12 + + + True + 8 + 8 + 4 + + + True + 2 + 3 + 8 + 4 + + + True + 0 + True + Thumb Shift _Left Key: + thumb:ls + + + + + + + True + True + False + + + 1 + 2 + + + + + ... + True + True + False + + + + 2 + 3 + + + + + True + 0 + True + _Thumb Shift Right Key: + thumb:rs + + + 1 + 2 + + + + + True + True + False + + + 1 + 2 + 1 + 2 + + + + + ... + True + True + False + + + + 2 + 3 + 1 + 2 + + + + + + + + + + Adjust _input method layout to system keyboard layout + Adjust IM layout to XKB layout + True + True + False + True + True + + + + + 1 + 2 + + + + + + True + 8 + + + True + 0 + True + Input _Method Layout: + thumb:keyboard_layout + + + False + False + 0 + + + + + True + NICOLA-J +NICOLA-A +NICOLA-F + + + + 1 + + + + + 2 + 3 + + + + + + True + 8 + + + True + gtk-dialog-info + + + False + False + 0 + + + + + True + 0 + True + Restart ibus when you change the keyboard layout. + Restart ibus when you change XKB + + + False + False + 1 + + + + + 3 + 4 + + + + + + False + 8 + + + True + gtk-dialog-warning + + + False + False + 0 + + + + + True + 0 + True + Strongly recommend to enable "Use system keyboard layout" check button in "Advanced" tab using 'ibus-setup' command + + + False + False + 1 + + + + + 4 + 5 + + + + + + True + 8 + + + True + 0 + True + _Additional Key Arrangement: + thumb:fmv_extension + + + False + False + 0 + + + + + True + None +FMV KB231 key extension +FMV KB611 key extension + '~', 『', '¢', '£' and so on can be output with Thumb Shift key + + + + 1 + + + + + 5 + 6 + + + + + + True + 8 + + + True + gtk-dialog-info + + + False + False + 0 + + + + + True + 0 + True + 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. + You do not have to reconfigure XKB since this option changes IM layout only with IM on. + + + False + False + 1 + + + + + 6 + 7 + + + + + + _Enable semi-voiced sound mark with Shift key + Seion + Shift can output Handakuon + True + True + False + True + True + + + + + 7 + 8 + + + + + + + + + + True + <b>Thumb Shift Layout</b> + True + + + label_item + + + + + False + False + 0 + + + + + 2 + + + + + True + Thumb S_hift + True + vbox3 + + + 2 + False + tab + + + True <span size='xx-large'><b>IBus-Anthy</b></span> @@ -626,18 +993,18 @@ URL : http://code.google.com/p/ibus/ start - 2 + 3 - + True Abo_ut True about - 2 + 3 False tab @@ -752,7 +1119,7 @@ URL : http://code.google.com/p/ibus/ True 8 - + True Key Code: @@ -799,7 +1166,7 @@ URL : http://code.google.com/p/ibus/ True 8 - + True Modifier: