Exemplo n.º 1
0
    def __init__(self):
        """Creates and configures a single steno pipeline."""
        self.subscribers = []
        self.stroke_listeners = []
        self.is_running = False
        self.machine = None

        self.translator = translation.Translator()
        self.formatter = formatting.Formatter()
        self.logger = Logger()
        self.translator.add_listener(self.logger.log_translation)
        self.translator.add_listener(self.formatter.format)
        # This seems like a reasonable number. If this becomes a problem it can
        # be parameterized.
        self.translator.set_min_undo_length(10)

        self.full_output = SimpleNamespace()
        self.command_only_output = SimpleNamespace()
        self.running_state = self.translator.get_state()
        self.set_is_running(False)
Exemplo n.º 2
0
Arquivo: app.py Projeto: Mqrius/plover
    def __init__(self):
        """Creates and configures a single steno pipeline."""
        self.subscribers = []
        self.stroke_listeners = []
        self.is_running = False
        self.machine = None

        self.translator = translation.Translator()
        self.formatter = formatting.Formatter()
        self.logger = Logger()
        self.translator.add_listener(self.logger.log_translation)
        self.translator.add_listener(self.formatter.format)
        # This seems like a reasonable number. If this becomes a problem it can
        # be parameterized.
        self.translator.set_min_undo_length(10)

        self.full_output = SimpleNamespace()
        self.command_only_output = SimpleNamespace()
        self.running_state = self.translator.get_state()
        self.set_is_running(False)
Exemplo n.º 3
0
Arquivo: app.py Projeto: brentn/plover
class StenoEngine(object):
    """Top-level class for using a stenotype machine for text input.

    This class combines all the non-GUI pieces needed to use a stenotype machine
    as a general purpose text entry device. The pipeline consists of the 
    following elements:

    machine: An instance of the Stenotype class from one of the submodules of 
    plover.machine. This object is responsible for monitoring a particular type 
    of hardware for stenotype output and passing that output on to the 
    translator.

    translator: An instance of the plover.steno.Translator class. This object 
    converts raw steno keys into strokes and strokes into translations. The 
    translation objects are then passed on to the formatter.

    formatter: An instance of the plover.formatting.Formatter class. This object 
    converts translation objects into printable text that can be displayed to 
    the user. Orthographic and lexical rules, such as capitalization at the 
    beginning of a sentence and pluralizing a word, are taken care of here. The 
    formatted text is then passed on to the output.

    output: An instance of plover.oslayer.keyboardcontrol.KeyboardEmulation 
    class plus a hook to the application allows output to the screen and control
    of the app with steno strokes.

    In addition to the above pieces, a logger records timestamped strokes and
    translations.

    """

    def __init__(self, thread_hook=same_thread_hook):
        """Creates and configures a single steno pipeline."""
        self.subscribers = []
        self.stroke_listeners = []
        self.is_running = False
        self.machine = None
        self.thread_hook = thread_hook

        self.translator = translation.Translator()
        self.formatter = formatting.Formatter()
        self.logger = Logger()
        self.translator.add_listener(self.logger.log_translation)
        self.translator.add_listener(self.formatter.format)
        # This seems like a reasonable number. If this becomes a problem it can
        # be parameterized.
        self.translator.set_min_undo_length(10)

        self.full_output = SimpleNamespace()
        self.command_only_output = SimpleNamespace()
        self.running_state = self.translator.get_state()
        self.set_is_running(False)

    def set_machine(self, machine):
        if self.machine:
            self.machine.remove_state_callback(self._machine_state_callback)
            self.machine.remove_stroke_callback(
                self._translator_machine_callback)
            self.machine.remove_stroke_callback(self.logger.log_stroke)
            self.machine.stop_capture()
        self.machine = machine
        if self.machine:
            self.machine.add_state_callback(self._machine_state_callback)
            self.machine.add_stroke_callback(self.logger.log_stroke)
            self.machine.add_stroke_callback(self._translator_machine_callback)
            self.machine.start_capture()
            self.set_is_running(self.is_running)
        else:
            self.set_is_running(False)

    def set_dictionary(self, d):
        self.translator.set_dictionary(d)

    def get_dictionary(self):
        return self.translator.get_dictionary()

    def set_is_running(self, value):
        self.is_running = value
        if self.is_running:
            self.translator.set_state(self.running_state)
            self.formatter.set_output(self.full_output)
        else:
            self.translator.clear_state()
            self.formatter.set_output(self.command_only_output)
        if isinstance(self.machine, plover.machine.sidewinder.Stenotype):
            self.machine.suppress_keyboard(self.is_running)
        for callback in self.subscribers:
            callback(None)

    def set_output(self, o):
        self.full_output.send_backspaces = o.send_backspaces
        self.full_output.send_string = o.send_string
        self.full_output.send_key_combination = o.send_key_combination
        self.full_output.send_engine_command = o.send_engine_command
        self.command_only_output.send_engine_command = o.send_engine_command

    def destroy(self):
        """Halts the stenography capture-translate-format-display pipeline.

        Calling this method causes all worker threads involved to terminate.
        This method should be called at least once if the start method had been
        previously called. Calling this method more than once or before the
        start method has been called has no effect.

        """
        if self.machine:
            self.machine.stop_capture()
        self.is_running = False

    def add_callback(self, callback):
        """Subscribes a function to receive changes of the is_running state.

        Arguments:

        callback -- A function that takes no arguments.

        """
        self.subscribers.append(callback)
        
    def set_log_file_name(self, filename):
        """Set the file name for log output."""
        self.logger.set_filename(filename)

    def enable_stroke_logging(self, b):
        """Turn stroke logging on or off."""
        self.logger.enable_stroke_logging(b)

    def set_space_placement(self, s):
        """Set whether spaces will be inserted before the output or after the output."""
        self.formatter.set_space_placement(s)
        
    def enable_translation_logging(self, b):
        """Turn translation logging on or off."""
        self.logger.enable_translation_logging(b)

    def add_stroke_listener(self, listener):
        self.stroke_listeners.append(listener)

    def remove_stroke_listener(self, listener):
        self.stroke_listeners.remove(listener)

    def _translate_stroke(self, s):
        stroke = steno.Stroke(s)
        self.translator.translate(stroke)
        for listener in self.stroke_listeners:
            listener(stroke)

    def _translator_machine_callback(self, s):
        self.thread_hook(self._translate_stroke, s)

    def _notify_listeners(self, s):
        for callback in self.subscribers:
            callback(s)

    def _machine_state_callback(self, s):
        self.thread_hook(self._notify_listeners, s)
Exemplo n.º 4
0
 def setUp(self):
     self.patcher = patch('plover.logger.RotatingFileHandler', FakeHandler)
     self.patcher.start()
     self.logger = Logger()
Exemplo n.º 5
0
class LoggerTestCase(unittest.TestCase):
    def setUp(self):
        self.patcher = patch('plover.logger.RotatingFileHandler', FakeHandler)
        self.patcher.start()
        self.logger = Logger()

    def tearDown(self):
        self.logger.set_filename(None)
        self.patcher.stop()

    def test_set_filename(self):
        self.logger.set_filename('fn1')
        self.logger.enable_stroke_logging(True)
        self.logger.log_stroke(('S', ))
        self.logger.set_filename('fn2')
        self.logger.log_stroke(('T', ))
        self.logger.set_filename(None)
        self.logger.log_stroke(('P', ))
        self.assertEqual(FakeHandler.get_output(), {
            'fn1': ['Stroke(S)'],
            'fn2': ['Stroke(T)']
        })

    def test_log_stroke(self):
        self.logger.set_filename('fn')
        self.logger.enable_stroke_logging(True)
        self.logger.log_stroke(('ST', 'T'))
        self.assertEqual(FakeHandler.get_output(), {'fn': ['Stroke(ST T)']})

    def test_log_translation(self):
        self.logger.set_filename('fn')
        self.logger.enable_translation_logging(True)
        self.logger.log_translation(['a', 'b'], ['c', 'd'], None)
        self.assertEqual(FakeHandler.get_output(),
                         {'fn': ['*a', '*b', 'c', 'd']})

    def test_enable_stroke_logging(self):
        self.logger.set_filename('fn')
        self.logger.log_stroke(('a', ))
        self.logger.enable_stroke_logging(True)
        self.logger.log_stroke(('b', ))
        self.logger.enable_stroke_logging(False)
        self.logger.log_stroke(('c', ))
        self.assertEqual(FakeHandler.get_output(), {'fn': ['Stroke(b)']})

    def test_enable_translation_logging(self):
        self.logger.set_filename('fn')
        self.logger.log_translation(['a'], ['b'], None)
        self.logger.enable_translation_logging(True)
        self.logger.log_translation(['c'], ['d'], None)
        self.logger.enable_translation_logging(False)
        self.logger.log_translation(['e'], ['f'], None)
        self.assertEqual(FakeHandler.get_output(), {'fn': ['*c', 'd']})
Exemplo n.º 6
0
class StenoEngine(object):
    """Top-level class for using a stenotype machine for text input.

    This class combines all the non-GUI pieces needed to use a stenotype machine
    as a general purpose text entry device. The pipeline consists of the 
    following elements:

    machine: An instance of the Stenotype class from one of the submodules of 
    plover.machine. This object is responsible for monitoring a particular type 
    of hardware for stenotype output and passing that output on to the 
    translator.

    translator: An instance of the plover.steno.Translator class. This object 
    converts raw steno keys into strokes and strokes into translations. The 
    translation objects are then passed on to the formatter.

    formatter: An instance of the plover.formatting.Formatter class. This object 
    converts translation objects into printable text that can be displayed to 
    the user. Orthographic and lexical rules, such as capitalization at the 
    beginning of a sentence and pluralizing a word, are taken care of here. The 
    formatted text is then passed on to the output.

    output: An instance of plover.oslayer.keyboardcontrol.KeyboardEmulation 
    class plus a hook to the application allows output to the screen and control
    of the app with steno strokes.

    In addition to the above pieces, a logger records timestamped strokes and
    translations.

    """
    def __init__(self, thread_hook=same_thread_hook):
        """Creates and configures a single steno pipeline."""
        self.subscribers = []
        self.stroke_listeners = []
        self.is_running = False
        self.machine = None
        self.thread_hook = thread_hook

        self.translator = translation.Translator()
        self.formatter = formatting.Formatter()
        self.logger = Logger()
        self.translator.add_listener(self.logger.log_translation)
        self.translator.add_listener(self.formatter.format)
        # This seems like a reasonable number. If this becomes a problem it can
        # be parameterized.
        self.translator.set_min_undo_length(10)

        self.full_output = SimpleNamespace()
        self.command_only_output = SimpleNamespace()
        self.running_state = self.translator.get_state()
        self.set_is_running(False)

    def set_machine(self, machine):
        if self.machine:
            self.machine.remove_state_callback(self._machine_state_callback)
            self.machine.remove_stroke_callback(
                self._translator_machine_callback)
            self.machine.remove_stroke_callback(self.logger.log_stroke)
            self.machine.stop_capture()
        self.machine = machine
        if self.machine:
            self.machine.add_state_callback(self._machine_state_callback)
            self.machine.add_stroke_callback(self.logger.log_stroke)
            self.machine.add_stroke_callback(self._translator_machine_callback)
            self.machine.start_capture()
            self.set_is_running(self.is_running)
        else:
            self.set_is_running(False)

    def set_dictionary(self, d):
        self.translator.set_dictionary(d)

    def get_dictionary(self):
        return self.translator.get_dictionary()

    def set_is_running(self, value):
        self.is_running = value
        if self.is_running:
            self.translator.set_state(self.running_state)
            self.formatter.set_output(self.full_output)
        else:
            self.translator.clear_state()
            self.formatter.set_output(self.command_only_output)
        if isinstance(self.machine, plover.machine.sidewinder.Stenotype):
            self.machine.suppress_keyboard(self.is_running)
        for callback in self.subscribers:
            callback(None)

    def set_output(self, o):
        self.full_output.send_backspaces = o.send_backspaces
        self.full_output.send_string = o.send_string
        self.full_output.send_key_combination = o.send_key_combination
        self.full_output.send_engine_command = o.send_engine_command
        self.command_only_output.send_engine_command = o.send_engine_command

    def destroy(self):
        """Halts the stenography capture-translate-format-display pipeline.

        Calling this method causes all worker threads involved to terminate.
        This method should be called at least once if the start method had been
        previously called. Calling this method more than once or before the
        start method has been called has no effect.

        """
        if self.machine:
            self.machine.stop_capture()
        self.is_running = False

    def add_callback(self, callback):
        """Subscribes a function to receive changes of the is_running state.

        Arguments:

        callback -- A function that takes no arguments.

        """
        self.subscribers.append(callback)

    def set_log_file_name(self, filename):
        """Set the file name for log output."""
        self.logger.set_filename(filename)

    def enable_stroke_logging(self, b):
        """Turn stroke logging on or off."""
        self.logger.enable_stroke_logging(b)

    def enable_translation_logging(self, b):
        """Turn translation logging on or off."""
        self.logger.enable_translation_logging(b)

    def add_stroke_listener(self, listener):
        self.stroke_listeners.append(listener)

    def remove_stroke_listener(self, listener):
        self.stroke_listeners.remove(listener)

    def _translate_stroke(self, s):
        stroke = steno.Stroke(s)
        self.translator.translate(stroke)
        for listener in self.stroke_listeners:
            listener(stroke)

    def _translator_machine_callback(self, s):
        self.thread_hook(self._translate_stroke, s)

    def _notify_listeners(self, s):
        for callback in self.subscribers:
            callback(s)

    def _machine_state_callback(self, s):
        self.thread_hook(self._notify_listeners, s)
Exemplo n.º 7
0
 def setUp(self):
     self.patcher = patch('plover.logger.RotatingFileHandler', FakeHandler)
     self.patcher.start()
     self.logger = Logger()
Exemplo n.º 8
0
class LoggerTestCase(unittest.TestCase):

    def setUp(self):
        self.patcher = patch('plover.logger.RotatingFileHandler', FakeHandler)
        self.patcher.start()
        self.logger = Logger()
            
    def tearDown(self):
        self.logger.set_filename(None)
        self.patcher.stop()

    def test_set_filename(self):
        self.logger.set_filename('fn1')
        self.logger.enable_stroke_logging(True)
        self.logger.log_stroke(('S',))
        self.logger.set_filename('fn2')
        self.logger.log_stroke(('T',))
        self.logger.set_filename(None)
        self.logger.log_stroke(('P',))
        self.assertEqual(FakeHandler.get_output(), {'fn1': ['Stroke(S)'], 
                                                    'fn2': ['Stroke(T)']})

    def test_log_stroke(self):
        self.logger.set_filename('fn')
        self.logger.enable_stroke_logging(True)
        self.logger.log_stroke(('ST', 'T'))
        self.assertEqual(FakeHandler.get_output(), {'fn': ['Stroke(ST T)']})

    def test_log_translation(self):
        self.logger.set_filename('fn')
        self.logger.enable_translation_logging(True)
        self.logger.log_translation(['a', 'b'], ['c', 'd'], None)
        self.assertEqual(FakeHandler.get_output(), 
                        {'fn': ['*a', '*b', 'c', 'd']})

    def test_enable_stroke_logging(self):
        self.logger.set_filename('fn')
        self.logger.log_stroke(('a',))
        self.logger.enable_stroke_logging(True)
        self.logger.log_stroke(('b',))
        self.logger.enable_stroke_logging(False)
        self.logger.log_stroke(('c',))
        self.assertEqual(FakeHandler.get_output(), {'fn': ['Stroke(b)']})

    def test_enable_translation_logging(self):
        self.logger.set_filename('fn')
        self.logger.log_translation(['a'], ['b'], None)
        self.logger.enable_translation_logging(True)
        self.logger.log_translation(['c'], ['d'], None)
        self.logger.enable_translation_logging(False)
        self.logger.log_translation(['e'], ['f'], None)
        self.assertEqual(FakeHandler.get_output(), {'fn': ['*c', 'd']})