diff --git a/plover/dictionary/loading_manager.py b/plover/dictionary/loading_manager.py index f177752da..a83936be6 100644 --- a/plover/dictionary/loading_manager.py +++ b/plover/dictionary/loading_manager.py @@ -14,7 +14,15 @@ class DictionaryLoadingManager: - def __init__(self): + def __init__(self, state_change_callback): + """ + Parameters: + + state_change_callback -- A function that will be called when any dictionary is loaded + with two parameters: the filename and the loaded dictionary object + (or an instance of DictionaryLoaderException if the load fails). + """ + self._state_change_callback = state_change_callback self.dictionaries = {} def __len__(self): @@ -31,7 +39,7 @@ def start_loading(self, filename): if op is not None and not op.needs_reloading(): return op log.info('%s dictionary: %s', 'loading' if op is None else 'reloading', filename) - op = DictionaryLoadingOperation(filename) + op = DictionaryLoadingOperation(filename, self._state_change_callback) self.dictionaries[filename] = op return op @@ -54,7 +62,15 @@ def load(self, filenames): class DictionaryLoadingOperation: - def __init__(self, filename): + def __init__(self, filename, state_change_callback): + """ + Parameters: + + state_change_callback -- A function that will be called when the load is finished + with two parameters: the filename and the loaded dictionary object + (or an instance of DictionaryLoaderException if the load fails). + """ + self._state_change_callback = state_change_callback self.loading_thread = threading.Thread(target=self.load) self.filename = filename self.result = None @@ -91,6 +107,7 @@ def load(self): log.debug('loading dictionary %s failed', self.filename, exc_info=True) self.result = DictionaryLoaderException(self.filename, e) self.result.timestamp = timestamp + self._state_change_callback(self.filename, self.result) def get(self): self.loading_thread.join() diff --git a/plover/engine.py b/plover/engine.py index 1b77dba87..ee0cdacf0 100644 --- a/plover/engine.py +++ b/plover/engine.py @@ -2,6 +2,7 @@ from collections import namedtuple, OrderedDict from functools import wraps from queue import Queue +import functools import os import shutil import threading @@ -81,6 +82,7 @@ class StenoEngine: output_changed config_changed dictionaries_loaded + dictionary_state_changed send_string send_backspaces send_key_combination @@ -113,7 +115,8 @@ def __init__(self, config, controller, keyboard_emulation): self._translator.add_listener(log.translation) self._translator.add_listener(self._formatter.format) self._dictionaries = self._translator.get_dictionary() - self._dictionaries_manager = DictionaryLoadingManager() + self._dictionaries_manager = DictionaryLoadingManager( + functools.partial(self._trigger_hook, "dictionary_state_changed")) self._running_state = self._translator.get_state() self._keyboard_emulation = keyboard_emulation self._hooks = { hook: [] for hook in self.HOOKS } diff --git a/plover/gui_qt/dictionaries_widget.py b/plover/gui_qt/dictionaries_widget.py index 94f29eac9..9bca2b758 100644 --- a/plover/gui_qt/dictionaries_widget.py +++ b/plover/gui_qt/dictionaries_widget.py @@ -25,6 +25,7 @@ from plover.misc import normalize_path from plover.oslayer.config import CONFIG_DIR from plover.registry import registry +from plover.exception import DictionaryLoaderException from plover.gui_qt.dictionaries_widget_ui import Ui_DictionariesWidget from plover.gui_qt.dictionary_editor import DictionaryEditor @@ -127,10 +128,32 @@ def __init__(self, *args, **kwargs): self.table.dropEvent = self._drop_event engine.signal_connect('config_changed', self.on_config_changed) engine.signal_connect('dictionaries_loaded', self.on_dictionaries_loaded) + engine.signal_connect('dictionary_state_changed', self.on_dictionary_state_changed) def setFocus(self): self.table.setFocus() + def on_dictionary_state_changed(self, filename, d): + config_dictionaries = self._config_dictionaries + [n] = [n for n, dictionary in enumerate(config_dictionaries) if dictionary.path == filename] + assert self.table.rowCount() == len(config_dictionaries) + row = n + if self._reverse_order: + row = len(config_dictionaries) - row - 1 + if isinstance(d, DictionaryLoaderException): + icon = 'error' + tooltip = str(d.exception) + elif d.readonly: + icon = 'readonly' + # i18n: Widget: “DictionariesWidget”, tooltip. + tooltip = _('This dictionary is read-only.') + else: + icon = 'normal' + tooltip = '' + item = self.table.verticalHeaderItem(row) + item.setIcon(QIcon(':/dictionary_%s.svg' % icon)) + item.setToolTip(tooltip) + def on_dictionaries_loaded(self, loaded_dictionaries): self._update_dictionaries(loaded_dictionaries=loaded_dictionaries, record=False, save=False) diff --git a/plover/gui_qt/engine.py b/plover/gui_qt/engine.py index 1c2d338c5..7da3a1d63 100644 --- a/plover/gui_qt/engine.py +++ b/plover/gui_qt/engine.py @@ -16,6 +16,7 @@ class Engine(StenoEngine, QThread): signal_machine_state_changed = pyqtSignal(str, str) signal_output_changed = pyqtSignal(bool) signal_config_changed = pyqtSignal(QVariant) + signal_dictionary_state_changed = pyqtSignal(str, QVariant) signal_dictionaries_loaded = pyqtSignal(QVariant) signal_send_string = pyqtSignal(str) signal_send_backspaces = pyqtSignal(int)