From 4ef9721dc5b5482524a45e256366d184a84e04c5 Mon Sep 17 00:00:00 2001 From: Davy Kager Date: Thu, 21 May 2015 17:13:51 +0200 Subject: [PATCH 1/8] Initial refactoring to allow for custom braille tables. * Rename braille.TABLES to braille.tables and turn it into a list. * Make the always-included patterns table path a constant. --- source/braille.py | 12 +++++------- source/brailleInput.py | 2 +- source/gui/settingsDialogs.py | 9 +++++---- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/source/braille.py b/source/braille.py index 8de4db80f31..76be9b9b36b 100644 --- a/source/braille.py +++ b/source/braille.py @@ -21,9 +21,10 @@ #: The directory in which liblouis braille tables are located. TABLES_DIR = r"louis\tables" +PATTERNS_TABLE = os.path.join(TABLES_DIR, "braille-patterns.cti") -#: The table file names and information. -TABLES = ( +#: The braille table file names and information. +tables = [ # (fileName, displayName, supportsInput), # Translators: The name of a braille table displayed in the # braille settings dialog. @@ -277,10 +278,7 @@ # Translators: The name of a braille table displayed in the # braille settings dialog. ("zh-tw.ctb", _("Chinese (Taiwan, Mandarin)"), False), -) - -#: Braille tables that support input (only computer braille tables yet). -INPUT_TABLES = tuple(t for t in TABLES if t[2]) +] roleLabels = { # Translators: Displayed in braille for an object which is an @@ -447,7 +445,7 @@ def update(self): text=unicode(self.rawText).replace('\0','') braille, self.brailleToRawPos, self.rawToBraillePos, brailleCursorPos = louis.translate( [os.path.join(TABLES_DIR, config.conf["braille"]["translationTable"]), - "braille-patterns.cti"], + PATTERNS_TABLE], text, # liblouis mutates typeform if it is a list. typeform=tuple(self.rawTextTypeforms) if isinstance(self.rawTextTypeforms, list) else self.rawTextTypeforms, diff --git a/source/brailleInput.py b/source/brailleInput.py index ffd08384140..f26229fd208 100644 --- a/source/brailleInput.py +++ b/source/brailleInput.py @@ -42,7 +42,7 @@ def input(self, dots): char = unichr(dots | 0x8000) text = louis.backTranslate( [os.path.join(braille.TABLES_DIR, config.conf["braille"]["inputTable"]), - "braille-patterns.cti"], + braille.PATTERNS_TABLE], char, mode=louis.dotsIO) chars = text[0] if len(chars) > 0: diff --git a/source/gui/settingsDialogs.py b/source/gui/settingsDialogs.py index 1e8b6f65477..2ef6dd70682 100644 --- a/source/gui/settingsDialogs.py +++ b/source/gui/settingsDialogs.py @@ -1370,8 +1370,8 @@ def makeSettings(self, settingsSizer): sizer = wx.BoxSizer(wx.HORIZONTAL) # Translators: The label for a setting in braille settings to select the output table (the braille table used to read braille text on the braille display). label = wx.StaticText(self, wx.ID_ANY, label=_("&Output table:")) - self.tableNames = [table[0] for table in braille.TABLES] - self.tableList = wx.Choice(self, wx.ID_ANY, choices=[table[1] for table in braille.TABLES]) + self.tableNames = [table[0] for table in braille.tables] + self.tableList = wx.Choice(self, wx.ID_ANY, choices=[table[1] for table in braille.tables]) try: selection = self.tableNames.index(config.conf["braille"]["translationTable"]) self.tableList.SetSelection(selection) @@ -1384,8 +1384,9 @@ def makeSettings(self, settingsSizer): sizer = wx.BoxSizer(wx.HORIZONTAL) # Translators: The label for a setting in braille settings to select the input table (the braille table used to type braille characters on a braille keyboard). label = wx.StaticText(self, wx.ID_ANY, label=_("&Input table:")) - self.inputTableNames = [table[0] for table in braille.INPUT_TABLES] - self.inputTableList = wx.Choice(self, wx.ID_ANY, choices=[table[1] for table in braille.INPUT_TABLES]) + inputTables = [table for table in braille.tables if table[2]] + self.inputTableNames = [table[0] for table in inputTables] + self.inputTableList = wx.Choice(self, wx.ID_ANY, choices=[table[1] for table in inputTables]) try: selection = self.inputTableNames.index(config.conf["braille"]["inputTable"]) self.inputTableList.SetSelection(selection) From de6799745acead472bea866836878964389ca90d Mon Sep 17 00:00:00 2001 From: Davy Kager Date: Mon, 25 May 2015 19:22:12 +0200 Subject: [PATCH 2/8] Cache the list of braille tables for translation and input. Prevents table paths from being computed on every translation or input. --- source/braille.py | 33 ++++++++++++++++++++++++++++++--- source/brailleInput.py | 4 +--- source/gui/settingsDialogs.py | 10 ++++++++-- 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/source/braille.py b/source/braille.py index 76be9b9b36b..f9e46baa60e 100644 --- a/source/braille.py +++ b/source/braille.py @@ -444,9 +444,7 @@ def update(self): mode |= louis.compbrlAtCursor text=unicode(self.rawText).replace('\0','') braille, self.brailleToRawPos, self.rawToBraillePos, brailleCursorPos = louis.translate( - [os.path.join(TABLES_DIR, config.conf["braille"]["translationTable"]), - PATTERNS_TABLE], - text, + handler.translationTableList, text, # liblouis mutates typeform if it is a list. typeform=tuple(self.rawTextTypeforms) if isinstance(self.rawTextTypeforms, list) else self.rawTextTypeforms, mode=mode, cursorPos=self.cursorPos or 0) @@ -1347,6 +1345,8 @@ class BrailleHandler(baseObject.AutoPropertyObject): def __init__(self): self.display = None self.displaySize = 0 + self.translationTableList = [] + self.inputTableList = [] self.mainBuffer = BrailleBuffer(self) self.messageBuffer = BrailleBuffer(self) self._messageCallLater = None @@ -1425,6 +1425,29 @@ def setDisplayByName(self, name, isFallback=False): self.setDisplayByName("noBraille", isFallback=True) return False + def _getTablePath(self, table): + if not os.path.isabs(table): + # This is a stock table. + return os.path.join(TABLES_DIR, table) + return table + + def _getTableList(self, table): + return [self._getTablePath(table), PATTERNS_TABLE] + + def setTranslationTable(self, table): + tableList = self._getTableList(table) + # TODO: Use louis.checkTable() to verify if tableList can actually be compiled. + config.conf["braille"]["translationTable"] = table + self.translationTableList = tableList + return True + + def setInputTable(self, table): + tableList = self._getTableList(table) + # TODO: Use louis.checkTable() to verify if tableList can actually be compiled. + config.conf["braille"]["inputTable"] = table + self.inputTableList = tableList + return True + def _updateDisplay(self): if self._cursorBlinkTimer: self._cursorBlinkTimer.Stop() @@ -1607,6 +1630,8 @@ def handleConfigProfileSwitch(self): display = config.conf["braille"]["display"] if display != self.display.name: self.setDisplayByName(display) + setTranslationTable(config.conf["braille"]["translationTable"]) + setInputTable(config.conf["braille"]["inputTable"]) def initialize(): global handler @@ -1614,6 +1639,8 @@ def initialize(): log.info("Using liblouis version %s" % louis.version()) handler = BrailleHandler() handler.setDisplayByName(config.conf["braille"]["display"]) + handler.setTranslationTable(config.conf["braille"]["translationTable"]) + handler.setInputTable(config.conf["braille"]["inputTable"]) # Update the display to the current focus/review position. if not handler.enabled or not api.getDesktopObject(): diff --git a/source/brailleInput.py b/source/brailleInput.py index f26229fd208..3af231d1c7c 100644 --- a/source/brailleInput.py +++ b/source/brailleInput.py @@ -41,9 +41,7 @@ def input(self, dots): # liblouis requires us to set the highest bit for proper use of dotsIO. char = unichr(dots | 0x8000) text = louis.backTranslate( - [os.path.join(braille.TABLES_DIR, config.conf["braille"]["inputTable"]), - braille.PATTERNS_TABLE], - char, mode=louis.dotsIO) + braille.handler.inputTableList, char, mode=louis.dotsIO) chars = text[0] if len(chars) > 0: self.sendChars(chars) diff --git a/source/gui/settingsDialogs.py b/source/gui/settingsDialogs.py index 2ef6dd70682..7f250f32afd 100644 --- a/source/gui/settingsDialogs.py +++ b/source/gui/settingsDialogs.py @@ -1457,8 +1457,14 @@ def onOk(self, evt): if not braille.handler.setDisplayByName(display): gui.messageBox(_("Could not load the %s display.")%display, _("Braille Display Error"), wx.OK|wx.ICON_WARNING, self) return - config.conf["braille"]["translationTable"] = self.tableNames[self.tableList.GetSelection()] - config.conf["braille"]["inputTable"] = self.inputTableNames[self.inputTableList.GetSelection()] + table = self.tableNames[self.tableList.GetSelection()] + if not braille.handler.setTranslationTable(table): + gui.messageBox(_("Could not load the %s translation table.")%table, _("Braille Table Error"), wx.OK|wx.ICON_WARNING, self) + return + table = self.inputTableNames[self.inputTableList.GetSelection()] + if not braille.handler.setInputTable(table): + gui.messageBox(_("Could not load the %s input table.")%table, _("Braille Table Error"), wx.OK|wx.ICON_WARNING, self) + return config.conf["braille"]["expandAtCursor"] = self.expandAtCursorCheckBox.GetValue() try: val = int(self.cursorBlinkRateEdit.GetValue()) From 0c5b6575606cc76388361a6fa5b4fefb4b6a19da Mon Sep 17 00:00:00 2001 From: Davy Kager Date: Mon, 25 May 2015 21:12:35 +0200 Subject: [PATCH 3/8] In the GUI, sort braille tables by display name rather than filename. --- source/gui/settingsDialogs.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/source/gui/settingsDialogs.py b/source/gui/settingsDialogs.py index 7f250f32afd..b04ca146781 100644 --- a/source/gui/settingsDialogs.py +++ b/source/gui/settingsDialogs.py @@ -1370,8 +1370,9 @@ def makeSettings(self, settingsSizer): sizer = wx.BoxSizer(wx.HORIZONTAL) # Translators: The label for a setting in braille settings to select the output table (the braille table used to read braille text on the braille display). label = wx.StaticText(self, wx.ID_ANY, label=_("&Output table:")) - self.tableNames = [table[0] for table in braille.tables] - self.tableList = wx.Choice(self, wx.ID_ANY, choices=[table[1] for table in braille.tables]) + tables = sorted(braille.tables, key=lambda table: table[1]) + self.tableNames = [table[0] for table in tables] + self.tableList = wx.Choice(self, wx.ID_ANY, choices=[table[1] for table in tables]) try: selection = self.tableNames.index(config.conf["braille"]["translationTable"]) self.tableList.SetSelection(selection) @@ -1384,9 +1385,9 @@ def makeSettings(self, settingsSizer): sizer = wx.BoxSizer(wx.HORIZONTAL) # Translators: The label for a setting in braille settings to select the input table (the braille table used to type braille characters on a braille keyboard). label = wx.StaticText(self, wx.ID_ANY, label=_("&Input table:")) - inputTables = [table for table in braille.tables if table[2]] - self.inputTableNames = [table[0] for table in inputTables] - self.inputTableList = wx.Choice(self, wx.ID_ANY, choices=[table[1] for table in inputTables]) + tables = [table for table in tables if table[2]] + self.inputTableNames = [table[0] for table in tables] + self.inputTableList = wx.Choice(self, wx.ID_ANY, choices=[table[1] for table in tables]) try: selection = self.inputTableNames.index(config.conf["braille"]["inputTable"]) self.inputTableList.SetSelection(selection) From 146448718fdc8b7b664af22feeaaebcb802a7dc8 Mon Sep 17 00:00:00 2001 From: Davy Kager Date: Wed, 17 Jun 2015 19:23:19 +0200 Subject: [PATCH 4/8] Introduce a fallback table to prevent cases where braille output stops when specifying an invalid table. Requires liblouis >= 2.6.3 (#5137). --- source/braille.py | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/source/braille.py b/source/braille.py index f9e46baa60e..5fbd13ea232 100644 --- a/source/braille.py +++ b/source/braille.py @@ -1434,17 +1434,29 @@ def _getTablePath(self, table): def _getTableList(self, table): return [self._getTablePath(table), PATTERNS_TABLE] - def setTranslationTable(self, table): + def setTranslationTable(self, table, isFallback=False): tableList = self._getTableList(table) - # TODO: Use louis.checkTable() to verify if tableList can actually be compiled. - config.conf["braille"]["translationTable"] = table + if not isFallback: + try: + louis.checkTable(tables) + except: + log.error("Error compiling translation tables", exc_info=True) + self.setTranslationTable("en-us-comp8.ctb", isFallback=True) + return False + config.conf["braille"]["translationTable"] = table self.translationTableList = tableList return True - def setInputTable(self, table): + def setInputTable(self, table, isFallback=False): tableList = self._getTableList(table) - # TODO: Use louis.checkTable() to verify if tableList can actually be compiled. - config.conf["braille"]["inputTable"] = table + if not isFallback: + try: + louis.checkTable(tables) + except: + log.error("Error compiling input tables", exc_info=True) + self.setInputTable("en-us-comp8.ctb", isFallback=True) + return False + config.conf["braille"]["inputTable"] = table self.inputTableList = tableList return True From 2902bc86f1aa131e4ee8fad7e797dbdaf77a3727 Mon Sep 17 00:00:00 2001 From: Davy Kager Date: Thu, 16 Jul 2015 17:10:14 +0200 Subject: [PATCH 5/8] Fixup. --- source/braille.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/braille.py b/source/braille.py index 5fbd13ea232..c7dc2b0d2f4 100644 --- a/source/braille.py +++ b/source/braille.py @@ -1642,8 +1642,8 @@ def handleConfigProfileSwitch(self): display = config.conf["braille"]["display"] if display != self.display.name: self.setDisplayByName(display) - setTranslationTable(config.conf["braille"]["translationTable"]) - setInputTable(config.conf["braille"]["inputTable"]) + self.setTranslationTable(config.conf["braille"]["translationTable"]) + self.setInputTable(config.conf["braille"]["inputTable"]) def initialize(): global handler From 162e8c159ba83273452a39dd8b7059bc233510c5 Mon Sep 17 00:00:00 2001 From: Davy Kager Date: Thu, 23 Jul 2015 21:06:51 +0200 Subject: [PATCH 6/8] Fixup. --- source/braille.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/braille.py b/source/braille.py index c7dc2b0d2f4..dfbc8af780b 100644 --- a/source/braille.py +++ b/source/braille.py @@ -1438,7 +1438,7 @@ def setTranslationTable(self, table, isFallback=False): tableList = self._getTableList(table) if not isFallback: try: - louis.checkTable(tables) + louis.checkTable(tableList) except: log.error("Error compiling translation tables", exc_info=True) self.setTranslationTable("en-us-comp8.ctb", isFallback=True) @@ -1451,7 +1451,7 @@ def setInputTable(self, table, isFallback=False): tableList = self._getTableList(table) if not isFallback: try: - louis.checkTable(tables) + louis.checkTable(tableList) except: log.error("Error compiling input tables", exc_info=True) self.setInputTable("en-us-comp8.ctb", isFallback=True) From 4b2a138ed4df15d49259fd87ae6082f0938c8429 Mon Sep 17 00:00:00 2001 From: Davy Kager Date: Fri, 4 Dec 2015 20:29:54 +0100 Subject: [PATCH 7/8] Refactor: * Rename braille.PATTERNS_TABLE so it better reflects its intended purpose. * Move code related to braille input into the brailleInput module. --- source/braille.py | 38 ++++++++++------------------------- source/brailleInput.py | 21 ++++++++++++++++++- source/config/__init__.py | 2 ++ source/gui/settingsDialogs.py | 3 ++- 4 files changed, 35 insertions(+), 29 deletions(-) diff --git a/source/braille.py b/source/braille.py index dfbc8af780b..768d36594e7 100644 --- a/source/braille.py +++ b/source/braille.py @@ -21,7 +21,7 @@ #: The directory in which liblouis braille tables are located. TABLES_DIR = r"louis\tables" -PATTERNS_TABLE = os.path.join(TABLES_DIR, "braille-patterns.cti") +UNICODe_BRAILLE_TABLE = os.path.join(TABLES_DIR, "braille-patterns.cti") #: The braille table file names and information. tables = [ @@ -280,6 +280,15 @@ ("zh-tw.ctb", _("Chinese (Taiwan, Mandarin)"), False), ] +def _getTablePath(table): + if not os.path.isabs(table): + # This is a stock table. + return os.path.join(TABLES_DIR, table) + return table + +def _getTableList(table): + return [_getTablePath(table), UNICODE_BRAILLE_TABLE] + roleLabels = { # Translators: Displayed in braille for an object which is an # editable text field. @@ -1346,7 +1355,6 @@ def __init__(self): self.display = None self.displaySize = 0 self.translationTableList = [] - self.inputTableList = [] self.mainBuffer = BrailleBuffer(self) self.messageBuffer = BrailleBuffer(self) self._messageCallLater = None @@ -1425,17 +1433,8 @@ def setDisplayByName(self, name, isFallback=False): self.setDisplayByName("noBraille", isFallback=True) return False - def _getTablePath(self, table): - if not os.path.isabs(table): - # This is a stock table. - return os.path.join(TABLES_DIR, table) - return table - - def _getTableList(self, table): - return [self._getTablePath(table), PATTERNS_TABLE] - def setTranslationTable(self, table, isFallback=False): - tableList = self._getTableList(table) + tableList = _getTableList(table) if not isFallback: try: louis.checkTable(tableList) @@ -1447,19 +1446,6 @@ def setTranslationTable(self, table, isFallback=False): self.translationTableList = tableList return True - def setInputTable(self, table, isFallback=False): - tableList = self._getTableList(table) - if not isFallback: - try: - louis.checkTable(tableList) - except: - log.error("Error compiling input tables", exc_info=True) - self.setInputTable("en-us-comp8.ctb", isFallback=True) - return False - config.conf["braille"]["inputTable"] = table - self.inputTableList = tableList - return True - def _updateDisplay(self): if self._cursorBlinkTimer: self._cursorBlinkTimer.Stop() @@ -1643,7 +1629,6 @@ def handleConfigProfileSwitch(self): if display != self.display.name: self.setDisplayByName(display) self.setTranslationTable(config.conf["braille"]["translationTable"]) - self.setInputTable(config.conf["braille"]["inputTable"]) def initialize(): global handler @@ -1652,7 +1637,6 @@ def initialize(): handler = BrailleHandler() handler.setDisplayByName(config.conf["braille"]["display"]) handler.setTranslationTable(config.conf["braille"]["translationTable"]) - handler.setInputTable(config.conf["braille"]["inputTable"]) # Update the display to the current focus/review position. if not handler.enabled or not api.getDesktopObject(): diff --git a/source/brailleInput.py b/source/brailleInput.py index 3af231d1c7c..83c44412ddd 100644 --- a/source/brailleInput.py +++ b/source/brailleInput.py @@ -4,7 +4,6 @@ #See the file COPYING for more details. #Copyright (C) 2012-2013 NV Access Limited, Rui Batista -import os.path import louis import braille import config @@ -25,6 +24,7 @@ def initialize(): global handler handler = BrailleInputHandler() + handler.setInputTable(config.conf["braille"]["inputTable"]) log.info("Braille input initialized") def terminate(): @@ -35,6 +35,22 @@ class BrailleInputHandler(object): """Handles braille input. """ + def __init__(self): + self.inputTableList = [] + + def setInputTable(self, table, isFallback=False): + tableList = braille._getTableList(table) + if not isFallback: + try: + louis.checkTable(tableList) + except: + log.error("Error compiling input tables", exc_info=True) + self.setInputTable("en-us-comp8.ctb", isFallback=True) + return False + config.conf["braille"]["inputTable"] = table + self.inputTableList = tableList + return True + def input(self, dots): """Handle one cell of braille input. """ @@ -58,6 +74,9 @@ def sendChars(self, chars): inputs.append(input) winUser.SendInput(inputs) + def handleConfigProfileSwitch(self): + self.setInputTable(config.conf["braille"]["translationTable"]) + class BrailleInputGesture(inputCore.InputGesture): """Input (dots and/or space bar) from a braille keyboard. This could either be as part of a braille display or a stand-alone unit. diff --git a/source/config/__init__.py b/source/config/__init__.py index 1de4ae440e2..410af9f091b 100644 --- a/source/config/__init__.py +++ b/source/config/__init__.py @@ -508,7 +508,9 @@ def _handleProfileSwitch(self): import synthDriverHandler synthDriverHandler.handleConfigProfileSwitch() import braille + import brailleInput braille.handler.handleConfigProfileSwitch() + brailleInput.handler.handleConfigProfileSwitch() def _initBaseConf(self, factoryDefaults=False): fn = os.path.join(globalVars.appArgs.configPath, "nvda.ini") diff --git a/source/gui/settingsDialogs.py b/source/gui/settingsDialogs.py index b04ca146781..7e3e8ac92e6 100644 --- a/source/gui/settingsDialogs.py +++ b/source/gui/settingsDialogs.py @@ -25,6 +25,7 @@ import appModuleHandler import queueHandler import braille +import brailleInput import core import keyboardHandler import characterProcessing @@ -1463,7 +1464,7 @@ def onOk(self, evt): gui.messageBox(_("Could not load the %s translation table.")%table, _("Braille Table Error"), wx.OK|wx.ICON_WARNING, self) return table = self.inputTableNames[self.inputTableList.GetSelection()] - if not braille.handler.setInputTable(table): + if not brailleInput.handler.setInputTable(table): gui.messageBox(_("Could not load the %s input table.")%table, _("Braille Table Error"), wx.OK|wx.ICON_WARNING, self) return config.conf["braille"]["expandAtCursor"] = self.expandAtCursorCheckBox.GetValue() From b64a16bd86e3a88a77265273c63956c593e376ab Mon Sep 17 00:00:00 2001 From: Davy Kager Date: Sun, 6 Dec 2015 13:49:53 +0100 Subject: [PATCH 8/8] Fixup. --- source/braille.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/braille.py b/source/braille.py index 768d36594e7..92e7c2df868 100644 --- a/source/braille.py +++ b/source/braille.py @@ -21,7 +21,7 @@ #: The directory in which liblouis braille tables are located. TABLES_DIR = r"louis\tables" -UNICODe_BRAILLE_TABLE = os.path.join(TABLES_DIR, "braille-patterns.cti") +UNICODE_BRAILLE_TABLE = os.path.join(TABLES_DIR, "braille-patterns.cti") #: The braille table file names and information. tables = [