Skip to content

Commit

Permalink
Implement dynamic status update of the dictionaries
Browse files Browse the repository at this point in the history
  • Loading branch information
user202729 committed Jul 17, 2023
1 parent 78f5020 commit 97a84ab
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 26 deletions.
24 changes: 19 additions & 5 deletions plover/dictionary/loading_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,20 @@
import time

from plover.dictionary.base import load_dictionary
from plover.exception import DictionaryLoaderException
from plover.resource import resource_timestamp
from plover import log


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 StenoDictionary object
(or an instance of ErroredDictionary if the load fails).
"""
self._state_change_callback = state_change_callback
self.dictionaries = {}

def __len__(self):
Expand All @@ -31,7 +37,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

Expand All @@ -54,7 +60,14 @@ 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 StenoDictionary object
(or an instance of ErroredDictionary 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
Expand Down Expand Up @@ -89,8 +102,9 @@ def load(self):
self.result = load_dictionary(self.filename)
except Exception as e:
log.debug('loading dictionary %s failed', self.filename, exc_info=True)
self.result = DictionaryLoaderException(self.filename, e)
self.result = ErroredDictionary(self.filename, e)
self.result.timestamp = timestamp
self._state_change_callback(self.filename, self.result)

def get(self):
self.loading_thread.join()
Expand Down
16 changes: 7 additions & 9 deletions plover/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
from collections import namedtuple, OrderedDict
from functools import wraps
from queue import Queue
import functools
import os
import shutil
import threading

from plover import log, system
from plover.dictionary.loading_manager import DictionaryLoadingManager
from plover.exception import DictionaryLoaderException
from plover.formatting import Formatter
from plover.misc import shorten_path
from plover.registry import registry
Expand Down Expand Up @@ -84,6 +84,7 @@ class StenoEngine:
output_changed
config_changed
dictionaries_loaded
dictionary_state_changed
send_string
send_backspaces
send_key_combination
Expand Down Expand Up @@ -116,7 +117,7 @@ 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._translator.clear_state()
self._keyboard_emulation = keyboard_emulation
Expand Down Expand Up @@ -271,15 +272,12 @@ def _update(self, config_update=None, full=False, reset_machine=False):
])
# And then (re)load all dictionaries.
dictionaries = []
for result in self._dictionaries_manager.load(config_dictionaries.keys()):
if isinstance(result, DictionaryLoaderException):
d = ErroredDictionary(result.path, result.exception)
for d in self._dictionaries_manager.load(config_dictionaries.keys()):
if isinstance(d, ErroredDictionary):
# Only show an error if it's new.
if d != self._dictionaries.get(result.path):
if d != self._dictionaries.get(d.path):
log.error('loading dictionary `%s` failed: %s',
shorten_path(result.path), str(result.exception))
else:
d = result
shorten_path(d.path), str(d.exception))
d.enabled = config_dictionaries[d.path].enabled
dictionaries.append(d)
self._set_dictionaries(dictionaries)
Expand Down
11 changes: 0 additions & 11 deletions plover/exception.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,3 @@
class InvalidConfigurationError(Exception):
"Raised when there is something wrong in the configuration."
pass

class DictionaryLoaderException(Exception):
"""Dictionary file could not be loaded."""

def __init__(self, path, exception):
super().__init__(path, exception)
self.path = path
self.exception = exception

def __str__(self):
return 'loading dictionary `%s` failed: %s' % (self.path, self.exception)
9 changes: 9 additions & 0 deletions plover/gui_qt/dictionaries_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
)

from plover import _
from plover.steno_dictionary import StenoDictionary
from plover.config import DictionaryConfig
from plover.dictionary.base import create_dictionary
from plover.engine import ErroredDictionary
Expand Down Expand Up @@ -118,6 +119,7 @@ def __init__(self, engine, icons, max_undo=20):
config = engine.config
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)
self._reset_items(config['dictionaries'],
config['classic_dictionaries_display_order'],
backup=False, publish=False)
Expand Down Expand Up @@ -237,6 +239,13 @@ def _on_dictionaries_loaded(self, loaded_dictionaries):
updated_rows.update(self._update_favorite())
self._updated_rows(updated_rows)

def _on_dictionary_state_changed(self, filename, d):
[item] = [item for item in self._from_row if item.path == filename]
# item is of type DictionaryItem
if item.loaded != d:
item.loaded = d
self._updated_rows([item.row])

def _move(self, index_list, step):
row_list = sorted(self._normalized_row_list(index_list))
if not row_list:
Expand Down
4 changes: 3 additions & 1 deletion plover/gui_qt/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@
class Engine(StenoEngine, QThread):

# Signals.
# Each signal is emitted when the correspondingly-named hook in the engine is triggered.
signal_stroked = pyqtSignal(QVariant)
signal_translated = pyqtSignal(QVariant, QVariant)
signal_machine_state_changed = pyqtSignal(str, str)
signal_output_changed = pyqtSignal(bool)
signal_config_changed = pyqtSignal(QVariant)
signal_dictionaries_loaded = pyqtSignal(QVariant)
signal_dictionary_state_changed = pyqtSignal(str, QVariant) # Some dictionary has finished loading. Refer to class DictionaryLoadingManager for argument description.
signal_dictionaries_loaded = pyqtSignal(QVariant) # All dictionaries are loaded. Argument is a StenoDictionaryCollection instance.
signal_send_string = pyqtSignal(str)
signal_send_backspaces = pyqtSignal(int)
signal_send_key_combination = pyqtSignal(str)
Expand Down

0 comments on commit 97a84ab

Please sign in to comment.