def on_strokes_edited(self): mapping_is_valid = self.strokes.hasAcceptableInput() if mapping_is_valid != self._mapping_is_valid: self._mapping_is_valid = mapping_is_valid self.mappingValid.emit(mapping_is_valid) if not mapping_is_valid: return strokes = self._strokes() if strokes: translations = self._engine.raw_lookup_from_all(strokes) if translations: # i18n: Widget: “AddTranslationWidget”. info = self._format_label(_('{strokes} maps to '), (strokes,)) entries = [ self._format_label( ('• ' if i else '') + '<bf>{translation}<bf/>\t({filename})', None, translation, os_path_split(resource_filename(dictionary.path))[1] ) for i, (translation, dictionary) in enumerate(translations) ] if (len(entries) > 1): # i18n: Widget: “AddTranslationWidget”. entries.insert(1, '<br />' + _('Overwritten entries:')) info += '<br />'.join(entries) else: info = self._format_label( # i18n: Widget: “AddTranslationWidget”. _('{strokes} is not mapped in any dictionary'), (strokes, ) ) else: info = '' self.strokes_info.setText(info)
def _update_strokes(self): strokes = self._strokes() if strokes: translations = self._engine.raw_lookup_from_all(strokes) if translations: # i18n: Widget: “AddTranslationWidget”. info = self._format_label(_('{strokes} maps to '), (strokes, )) entries = [ self._format_label( ('• ' if i else '') + '<bf>{translation}<bf/>\t({filename})', None, translation, os_path_split(resource_filename(dictionary.path))[1]) for i, (translation, dictionary) in enumerate(translations) ] if (len(entries) > 1): # i18n: Widget: “AddTranslationWidget”. entries.insert(1, '<br />' + _('Overwritten entries:')) info += '<br />'.join(entries) else: info = self._format_label( # i18n: Widget: “AddTranslationWidget”. _('{strokes} is not mapped in any dictionary'), (strokes, )) else: info = '' self.strokes_info.setText(info)
def load(cls, resource): filename = resource_filename(resource) timestamp = resource_timestamp(filename) d = cls() d._load(filename) if resource.startswith(ASSET_SCHEME): d.readonly = True d.path = resource d.timestamp = timestamp return d
def save(self): assert not self.readonly filename = resource_filename(self.path) # Write the new file to a temp location. tmp = filename + '.tmp' self._save(tmp) timestamp = resource_timestamp(tmp) # Then move the new file to the final location. shutil.move(tmp, filename) # And update our timestamp. self.timestamp = timestamp
def load(cls, resource): filename = resource_filename(resource) timestamp = resource_timestamp(filename) d = cls() d._load(filename) if (cls.readonly or resource.startswith(ASSET_SCHEME) or not os.access(filename, os.W_OK)): d.readonly = True d.path = resource d.timestamp = timestamp return d
def _load_wordlist(filename, assets_dir): if filename is None: return {} path = None for directory in (CONFIG_DIR, assets_dir): if directory is None: continue path = os.path.join(resource_filename(directory), filename) if os.path.exists(path): break else: return {} words = {} with open(path, encoding='utf-8') as f: pairs = [word.strip().rsplit(' ', 1) for word in f] pairs.sort(reverse=True, key=lambda x: int(x[1])) words = {p[0]: int(p[1]) for p in pairs} return words
def _load_wordlist(filename, assets_dir): if filename is None: return {} path = None for directory in (CONFIG_DIR, assets_dir): if directory is None: continue path = os.path.join(resource_filename(directory), filename) if os.path.exists(path): break else: return {} with open(path, encoding='utf-8') as f: text = f.read() fields = text.split() it = iter(fields) words = dict(zip(it, map(int, it))) assert len(fields) == 2 * len(words), path + ' contains duplicate words.' return words
def copy_default_dictionaries(dictionaries_files): '''Recreate default dictionaries. Each default dictionary is recreated if it's in use by the current config and missing. ''' for dictionary in dictionaries_files: # Ignore assets. if dictionary.startswith(ASSET_SCHEME): continue # Nothing to do if dictionary file already exists. if os.path.exists(dictionary): continue # Check it's actually a default dictionary. basename = os.path.basename(dictionary) if basename not in system.DEFAULT_DICTIONARIES: continue default_dictionary = os.path.join(system.DICTIONARIES_ROOT, basename) log.info('recreating %s from %s', dictionary, default_dictionary) shutil.copyfile(resource_filename(default_dictionary), dictionary)
def __init__(self, engine, use_qt_notifications): super(MainWindow, self).__init__() self.setupUi(self) if hasattr(self, 'setUnifiedTitleAndToolBarOnMac'): self.setUnifiedTitleAndToolBarOnMac(True) self._engine = engine self._active_dialogs = {} self._dialog_class = { 'about' : AboutDialog, 'configuration' : ConfigWindow, } all_actions = find_menu_actions(self.menubar) # Dictionaries. self.dictionaries = DictionariesWidget(engine) self.dictionaries.add_translation.connect(self._add_translation) self.scroll_area.setWidget(self.dictionaries) self.dictionaries.setFocus() edit_menu = all_actions['menu_Edit'].menu() edit_menu.addAction(self.dictionaries.action_Undo) edit_menu.addSeparator() edit_menu.addAction(self.dictionaries.action_AddDictionaries) edit_menu.addAction(self.dictionaries.action_EditDictionaries) edit_menu.addAction(self.dictionaries.action_RemoveDictionaries) edit_menu.addSeparator() edit_menu.addAction(self.dictionaries.action_MoveDictionariesUp) edit_menu.addAction(self.dictionaries.action_MoveDictionariesDown) # Tray icon. self._trayicon = TrayIcon() self._trayicon.enable() self._trayicon.clicked.connect(self._engine.toggle_output) if use_qt_notifications: handler = NotificationHandler() handler.emitSignal.connect(self._trayicon.log) log.add_handler(handler) popup_menu = QMenu() for action_name in ( 'action_ToggleOutput', 'action_Reconnect', '', 'menu_Tools', '', 'action_Configure', '', 'menu_Help', '', 'action_Show', 'action_Quit', ): if action_name: popup_menu.addAction(all_actions[action_name]) else: popup_menu.addSeparator() self._trayicon.set_menu(popup_menu) engine.signal_connect('machine_state_changed', self._trayicon.update_machine_state) engine.signal_connect('quit', self.on_quit) self.action_Quit.triggered.connect(engine.quit) # Populate tools bar/menu. tools_menu = all_actions['menu_Tools'].menu() # Toolbar popup menu for selecting which tools are shown. self.toolbar_menu = QMenu() self.toolbar.setContextMenuPolicy(Qt.CustomContextMenu) self.toolbar.customContextMenuRequested.connect( lambda: self.toolbar_menu.popup(QCursor.pos()) ) for tool_plugin in registry.list_plugins('gui.qt.tool'): tool = tool_plugin.obj action_parameters = [] if tool.ICON is not None: icon = tool.ICON # Internal QT resources start with a `:`. if not icon.startswith(':'): icon = resource_filename(icon) action_parameters.append(QIcon(icon)) action_parameters.append(tool.TITLE) toolbar_action = None for parent in (tools_menu, self.toolbar, self.toolbar_menu): action = parent.addAction(*action_parameters) action.setObjectName(tool_plugin.name) if tool.__doc__ is not None: action.setToolTip(tool.__doc__) if tool.SHORTCUT is not None: action.setShortcut(QKeySequence.fromString(tool.SHORTCUT)) if parent == self.toolbar_menu: action.setCheckable(True) action.setChecked(True) assert toolbar_action is not None action.toggled.connect(toolbar_action.setVisible) else: if parent == self.toolbar: toolbar_action = action action.triggered.connect(partial(self._activate_dialog, tool_plugin.name, args=())) self._dialog_class[tool_plugin.name] = tool engine.signal_connect('output_changed', self.on_output_changed) # Machine. self.machine_type.addItems( _(plugin.name) for plugin in registry.list_plugins('machine') ) engine.signal_connect('config_changed', self.on_config_changed) engine.signal_connect('machine_state_changed', lambda machine, state: self.machine_state.setText(_(state.capitalize())) ) self.restore_state() # Commands. engine.signal_connect('add_translation', partial(self._add_translation, manage_windows=True)) engine.signal_connect('focus', self._focus) engine.signal_connect('configure', partial(self._configure, manage_windows=True)) engine.signal_connect('lookup', partial(self._activate_dialog, 'lookup', manage_windows=True)) # Load the configuration (but do not start the engine yet). if not engine.load_config(): self.on_configure() # Apply configuration settings. config = self._engine.config self.machine_type.setCurrentText(config['machine_type']) self._configured = False self.dictionaries.on_config_changed(config) self.set_visible(not config['start_minimized']) # Start the engine. engine.start()
def __init__(self, engine, use_qt_notifications): super(MainWindow, self).__init__() self.setupUi(self) if hasattr(self, 'setUnifiedTitleAndToolBarOnMac'): self.setUnifiedTitleAndToolBarOnMac(True) self._engine = engine self._active_dialogs = {} self._dialog_class = { 'about' : AboutDialog, 'configuration' : ConfigWindow, } all_actions = find_menu_actions(self.menubar) # Dictionaries. self.dictionaries = self.scroll_area.widget() self.dictionaries.add_translation.connect(self._add_translation) self.dictionaries.setFocus() edit_menu = all_actions['menu_Edit'].menu() edit_menu.addAction(self.dictionaries.action_Undo) edit_menu.addSeparator() edit_menu.addMenu(self.dictionaries.menu_AddDictionaries) edit_menu.addAction(self.dictionaries.action_EditDictionaries) edit_menu.addAction(self.dictionaries.action_RemoveDictionaries) edit_menu.addSeparator() edit_menu.addAction(self.dictionaries.action_MoveDictionariesUp) edit_menu.addAction(self.dictionaries.action_MoveDictionariesDown) # Tray icon. self._trayicon = TrayIcon() self._trayicon.enable() self._trayicon.clicked.connect(self._engine.toggle_output) if use_qt_notifications: handler = NotificationHandler() handler.emitSignal.connect(self._trayicon.log) log.add_handler(handler) popup_menu = QMenu() for action_name in ( 'action_ToggleOutput', 'action_Reconnect', '', 'menu_Tools', '', 'action_Configure', '', 'menu_Help', '', 'action_Show', 'action_Quit', ): if action_name: popup_menu.addAction(all_actions[action_name]) else: popup_menu.addSeparator() self._trayicon.set_menu(popup_menu) engine.signal_connect('machine_state_changed', self._trayicon.update_machine_state) engine.signal_connect('quit', self.on_quit) self.action_Quit.triggered.connect(engine.quit) # Populate tools bar/menu. tools_menu = all_actions['menu_Tools'].menu() # Toolbar popup menu for selecting which tools are shown. self.toolbar_menu = QMenu() self.toolbar.setContextMenuPolicy(Qt.CustomContextMenu) self.toolbar.customContextMenuRequested.connect( lambda: self.toolbar_menu.popup(QCursor.pos()) ) for tool_plugin in registry.list_plugins('gui.qt.tool'): tool = tool_plugin.obj action_parameters = [] if tool.ICON is not None: icon = tool.ICON # Internal QT resources start with a `:`. if not icon.startswith(':'): icon = resource_filename(icon) action_parameters.append(QIcon(icon)) action_parameters.append(tool.TITLE) toolbar_action = None for parent in (tools_menu, self.toolbar, self.toolbar_menu): action = parent.addAction(*action_parameters) action.setObjectName(tool_plugin.name) if tool.__doc__ is not None: action.setToolTip(tool.__doc__) if tool.SHORTCUT is not None: action.setShortcut(QKeySequence.fromString(tool.SHORTCUT)) if parent == self.toolbar_menu: action.setCheckable(True) action.setChecked(True) assert toolbar_action is not None action.toggled.connect(toolbar_action.setVisible) else: if parent == self.toolbar: toolbar_action = action action.triggered.connect(partial(self._activate_dialog, tool_plugin.name, args=())) self._dialog_class[tool_plugin.name] = tool engine.signal_connect('output_changed', self.on_output_changed) # Machine. self.machine_type.addItems( _(plugin.name) for plugin in registry.list_plugins('machine') ) engine.signal_connect('config_changed', self.on_config_changed) engine.signal_connect('machine_state_changed', lambda machine, state: self.machine_state.setText(_(state.capitalize())) ) self.restore_state() # Commands. engine.signal_connect('add_translation', partial(self._add_translation, manage_windows=True)) engine.signal_connect('focus', self._focus) engine.signal_connect('configure', partial(self._configure, manage_windows=True)) engine.signal_connect('lookup', partial(self._activate_dialog, 'lookup', manage_windows=True)) # Load the configuration (but do not start the engine yet). if not engine.load_config(): self.on_configure() # Apply configuration settings. config = self._engine.config self.machine_type.setCurrentText(config['machine_type']) self._configured = False self.dictionaries.on_config_changed(config) self.set_visible(not config['start_minimized']) # Start the engine. engine.start()
def __init__(self, engine, use_qt_notifications): super().__init__() self.setupUi(self) if hasattr(self, 'setUnifiedTitleAndToolBarOnMac'): self.setUnifiedTitleAndToolBarOnMac(True) self._engine = engine self._active_dialogs = {} self._dialog_class = { 'about': AboutDialog, 'configuration': ConfigWindow, } all_actions = find_menu_actions(self.menubar) # Dictionaries. self.dictionaries.add_translation.connect(self._add_translation) self.dictionaries.setup(engine) # Populate edit menu from dictionaries' own. edit_menu = all_actions['menu_Edit'].menu() for action in self.dictionaries.edit_menu.actions(): edit_menu.addAction(action) # Tray icon. self._trayicon = TrayIcon() self._trayicon.enable() self._trayicon.clicked.connect(self._engine.toggle_output) if use_qt_notifications: handler = NotificationHandler() handler.emitSignal.connect(self._trayicon.log) log.add_handler(handler) popup_menu = QMenu() for action_name in ( 'action_ToggleOutput', 'action_Reconnect', '', 'menu_Tools', '', 'action_Configure', 'action_OpenConfigFolder', '', 'menu_Help', '', 'action_Show', 'action_Quit', ): if action_name: popup_menu.addAction(all_actions[action_name]) else: popup_menu.addSeparator() self._trayicon.set_menu(popup_menu) engine.signal_connect('machine_state_changed', self._trayicon.update_machine_state) engine.signal_connect('quit', self.on_quit) self.action_Quit.triggered.connect(engine.quit) # Toolbar popup menu for selecting which tools are shown. self.toolbar_menu = QMenu() self.toolbar.setContextMenuPolicy(Qt.CustomContextMenu) self.toolbar.customContextMenuRequested.connect( lambda: self.toolbar_menu.popup(QCursor.pos())) # Populate tools bar/menu. tools_menu = all_actions['menu_Tools'].menu() for tool_plugin in registry.list_plugins('gui.qt.tool'): tool = tool_plugin.obj menu_action = tools_menu.addAction(tool.TITLE) if tool.SHORTCUT is not None: menu_action.setShortcut(QKeySequence.fromString(tool.SHORTCUT)) if tool.ICON is not None: icon = tool.ICON # Internal QT resources start with a `:`. if not icon.startswith(':'): icon = resource_filename(icon) menu_action.setIcon(QIcon(icon)) menu_action.triggered.connect( partial(self._activate_dialog, tool_plugin.name, args=())) toolbar_action = self.toolbar.addAction(menu_action.icon(), menu_action.text()) if tool.__doc__ is not None: toolbar_action.setToolTip(tool.__doc__) toolbar_action.triggered.connect(menu_action.trigger) toggle_action = self.toolbar_menu.addAction( menu_action.icon(), menu_action.text()) toggle_action.setObjectName(tool_plugin.name) toggle_action.setCheckable(True) toggle_action.setChecked(True) toggle_action.toggled.connect(toolbar_action.setVisible) self._dialog_class[tool_plugin.name] = tool engine.signal_connect('output_changed', self.on_output_changed) # Machine. for plugin in registry.list_plugins('machine'): self.machine_type.addItem(_(plugin.name), plugin.name) engine.signal_connect('config_changed', self.on_config_changed) engine.signal_connect( 'machine_state_changed', lambda machine, state: self.machine_state.setText(state.capitalize( ))) self.restore_state() # Commands. engine.signal_connect( 'add_translation', partial(self._add_translation, manage_windows=True)) engine.signal_connect('focus', self._focus) engine.signal_connect('configure', partial(self._configure, manage_windows=True)) engine.signal_connect( 'lookup', partial(self._activate_dialog, 'lookup', manage_windows=True)) engine.signal_connect( 'suggestions', partial(self._activate_dialog, 'suggestions', manage_windows=True)) # Load the configuration (but do not start the engine yet). if not engine.load_config(): self.on_configure() # Apply configuration settings. config = self._engine.config self._warn_on_hide_to_tray = not config['start_minimized'] self._update_machine(config['machine_type']) self._configured = False self.set_visible(not config['start_minimized']) # Process events before starting the engine # (to avoid display lag at window creation). QCoreApplication.processEvents() # Start the engine. engine.start()