diff options
author | fujiwarat <takao.fujiwara1@gmail.com> | 2010-03-10 17:28:37 +0900 |
---|---|---|
committer | fujiwarat <takao.fujiwara1@gmail.com> | 2010-03-11 19:22:15 +0900 |
commit | f8c60a9844df6da08cc0327b62dec6917961dfc4 (patch) | |
tree | 008da92526d3dd5f43c6e99242474b6619c5f92b | |
parent | 1c30de7977d789d084df6122b73f9dc6a4b44f26 (diff) | |
download | ibus-anthy-f8c60a9844df6da08cc0327b62dec6917961dfc4.tar.gz |
Add dict switch menu #571728
-rw-r--r-- | engine/anthy.i | 8 | ||||
-rw-r--r-- | engine/engine.py | 398 | ||||
-rw-r--r-- | po/POTFILES.in | 1 | ||||
-rw-r--r-- | setup/anthyprefs.py | 62 | ||||
-rw-r--r-- | setup/main.py | 526 | ||||
-rw-r--r-- | setup/prefs.py | 6 | ||||
-rw-r--r-- | setup/setup.glade | 468 |
7 files changed, 1439 insertions, 30 deletions
diff --git a/engine/anthy.i b/engine/anthy.i index 2f1140d..11a52dd 100644 --- a/engine/anthy.i +++ b/engine/anthy.i @@ -109,6 +109,14 @@ struct anthy_context {}; 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/engine.py b/engine/engine.py index 56e5b28..6b95ab8 100644 --- a/engine/engine.py +++ b/engine/engine.py @@ -21,8 +21,9 @@ # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. import os -from os import path +from os import environ, path from locale import getpreferredencoding +import signal import sys import gobject import ibus @@ -73,6 +74,13 @@ CONV_MODE_PREDICTION = range(14) CLIPBOARD_RECONVERT = range(1) +LINK_DICT_EMBEDDED, \ +LINK_DICT_SINGLE = range(2) + +IMPORTED_EMBEDDED_DICT_DIR = "imported_words_default.d" +IMPORTED_EMBEDDED_DICT_PREFIX = "ibus__" +IMPORTED_SINGLE_DICT_PREFIX = "imported_words_ibus__" + ''' FIXME: currently configuration values are extracted by enviroment values. It's better to load config.py(.in) in engine and setup instead and I will move KASUMI_IMG_PATH. @@ -109,6 +117,7 @@ class Engine(ibus.EngineBase): # init state self.__idle_id = 0 self.__input_mode = INPUT_MODE_HIRAGANA + self.__dict_mode = 0 self.__prop_dict = {} self.__is_utf8 = (getpreferredencoding().lower() == "utf-8") @@ -207,18 +216,73 @@ class Engine(ibus.EngineBase): typing_mode_prop.set_sub_props(props) anthy_props.append(typing_mode_prop) - self.__set_dict_props(anthy_props) + self.__set_dict_mode_props(anthy_props) + self.__set_dict_config_props(anthy_props) anthy_props.append(ibus.Property(key=u"setup", tooltip=UN(_("Configure Anthy")))) return anthy_props - def __set_dict_props(self, anthy_props): - path = self.__prefs.get_value('common', 'dict_admin_command') - if not os.path.exists(path[0]): + 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_dict_mode_props(self, anthy_props): + short_label = self.__prefs.get_value('dict/file/embedded', + 'short_label') + dict_mode_prop = ibus.Property(key=u"DictMode", + type=ibus.PROP_TYPE_MENU, + label=UN(short_label), + tooltip=UN(_("Switch Dictionary"))) + self.__prop_dict[u"DictMode"] = dict_mode_prop + props = ibus.PropList() + + long_label = self.__prefs.get_value('dict/file/embedded', + 'long_label') + props.append(ibus.Property(key=u"DictMode.embedded", + type=ibus.PROP_TYPE_RADIO, + label=UN(_(long_label)))) + + for file in self.__prefs.get_value('dict', 'files'): + self._link_dict_file(file) + id = self._get_dict_id_from_file(file) + if id == None: + continue + 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') + if 'is_system' in self.__prefs.keys(section) and \ + self.__prefs.get_value(section, 'is_system'): + uni_long_label = UN(_(long_label)) + else: + uni_long_label = UN(long_label) + props.append(ibus.Property(key=UN(key), + type=ibus.PROP_TYPE_RADIO, + label=uni_long_label)) + + props[self.__dict_mode].set_state(ibus.PROP_STATE_CHECKED) + for prop in props: + self.__prop_dict[prop.key] = prop + dict_mode_prop.set_sub_props(props) + anthy_props.append(dict_mode_prop) + self.__init_signal() + + def __set_dict_config_props(self, anthy_props): + admin_command = self.__prefs.get_value('common', 'dict_admin_command') + if not path.exists(admin_command[0]): return - if os.path.exists(KASUMI_IMG_PATH): + if path.exists(KASUMI_IMG_PATH): label = u"" icon = unicode(KASUMI_IMG_PATH) else: @@ -255,6 +319,22 @@ class Engine(ibus.EngineBase): return clipboard_text + def __get_single_dict_files(self): + files = self.__prefs.get_value('dict', 'files') + single_files = [] + for file in files: + id = self._get_dict_id_from_file(file) + if id == None: + continue + 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): self.update_preedit_text(ibus.Text(string, attrs), cursor_pos, visible) @@ -434,9 +514,16 @@ class Engine(ibus.EngineBase): def property_activate(self, prop_name, state): if state == ibus.PROP_STATE_CHECKED: - if self.__input_mode_activate(prop_name, state): + if prop_name == None: return - if self.__typing_mode_activate(prop_name, state): + elif prop_name.startswith(u"InputMode."): + self.__input_mode_activate(prop_name, state) + return + elif prop_name.startswith(u"TypingMode."): + self.__typing_mode_activate(prop_name, state) + return + elif prop_name.startswith(u"DictMode."): + self.__dict_mode_activate(prop_name, state) return else: if prop_name == 'setup': @@ -447,11 +534,14 @@ class Engine(ibus.EngineBase): 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.PROP_STATE_CHECKED) def __input_mode_activate(self, prop_name, state): - if not prop_name.startswith(u"InputMode."): - return False - input_modes = { u"InputMode.Hiragana" : (INPUT_MODE_HIRAGANA, u"あ"), u"InputMode.Katakana" : (INPUT_MODE_KATAKANA, u"ア"), @@ -462,13 +552,13 @@ class Engine(ibus.EngineBase): if prop_name not in input_modes: print >> sys.stderr, "Unknow prop_name = %s" % prop_name - return True + return self.__prop_dict[prop_name].set_state(state) self.update_property(self.__prop_dict[prop_name]) mode, label = input_modes[prop_name] if self.__input_mode == mode: - return True + return self.__input_mode = mode prop = self.__prop_dict[u"InputMode"] @@ -479,9 +569,6 @@ class Engine(ibus.EngineBase): self.__invalidate() def __typing_mode_activate(self, prop_name, state): - if not prop_name.startswith(u"TypingMode."): - return False - typing_modes = { u"TypingMode.Romaji" : (jastring.TYPING_MODE_ROMAJI, u"R"), u"TypingMode.Kana" : (jastring.TYPING_MODE_KANA, u"か"), @@ -490,7 +577,7 @@ class Engine(ibus.EngineBase): if prop_name not in typing_modes: print >> sys.stderr, "Unknow prop_name = %s" % prop_name - return True + return self.__prop_dict[prop_name].set_state(state) self.update_property(self.__prop_dict[prop_name]) if prop_name == u"TypingMode.ThumbShift": @@ -522,6 +609,57 @@ class Engine(ibus.EngineBase): prop.label = label self.update_property(prop) + 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) + if id == None: + return None + return 'DictMode.' + id + + def __dict_mode_activate(self, prop_name, state): + if prop_name not in self.__prop_dict.keys(): + # The prop_name is added. Need to restart. + return + i = prop_name.find('.') + if i < 0: + return + id = prop_name[i + 1:].encode('utf-8') + + file = None + files = self.__prefs.get_value('dict', 'files') + if id == 'embedded': + pass + elif id == 'anthy_zipcode' or id == 'ibus_symbol': + file = self.__prefs.get_value('dict', id)[0] + else: + found = False + for file in files: + if id == self._get_quoted_id(file): + found = True + break + if found == False: + return + + if id == 'embedded': + dict_name = 'default' + self.__dict_mode = 0 + else: + dict_name = 'ibus__' + id + self.__dict_mode = files.index(file) + 1 + self.__prop_dict[prop_name].set_state(state) + self.update_property(self.__prop_dict[prop_name]) + self.__context.init_personality() + self.__context.do_set_personality(dict_name) + + prop = self.__prop_dict[u"DictMode"] + section = 'dict/file/' + id + prop.label = self.__prefs.get_value(section, 'short_label') + self.update_property(prop) + def focus_in(self): self.register_properties(self.__prop_list) self.__refresh_typing_mode_property() @@ -540,6 +678,7 @@ class Engine(ibus.EngineBase): if self.__idle_id != 0: gobject.source_remove(self.__idle_id) self.__idle_id = 0 + self.__remove_dict_files() super(Engine,self).do_destroy() # begine convert @@ -587,6 +726,43 @@ class Engine(ibus.EngineBase): candidate = candidate.replace(key, value) self.__lookup_table.append_candidate(ibus.Text(candidate)) + def __fill_anthy_zipcode_strip(self, dict_file, id): + import re + text = self.__preedit_ja_string.get_latin()[0] + if text.find('-') < 0: + return + text = text.replace('-', '') + section = 'dict/file/' + id + if 'encoding' not in self.__prefs.keys(section): + section = 'dict/file/default' + encoding = self.__prefs.get_value(section, 'encoding') + contents = unicode(open(dict_file).read(), encoding) + expression = re.compile("^" + text + "[ \t]") + + found = False + dict_dest = None + for line in contents.split('\n'): + matched = expression.search(line) + if matched: + found = True + dict_dest = unicode(matched.string).split(' ')[2] + break + if found: + self.__lookup_table.append_candidate(ibus.Text(dict_dest)) + + def __fill_lookup_table_dict_mode(self): + if self.__dict_mode <= 0: + return + single_files = self.__get_single_dict_files() + file = single_files[self.__dict_mode - 1] + if file == None: + return + id = self._get_dict_id_from_file(file) + if id == None: + return + if id == 'anthy_zipcode': + self.__fill_anthy_zipcode_strip(file, id) + def __fill_lookup_table(self): if self.__convert_mode == CONV_MODE_PREDICTION: seg_stat = anthy.anthy_prediction_stat() @@ -612,6 +788,7 @@ class Engine(ibus.EngineBase): candidate = unicode(buf, "utf-8") self.__lookup_table.append_candidate(ibus.Text(candidate)) self.__candidate_cb(candidate) + self.__fill_lookup_table_dict_mode() def __invalidate(self): @@ -1060,6 +1237,12 @@ class Engine(ibus.EngineBase): elif base_sec == 'thumb': cls.__prefs.set_value(base_sec, name, value) cls._reset_thumb() + elif base_sec == 'dict': + cls._set_dict_files_value(base_sec, name, value) + elif base_sec.startswith('dict/file/'): + if base_sec not in cls.__prefs.sections(): + cls._fetch_dict_values(base_sec) + cls.__prefs.set_value(base_sec, name, value) elif base_sec: cls.__prefs.set_value(base_sec, name, value) else: @@ -1101,6 +1284,163 @@ class Engine(ibus.EngineBase): else: cls.__thumb.reset() + @classmethod + def _get_userhome(cls): + if 'HOME' not in environ: + import pwd + userhome = pwd.getpwuid(getuid()).pw_dir + else: + userhome = environ['HOME'] + userhome = userhome.rstrip('/') + return userhome + + @classmethod + def _get_quoted_id(cls, file): + id = file + has_mbcs = False + + for i in xrange(0, len(id)): + if ord(id[i]) >= 0x7f: + has_mbcs = True + break + if has_mbcs: + import urllib + id = urllib.quote(id) + + if id.find('/') >=0: + id = id[id.rindex('/') + 1:] + if id.find('.') >=0: + id = id[:id.rindex('.')] + return id + + @classmethod + def _get_dict_id_from_file(cls, file): + if file in cls.__prefs.get_value('dict', 'anthy_zipcode'): + id = 'anthy_zipcode' + elif file in cls.__prefs.get_value('dict', 'ibus_symbol'): + id = 'ibus_symbol' + else: + id = cls._get_quoted_id(file) + return id + + @classmethod + def _link_dict_file_with_id(cls, file, id, link_mode): + if id == None: + return + if link_mode == LINK_DICT_EMBEDDED: + directory = cls._get_userhome() + "/.anthy/" + IMPORTED_EMBEDDED_DICT_DIR + name = IMPORTED_EMBEDDED_DICT_PREFIX + id + elif link_mode == LINK_DICT_SINGLE: + directory = cls._get_userhome() + "/.anthy" + name = IMPORTED_SINGLE_DICT_PREFIX + id + else: + return + if path.exists(directory): + if not path.isdir(directory): + print >> sys.stderr, directory + " is not a directory" + return + else: + os.makedirs(directory, 0700) + backup_dir = os.getcwd() + os.chdir(directory) + if path.exists(directory + '/' + name): + if path.islink(directory + '/' + name): + print >> sys.stderr, "Removing " + name + os.unlink(directory + '/' + name) + else: + alternate = name + str(os.getpid()) + print >> sys.stderr, "Moving " + name + " to " + alternate + os.rename(name, alternate) + os.symlink(file, directory + '/' + name) + if backup_dir != None: + os.chdir(backup_dir) + + @classmethod + def _remove_dict_file_with_id(cls, file, id, link_mode): + if id == None: + return + if link_mode == LINK_DICT_EMBEDDED: + directory = cls._get_userhome() + "/.anthy/" + IMPORTED_EMBEDDED_DICT_DIR + name = IMPORTED_EMBEDDED_DICT_PREFIX + id + elif link_mode == LINK_DICT_SINGLE: + directory = cls._get_userhome() + "/.anthy" + name = IMPORTED_SINGLE_DICT_PREFIX + id + else: + return + if path.exists(directory): + if not path.isdir(directory): + print >> sys.stderr, directory + " is not a directory" + return + backup_dir = os.getcwd() + os.chdir(directory) + if path.exists(directory + '/' + name): + os.unlink(directory + '/' + name) + if backup_dir != None: + os.chdir(backup_dir) + + @classmethod + def _link_dict_file(cls, file): + id = cls._get_dict_id_from_file(file) + if id == None: + return + section = 'dict/file/' + id + if section not in cls.__prefs.sections(): + cls._fetch_dict_values(section) + if cls.__prefs.get_value(section, 'embed'): + cls._link_dict_file_with_id(file, id, LINK_DICT_EMBEDDED) + if cls.__prefs.get_value(section, 'single'): + cls._link_dict_file_with_id(file, id, LINK_DICT_SINGLE) + + @classmethod + def _remove_dict_file(cls, file): + id = cls._get_dict_id_from_file(file) + if id == None: + return + section = 'dict/file/' + id + if section not in cls.__prefs.sections(): + cls._fetch_dict_values(section) + if cls.__prefs.get_value(section, 'embed'): + cls._remove_dict_file_with_id(file, id, LINK_DICT_EMBEDDED) + if cls.__prefs.get_value(section, 'single'): + cls._remove_dict_file_with_id(file, id, LINK_DICT_SINGLE) + + @classmethod + def _set_dict_files_value(cls, base_sec, name, value): + if name == 'files': + str_list = [] + for file in value: + str_list.append(str(file)) + old_files = cls.__prefs.get_value(base_sec, name) + for file in old_files: + if file in str_list: + continue + cls._remove_dict_file(file) + for file in str_list: + if file in old_files: + continue + cls._link_dict_file(file) + cls.__prefs.set_value(base_sec, name, str_list) + else: + cls.__prefs.set_value(base_sec, name, value) + + @classmethod + def _fetch_dict_values(cls, section): + cls.__prefs.set_new_section(section) + cls.__prefs.set_new_key(section, 'short_label') + cls.__prefs.fetch_item(section, 'short_label') + cls.__prefs.set_value(section, 'short_label', + str(cls.__prefs.get_value(section, 'short_label'))) + cls.__prefs.set_new_key(section, 'long_label') + cls.__prefs.fetch_item(section, 'long_label') + cls.__prefs.set_value(section, 'long_label', + str(cls.__prefs.get_value(section, 'long_label'))) + cls.__prefs.set_new_key(section, 'embed') + cls.__prefs.fetch_item(section, 'embed') + cls.__prefs.set_new_key(section, 'single') + cls.__prefs.fetch_item(section, 'single') + cls.__prefs.set_new_key(section, 'reverse') + cls.__prefs.fetch_item(section, 'reverse') + @staticmethod def _mk_key(keyval, state): if state & (modifier.CONTROL_MASK | modifier.MOD1_MASK): @@ -1383,6 +1723,22 @@ class Engine(ibus.EngineBase): ibus.PROP_STATE_CHECKED) return True + def __cmd_circle_dict_method(self, keyval, state): + if not self._chk_mode('0'): + return False + + single_files = self.__get_single_dict_files() + new_mode = self.__dict_mode + 1 + if new_mode > len(single_files): + new_mode = 0 + self.__dict_mode = new_mode + prop_name = self.__dict_mode_get_prop_name(self.__dict_mode) + if prop_name == None: + return False + self.__dict_mode_activate(prop_name, + ibus.PROP_STATE_CHECKED) + return True + #edit_keys def __cmd_insert_space(self, keyval, state): if (self.__prefs.get_value('common', 'half_width_space') or @@ -1909,12 +2265,12 @@ class Engine(ibus.EngineBase): return True def __start_dict_admin(self): - path = self.__prefs.get_value('common', 'dict_admin_command') - os.spawnl(os.P_NOWAIT, *path) + command = self.__prefs.get_value('common', 'dict_admin_command') + os.spawnl(os.P_NOWAIT, *command) def __start_add_word(self): - path = self.__prefs.get_value('common', 'add_word_command') - os.spawnl(os.P_NOWAIT, *path) + command = self.__prefs.get_value('common', 'add_word_command') + os.spawnl(os.P_NOWAIT, *command) def __start_setup(self): if Engine.__setup_pid != 0: diff --git a/po/POTFILES.in b/po/POTFILES.in index 2360a02..4c03774 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -2,5 +2,6 @@ # Please keep this file in alphabetical order. engine/engine.py engine/factory.py +setup/anthyprefs.py setup/main.py setup/setup.glade diff --git a/setup/anthyprefs.py b/setup/anthyprefs.py index 5444bab..2f66a3d 100644 --- a/setup/anthyprefs.py +++ b/setup/anthyprefs.py @@ -26,6 +26,7 @@ import sys from prefs import Prefs +N_ = lambda a : a __all__ = ['AnthyPrefs'] @@ -88,6 +89,7 @@ _cmd_keys = [ "half_katakana_mode", # "cancel_pseudo_ascii_mode_key", "circle_typing_method", + "circle_dict_method", "insert_space", "insert_alternate_space", @@ -181,7 +183,62 @@ _config = { 'ls': 'Muhenkan', 't1': 100, 't2': 75, - } + }, + + 'dict': { + 'anthy_zipcode': ['/usr/share/anthy/zipcode.t'], + 'ibus_symbol': ['/usr/share/ibus-anthy/dicts/symbol.t'], + 'files': [ + '/usr/share/anthy/zipcode.t', + '/usr/share/ibus-anthy/dicts/symbol.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/anthy_zipcode': { + 'embed': False, + 'single': True, + 'icon': None, + 'short_label': '〒', + 'long_label': N_("Zip Code Conversion"), + 'preview_lines': 30, + 'reverse': True, + 'is_system': True, + 'encoding': 'euc_jp', + }, + + 'dict/file/ibus_symbol': { + 'embed': True, + 'single': False, + 'icon': None, + 'short_label': '記', + 'long_label': N_("Symbol"), + 'preview_lines': -1, + 'reverse': False, + 'is_system': True, + }, } _shortcut_default = { @@ -190,6 +247,7 @@ _shortcut_default = { 'circle_kana_mode': ['Ctrl+period', 'Ctrl+greater', 'Hiragana_Katakana'], # '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'], @@ -254,6 +312,7 @@ _shortcut_atok = { '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'], @@ -316,6 +375,7 @@ _shortcut_wnn = { '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'], diff --git a/setup/main.py b/setup/main.py index 5921d24..a05d421 100644 --- a/setup/main.py +++ b/setup/main.py @@ -20,7 +20,8 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -from os import path, getenv +from os import environ, getenv, getuid, path +import os import gtk import pango from gtk import glade @@ -109,8 +110,72 @@ class AnthySetup(object): 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' + xml.get_widget(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' + xml.get_widget(name).set_text(cli) + + tv = xml.get_widget('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_max_width(300) + tv.append_column(column) + + # Translators: "Embd" means a short word 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" means a short word 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) + + ''' + Unfortunatelly reverse conversion is too slow. + # Translators: "Rev" means a short word 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() + xml.signal_autoconnect(self) + 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: @@ -121,6 +186,16 @@ class AnthySetup(object): key = name return (section, key) + def __run_message_dialog(self, message, type=gtk.MESSAGE_INFO): + label = gtk.Label(message) + dlg = gtk.MessageDialog(parent=self.xml.get_widget('main'), + flags='modal', + type=type, + buttons=gtk.BUTTONS_OK, + message_format=message) + dlg.run() + dlg.destroy() + def __set_thumb_kb_label(self): if self.__thumb_kb_layout_mode == None or \ self.__thumb_kb_layout == None: @@ -137,6 +212,256 @@ class AnthySetup(object): else: self.xml.get_widget('thumb:warning_hbox').hide() + 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 xrange(0, len(id)): + if ord(id[i]) >= 0x7f: + has_mbcs = True + break + if has_mbcs: + import urllib + id = urllib.quote(id) + + if id.find('/') >=0: + id = id[id.rindex('/') + 1:] + if id.find('.') >=0: + id = id[:id.rindex('.')] + return id + + def __get_dict_file_from_id(self, selected_id): + found = False + files = self.prefs.get_value('dict', 'files') + + if selected_id == 'anthy_zipcode': + return self.prefs.get_value('dict', 'anthy_zipcode')[0] + elif selected_id == 'ibus_symbol': + return self.prefs.get_value('dict', 'ibus_symbol')[0] + for file in files: + id = self.__get_quoted_id(file) + if selected_id == id: + found = True + break + if found: + return file + return None + + 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 + 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.xml.get_widget('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 + if file in prefs.get_value('dict', 'anthy_zipcode'): + id = 'anthy_zipcode' + elif file in prefs.get_value('dict', 'ibus_symbol'): + id = 'ibus_symbol' + else: + 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."), + gtk.MESSAGE_ERROR) + return + if not path.exists(file): + self.__run_message_dialog(_("Your choosed file does not exist."), + gtk.MESSAGE_ERROR) + return + if path.isdir(file): + self.__run_message_dialog(_("Your choosed file is a directory."), + gtk.MESSAGE_ERROR) + return + if file.startswith(self.__get_userhome() + "/.anthy"): + self.__run_message_dialog(_("You cannot add dictionaries in the anthy private directory."), + gtk.MESSAGE_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.MESSAGE_ERROR) + return + + single = self.xml.get_widget('dict:single').get_active() + embed = self.xml.get_widget('dict:embed').get_active() + reverse = self.xml.get_widget('dict:reverse').get_active() + short_label = self.xml.get_widget('dict:short_entry').get_text() + if len(unicode(short_label, "utf-8")) > 1: + short_label = unicode(short_label, "utf-8")[0].encode("utf-8") + long_label = self.xml.get_widget('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.xml.get_widget('btn_apply').set_sensitive(True) + files = [] + + def __init_dict_chooser_dialog(self): + self.xml.get_widget('dict:single').set_active(True) + self.xml.get_widget('dict:embed').set_active(False) + self.xml.get_widget('dict:reverse').set_active(False) + short_entry = self.xml.get_widget('dict:short_entry') + short_entry.set_text('') + short_entry.set_editable(True) + long_entry = self.xml.get_widget('dict:long_entry') + long_entry.set_text('') + long_entry.set_editable(True) + + def __get_selected_dict_id(self): + l, it = self.xml.get_widget('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(unicode(short_label, "utf-8")) > 1: + short_label = unicode(short_label, "utf-8")[0].encode("utf-8") + self.xml.get_widget('dict:single').set_active(single) + self.xml.get_widget('dict:embed').set_active(embed) + self.xml.get_widget('dict:reverse').set_active(reverse) + short_entry = self.xml.get_widget('dict:short_entry') + short_entry.set_text(short_label) + long_entry = self.xml.get_widget('dict:long_entry') + long_entry.set_text(long_label) + if is_system_dict: + short_entry.set_editable(False) + long_entry.set_editable(False) + else: + short_entry.set_editable(True) + 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') + prefs.set_value(section, 'short_label', + 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', + 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.xml.get_widget('dict:view').get_model() + l.append([id, short_label, long_label, embed, single, reverse]) + else: + l, i = self.xml.get_widget('dict:view').get_selection().get_selected() + if i : + l[i] = [id, short_label, long_label, embed, single, reverse] + + key = 'short_label' + if key not in prefs.keys(section): + prefs.set_new_key(section, key) + prefs.set_value(section, key, short_label) + key = 'long_label' + if key not in prefs.keys(section): + prefs.set_new_key(section, key) + prefs.set_value(section, key, long_label) + key = 'embed' + if key not in prefs.keys(section): + prefs.set_new_key(section, key) + prefs.set_value(section, key, embed) + key = 'single' + if key not in prefs.keys(section): + prefs.set_new_key(section, key) + prefs.set_value(section, key, single) + key = 'reverse' + if key not in prefs.keys(section): + prefs.set_new_key(section, key) + prefs.set_value(section, key, reverse) + + def __text_cell_data_cb(self, layout, renderer, model, iter, id): + l = self.xml.get_widget('dict:view').get_model() + text = l.get_value(iter, id) + renderer.set_property('text', text) + + def __toggle_cell_data_cb(self, layout, renderer, model, iter, id): + l = self.xml.get_widget('dict:view').get_model() + active = l.get_value(iter, id) + renderer.set_property('active', active) + 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 @@ -260,6 +585,181 @@ class AnthySetup(object): self.xml.get_widget(entry).set_text(new) self.xml.get_widget('btn_apply').set_sensitive(True) + def on_btn_dict_command_clicked(self, widget): + if widget.name == 'dict:btn_edit_dict_command': + key = 'dict_admin_command' + elif widget.name == 'dict:btn_add_word_command': + key = 'add_word_command' + else: + return + command = self.prefs.get_value('common', key) + os.spawnl(os.P_NOWAIT, *command) + + def on_btn_dict_add_clicked(self, widget): + file = None + id = None + + if widget.name == "dict:btn_add": + dlg = gtk.FileChooserDialog(title=_("Open Dictionary File"), + parent=self.xml.get_widget('main'), + action=gtk.FILE_CHOOSER_ACTION_OPEN, + buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, + gtk.STOCK_OPEN, gtk.RESPONSE_OK)) + if widget.name == "dict:btn_edit": + dlg = gtk.Dialog(title=_("Edit Dictionary File"), + parent=self.xml.get_widget('main'), + flags='modal', + buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, + gtk.STOCK_OK, gtk.RESPONSE_OK)) + + vbox = self.xml.get_widget('dict:add_extra_vbox') + if widget.name == "dict:btn_add": + # Need to init for the second time + self.__init_dict_chooser_dialog() + dlg.set_extra_widget(vbox) + if widget.name == "dict:btn_edit": + id = self.__set_selected_dict_to_dialog() + if id == None: + self.__run_message_dialog(_("Your choosed file is not correct."), + gtk.MESSAGE_ERROR) + return + parent_vbox = dlg.vbox + parent_vbox.add(vbox) + vbox.show_all() + + if dlg.run() == gtk.RESPONSE_OK: + if widget.name == "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 widget.name == "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.xml.get_widget('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.MESSAGE_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.xml.get_widget('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.MESSAGE_ERROR) + return + if not path.exists(dict_file): + self.__run_message_dialog(_("Your file does not exist."), + gtk.MESSAGE_ERROR) + return + + if dict_file == None: + return + + 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(file(dict_file)): + if nline >= 0 and i >= nline: + break; + lines = lines + line + if encoding != None and encoding != 'utf-8': + lines = unicode(lines, encoding).encode('utf-8') + + dlg = gtk.Dialog(title=_("View Dictionary File"), + parent=self.xml.get_widget('main'), + flags='modal', + buttons=(gtk.STOCK_OK, gtk.RESPONSE_OK)) + buffer = gtk.TextBuffer() + buffer.set_text (lines) + text_view = gtk.TextView(buffer) + text_view.set_editable(False) + sw = gtk.ScrolledWindow() + sw.add(text_view) + 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.xml.get_widget('dict:view').get_selection().get_selected() + + if not it: + return + selected_path = l.get_path(it) + selected_id = l.get_value(it, 0) + + if widget.name == "dict:btn_up": + if selected_path[0] <= 0: + return + next_path = (selected_path[0] - 1, ) + elif widget.name == "dict:btn_down": + if selected_path[0] + 1 >= len(l): + return + next_path = (selected_path[0] + 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 widget.name == "dict:btn_up": + if i <= 0: + return + next_i = i - 1 + elif widget.name == "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.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() @@ -300,6 +800,30 @@ class AnthySetup(object): widget.response(gtk.RESPONSE_OK) return True + 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 widget.name == 'dict:entry_edit_dict_command': + key = 'dict_admin_command' + elif widget.name == 'dict:entry_add_word_command': + key = 'add_word_command' + else: + return + self.prefs.set_value('common', key, list) + self.xml.get_widget('btn_apply').set_sensitive(True) + def on_entry2_changed(self, widget): if not widget.get_text(): self.xml.get_widget('button4').set_sensitive(False) diff --git a/setup/prefs.py b/setup/prefs.py index 0b342d4..f3f0781 100644 --- a/setup/prefs.py +++ b/setup/prefs.py @@ -41,6 +41,12 @@ class Prefs(object): def sections(self): return 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] diff --git a/setup/setup.glade b/setup/setup.glade index 39fc754..d44d7fb 100644 --- a/setup/setup.glade +++ b/setup/setup.glade @@ -460,7 +460,7 @@ Hold <property name="visible">True</property> <property name="spacing">8</property> <child> - <widget class="GtkLabel" id="label5"> + <widget class="GtkLabel" id="label6"> <property name="visible">True</property> <property name="label" translatable="yes">_Shortcut Type:</property> <property name="use_underline">True</property> @@ -979,6 +979,341 @@ FMV KB611 key extension</property> </packing> </child> <child> + <widget class="GtkVBox" id="vbox4"> + <property name="visible">True</property> + <property name="border_width">4</property> + <property name="spacing">4</property> + <child> + <widget class="GtkFrame" id="frame5"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="shadow_type">none</property> + <child> + <widget class="GtkAlignment" id="alignment6"> + <property name="visible">True</property> + <property name="top_padding">4</property> + <property name="left_padding">0</property> + <child> + <widget class="GtkVBox" id="vbox5"> + <property name="visible">True</property> + <property name="border_width">4</property> + <property name="spacing">4</property> + <child> + <widget class="GtkTable" id="table6"> + <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> + <widget class="GtkLabel" id="label36"> + <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> + </widget> + <packing> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget 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 name="changed" handler="on_entry_dict_command_changed"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + </packing> + </child> + <child> + <widget 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 name="clicked" handler="on_btn_dict_command_clicked"/> + </widget> + <packing> + <property name="left_attach">2</property> + <property name="right_attach">3</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label37"> + <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> + </widget> + <packing> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + </packing> + </child> + <child> + <widget 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 name="changed" handler="on_entry_dict_command_changed"/> + </widget> + <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> + <child> + <widget 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 name="clicked" handler="on_btn_dict_command_clicked"/> + </widget> + <packing> + <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> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkLabel" id="label38"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Default Dictionary Configuration</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkFrame" id="frame6"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="shadow_type">none</property> + <child> + <widget class="GtkAlignment" id="alignment7"> + <property name="visible">True</property> + <property name="top_padding">4</property> + <property name="left_padding">0</property> + <child> + <widget class="GtkVBox" id="vbox6"> + <property name="visible">True</property> + <property name="border_width">4</property> + <property name="spacing">4</property> + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow2"> + <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> + <widget class="GtkTreeView" id="dict:view"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <signal name="button_press_event" handler="on_shortcut_click_event"/> + <signal name="button_release_event" handler="on_shortcut_click_event"/> + <signal name="key_release_event" handler="on_shortcut_key_release_event"/> + </widget> + </child> + </widget> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkHButtonBox" id="hbuttonbox2"> + <property name="visible">True</property> + <property name="spacing">4</property> + <property name="layout_style">end</property> + <child> + <widget 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 name="clicked" handler="on_btn_dict_view_clicked"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget 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 name="clicked" handler="on_btn_dict_add_clicked"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget 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 name="clicked" handler="on_btn_dict_add_clicked"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + <child> + <widget 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 name="clicked" handler="on_btn_dict_delete_clicked"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">3</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkHButtonBox" id="hbuttonbox2"> + <property name="visible">True</property> + <property name="spacing">4</property> + <property name="layout_style">end</property> + <child> + <widget 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 name="clicked" handler="on_btn_dict_order_clicked"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget 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 name="clicked" handler="on_btn_dict_order_clicked"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkLabel" id="label39"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Extended Dictionaries</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">3</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label4"> + <property name="visible">True</property> + <property name="label" translatable="yes">Dictionar_y</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">vbox4</property> + </widget> + <packing> + <property name="position">3</property> + <property name="tab_fill">False</property> + <property name="type">tab</property> + </packing> + </child> + <child> <widget class="GtkLabel" id="about"> <property name="visible">True</property> <property name="label" translatable="yes"><span size='xx-large'><b>IBus-Anthy</b></span> @@ -993,18 +1328,18 @@ URL : http://code.google.com/p/ibus/ <property name="ellipsize">start</property> </widget> <packing> - <property name="position">3</property> + <property name="position">4</property> </packing> </child> <child> - <widget class="GtkLabel" id="label4"> + <widget class="GtkLabel" id="label5"> <property name="visible">True</property> <property name="label" translatable="yes">Abo_ut</property> <property name="use_underline">True</property> <property name="mnemonic_widget">about</property> </widget> <packing> - <property name="position">3</property> + <property name="position">4</property> <property name="tab_fill">False</property> <property name="type">tab</property> </packing> @@ -1090,12 +1425,12 @@ URL : http://code.google.com/p/ibus/ <widget class="GtkVBox" id="dialog-vbox2"> <property name="visible">True</property> <child> - <widget class="GtkVBox" id="vbox3"> + <widget class="GtkVBox" id="vbox20"> <property name="visible">True</property> <property name="border_width">5</property> <property name="spacing">6</property> <child> - <widget class="GtkScrolledWindow" id="scrolledwindow2"> + <widget class="GtkScrolledWindow" id="scrolledwindow3"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="border_width">1</property> @@ -1231,7 +1566,7 @@ URL : http://code.google.com/p/ibus/ </packing> </child> <child> - <widget class="GtkHButtonBox" id="hbuttonbox2"> + <widget class="GtkHButtonBox" id="hbuttonbox3"> <property name="visible">True</property> <property name="spacing">6</property> <property name="layout_style">end</property> @@ -1484,4 +1819,123 @@ URL : http://code.google.com/p/ibus/ </widget> </child> </widget> + <widget 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> + <widget class="GtkTable" id="table10"> + <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> + <widget class="GtkLabel" id="label60"> + <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> + </widget> + <packing> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget 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> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label61"> + <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> + </widget> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="dict:long_entry"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">True</property> + </widget> + <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> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget 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">False</property> + <property name="receives_default">False</property> + <property name="use_underline">True</property> + <property name="draw_indicator">True</property> + <property name="active">True</property> + <accelerator key="U" signal="grab_focus" modifiers="GDK_MOD1_MASK"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget 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">False</property> + <property name="receives_default">False</property> + <property name="use_underline">True</property> + <property name="draw_indicator">True</property> + <accelerator key="E" signal="grab_focus" modifiers="GDK_MOD1_MASK"/> + </widget> + <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. --> + <widget class="GtkCheckButton" id="dict:reverse"> + <property name="label" translatable="yes">Enable the _reverse conversion</property> + <property name="visible">False</property> + <property name="can_focus">False</property> + <property name="receives_default">False</property> + <property name="use_underline">True</property> + <property name="draw_indicator">True</property> + <accelerator key="R" signal="grab_focus" modifiers="GDK_MOD1_MASK"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">3</property> + </packing> + </child> + </widget> </glade-interface> |