# Orca # # Copyright 2014 Igalia, S.L. # # Author: Joanmarie Diggs <jdiggs@igalia.com> # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the # Free Software Foundation, Inc., Franklin Street, Fifth Floor, # Boston MA 02110-1301 USA. """Script-customizable support for application spellcheckers.""" __id__ = "$Id$" __version__ = "$Revision$" __date__ = "$Date$" __copyright__ = "Copyright (c) 2014 Igalia, S.L." __license__ = "LGPL" import pyatspi import re from orca import guilabels from orca import messages from orca import object_properties from orca import orca_state from orca import settings_manager _settingsManager = settings_manager.getManager() class SpellCheck: def __init__(self, script, hasChangeToEntry=True): self._script = script self._hasChangeToEntry = hasChangeToEntry self._window = None self._errorWidget = None self._changeToEntry = None self._suggestionsList = None self._activated = False self._documentPosition = None, -1 self.spellErrorCheckButton = None self.spellSuggestionCheckButton = None self.presentContextCheckButton = None def activate(self, window): if not self._isCandidateWindow(window): return False if self._hasChangeToEntry: self._changeToEntry = self._findChangeToEntry(window) if not self._changeToEntry: return False self._errorWidget = self._findErrorWidget(window) if not self._errorWidget: return False self._suggestionsList = self._findSuggestionsList(window) if not self._suggestionsList: return False self._window = window self._activated = True return True def deactivate(self): self._clearState() def getDocumentPosition(self): return self._documentPosition def setDocumentPosition(self, obj, offset): self._documentPosition = obj, offset def getErrorWidget(self): return self._errorWidget def getMisspelledWord(self): if not self._errorWidget: return "" return self._script.utilities.displayedText(self._errorWidget) def getCompletionMessage(self): if not self._errorWidget: return "" return self._script.utilities.displayedText(self._errorWidget) def getChangeToEntry(self): return self._changeToEntry def getSuggestionsList(self): return self._suggestionsList def isActive(self): return self._activated def isCheckWindow(self, window): if window and window == self._window: return True return self.activate(window) def isComplete(self): try: state = self._changeToEntry.getState() except: return False return not state.contains(pyatspi.STATE_SENSITIVE) def isAutoFocusEvent(self, event): return False def isSuggestionsItem(self, obj): if not self._suggestionsList: return False return obj and obj.parent == self._suggestionsList def presentContext(self): if not self.isActive(): return False obj, offset = self._documentPosition if not (obj and offset >= 0): return False try: text = obj.queryText() except: return False # This should work, but some toolkits are broken. boundary = pyatspi.TEXT_BOUNDARY_SENTENCE_START string, start, end = text.getTextAtOffset(offset, boundary) if not string: boundary = pyatspi.TEXT_BOUNDARY_LINE_START string, start, end = text.getTextAtOffset(offset, boundary) sentences = re.split(r'(?:\.|\!|\?)', string) word = self.getMisspelledWord() if string.count(word) == 1: match = list(filter(lambda x: x.count(word), sentences)) string = match[0] if not string: return False msg = messages.MISSPELLED_WORD_CONTEXT % string voice = self._script.speechGenerator.voice(string=msg) self._script.speakMessage(msg, voice=voice) return True def presentCompletionMessage(self): if not (self.isActive() and self.isComplete()): return False self._script.clearBraille() msg = self.getCompletionMessage() voice = self._script.speechGenerator.voice(string=msg) self._script.presentMessage(msg, voice=voice) return True def presentErrorDetails(self, detailed=False): if self.isComplete(): return False if self.presentMistake(detailed): self.presentSuggestion(detailed) if detailed or _settingsManager.getSetting('spellcheckPresentContext'): self.presentContext() return True return False def presentMistake(self, detailed=False): if not self.isActive(): return False word = self.getMisspelledWord() if not word: return False msg = messages.MISSPELLED_WORD % word voice = self._script.speechGenerator.voice(string=msg) self._script.speakMessage(msg, voice=voice) if detailed or _settingsManager.getSetting('spellcheckSpellError'): self._script.spellCurrentItem(word) return True def presentSuggestion(self, detailed=False): if not self._hasChangeToEntry: return self.presentSuggestionListItem(detailed, includeLabel=True) if not self.isActive(): return False entry = self._changeToEntry if not entry: return False label = self._script.utilities.displayedLabel(entry) or entry.name string = self._script.utilities.substring(entry, 0, -1) msg = "%s %s" % (label, string) voice = self._script.speechGenerator.voice(string=msg) self._script.speakMessage(msg, voice=voice) if detailed or _settingsManager.getSetting('spellcheckSpellSuggestion'): self._script.spellCurrentItem(string) return True def presentSuggestionListItem(self, detailed=False, includeLabel=False): if not self.isActive(): return False suggestions = self._suggestionsList if not suggestions: return False items = self._script.utilities.selectedChildren(suggestions) if not len(items) == 1: return False if includeLabel: label = self._script.utilities.displayedLabel(suggestions) or suggestions.name else: label = "" string = items[0].name msg = "%s %s" % (label, string) voice = self._script.speechGenerator.voice(string=msg) self._script.speakMessage(msg.strip(), voice=voice) if detailed or _settingsManager.getSetting('spellcheckSpellSuggestion'): self._script.spellCurrentItem(string) if _settingsManager.getSetting('enablePositionSpeaking') \ and items[0] == orca_state.locusOfFocus: index, total = self._getSuggestionIndexAndPosition(items[0]) msg = object_properties.GROUP_INDEX_SPEECH % {"index": index, "total": total} self._script.speakMessage(msg) return True def _clearState(self): self._window = None self._errorWidget = None self._changeToEntry = None self._suggestionsList = None self._activated = False def _isCandidateWindow(self, window): return False def _findChangeToEntry(self, root): return None def _findErrorWidget(self, root): return None def _findSuggestionsList(self, root): return None def _getSuggestionIndexAndPosition(self, suggestion): return -1, -1 def getAppPreferencesGUI(self): from gi.repository import Gtk frame = Gtk.Frame() label = Gtk.Label(label="<b>%s</b>" % guilabels.SPELL_CHECK) label.set_use_markup(True) frame.set_label_widget(label) alignment = Gtk.Alignment.new(0.5, 0.5, 1, 1) alignment.set_padding(0, 0, 12, 0) frame.add(alignment) grid = Gtk.Grid() alignment.add(grid) label = guilabels.SPELL_CHECK_SPELL_ERROR value = _settingsManager.getSetting('spellcheckSpellError') self.spellErrorCheckButton = Gtk.CheckButton.new_with_mnemonic(label) self.spellErrorCheckButton.set_active(value) grid.attach(self.spellErrorCheckButton, 0, 0, 1, 1) label = guilabels.SPELL_CHECK_SPELL_SUGGESTION value = _settingsManager.getSetting('spellcheckSpellSuggestion') self.spellSuggestionCheckButton = Gtk.CheckButton.new_with_mnemonic(label) self.spellSuggestionCheckButton.set_active(value) grid.attach(self.spellSuggestionCheckButton, 0, 1, 1, 1) label = guilabels.SPELL_CHECK_PRESENT_CONTEXT value = _settingsManager.getSetting('spellcheckPresentContext') self.presentContextCheckButton = Gtk.CheckButton.new_with_mnemonic(label) self.presentContextCheckButton.set_active(value) grid.attach(self.presentContextCheckButton, 0, 2, 1, 1) return frame def getPreferencesFromGUI(self): """Returns a dictionary with the app-specific preferences.""" return { 'spellcheckSpellError': self.spellErrorCheckButton.get_active(), 'spellcheckSpellSuggestion': self.spellSuggestionCheckButton.get_active(), 'spellcheckPresentContext': self.presentContextCheckButton.get_active() }
Name | Type | Size | Permission | Actions |
---|---|---|---|---|
__pycache__ | Folder | 0755 |
|
|
backends | Folder | 0755 |
|
|
scripts | Folder | 0755 |
|
|
__init__.py | File | 115 B | 0644 |
|
acss.py | File | 3.49 KB | 0644 |
|
bookmarks.py | File | 8.37 KB | 0644 |
|
braille.py | File | 59.87 KB | 0644 |
|
braille_generator.py | File | 20.5 KB | 0644 |
|
braille_rolenames.py | File | 10.33 KB | 0644 |
|
brlmon.py | File | 6.45 KB | 0644 |
|
brltablenames.py | File | 7.15 KB | 0644 |
|
caret_navigation.py | File | 13.67 KB | 0644 |
|
chat.py | File | 33.63 KB | 0644 |
|
chnames.py | File | 23.03 KB | 0644 |
|
cmdnames.py | File | 55.65 KB | 0644 |
|
colornames.py | File | 38.13 KB | 0644 |
|
common_keyboardmap.py | File | 6.64 KB | 0644 |
|
debug.py | File | 17.16 KB | 0644 |
|
desktop_keyboardmap.py | File | 4.62 KB | 0644 |
|
event_manager.py | File | 31.81 KB | 0644 |
|
eventsynthesizer.py | File | 17.82 KB | 0644 |
|
find.py | File | 12.77 KB | 0644 |
|
flat_review.py | File | 51.84 KB | 0644 |
|
formatting.py | File | 53.94 KB | 0644 |
|
generator.py | File | 59.09 KB | 0644 |
|
guilabels.py | File | 45.78 KB | 0644 |
|
input_event.py | File | 36.41 KB | 0644 |
|
keybindings.py | File | 16.39 KB | 0644 |
|
keynames.py | File | 9.71 KB | 0644 |
|
label_inference.py | File | 19.38 KB | 0644 |
|
laptop_keyboardmap.py | File | 4.61 KB | 0644 |
|
liveregions.py | File | 21.55 KB | 0644 |
|
logger.py | File | 1.97 KB | 0644 |
|
mathsymbols.py | File | 88.14 KB | 0644 |
|
messages.py | File | 140.32 KB | 0644 |
|
mouse_review.py | File | 18.91 KB | 0644 |
|
notification_messages.py | File | 6.18 KB | 0644 |
|
object_properties.py | File | 32.74 KB | 0644 |
|
orca.py | File | 25 KB | 0644 |
|
orca_gtkbuilder.py | File | 5.35 KB | 0644 |
|
orca_gui_commandlist.py | File | 4.19 KB | 0644 |
|
orca_gui_find.py | File | 8.12 KB | 0644 |
|
orca_gui_navlist.py | File | 6.66 KB | 0644 |
|
orca_gui_prefs.py | File | 139.07 KB | 0644 |
|
orca_gui_profile.py | File | 4.06 KB | 0644 |
|
orca_i18n.py | File | 3.18 KB | 0644 |
|
orca_platform.py | File | 1.41 KB | 0644 |
|
orca_state.py | File | 2.1 KB | 0644 |
|
phonnames.py | File | 2.76 KB | 0644 |
|
pronunciation_dict.py | File | 2.61 KB | 0644 |
|
punctuation_settings.py | File | 13.64 KB | 0644 |
|
script.py | File | 19.04 KB | 0644 |
|
script_manager.py | File | 13.31 KB | 0644 |
|
script_utilities.py | File | 183.59 KB | 0644 |
|
settings.py | File | 12.82 KB | 0644 |
|
settings_manager.py | File | 20.73 KB | 0644 |
|
sound.py | File | 5.17 KB | 0644 |
|
sound_generator.py | File | 11.99 KB | 0644 |
|
speech.py | File | 11.4 KB | 0644 |
|
speech_generator.py | File | 108.24 KB | 0644 |
|
speechdispatcherfactory.py | File | 24.54 KB | 0644 |
|
speechserver.py | File | 7.41 KB | 0644 |
|
spellcheck.py | File | 10.07 KB | 0644 |
|
structural_navigation.py | File | 122.53 KB | 0644 |
|
text_attribute_names.py | File | 28.62 KB | 0644 |
|
tutorialgenerator.py | File | 30.41 KB | 0644 |
|