1# Orca 2# 3# Copyright 2014 Igalia, S.L. 4# 5# Author: Joanmarie Diggs <jdiggs@igalia.com> 6# 7# This library is free software; you can redistribute it and/or 8# modify it under the terms of the GNU Lesser General Public 9# License as published by the Free Software Foundation; either 10# version 2.1 of the License, or (at your option) any later version. 11# 12# This library is distributed in the hope that it will be useful, 13# but WITHOUT ANY WARRANTY; without even the implied warranty of 14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15# Lesser General Public License for more details. 16# 17# You should have received a copy of the GNU Lesser General Public 18# License along with this library; if not, write to the 19# Free Software Foundation, Inc., Franklin Street, Fifth Floor, 20# Boston MA 02110-1301 USA. 21 22"""Customized support for spellcheck in Thunderbird.""" 23 24__id__ = "$Id$" 25__version__ = "$Revision$" 26__date__ = "$Date$" 27__copyright__ = "Copyright (c) 2014 Igalia, S.L." 28__license__ = "LGPL" 29 30import pyatspi 31 32import orca.orca_state as orca_state 33import orca.spellcheck as spellcheck 34 35class SpellCheck(spellcheck.SpellCheck): 36 37 def __init__(self, script): 38 super(SpellCheck, self).__init__(script) 39 40 def isAutoFocusEvent(self, event): 41 if event.source != self._changeToEntry: 42 return False 43 44 locusOfFocus = orca_state.locusOfFocus 45 if not locusOfFocus: 46 return False 47 48 role = locusOfFocus.getRole() 49 if not role == pyatspi.ROLE_PUSH_BUTTON: 50 return False 51 52 lastKey, mods = self._script.utilities.lastKeyAndModifiers() 53 keys = self._script.utilities.mnemonicShortcutAccelerator(locusOfFocus) 54 for key in keys: 55 if key.endswith(lastKey.upper()): 56 return True 57 58 return False 59 60 def _isCandidateWindow(self, window): 61 if not (window and window.getRole() == pyatspi.ROLE_DIALOG): 62 return False 63 64 roles = [pyatspi.ROLE_PAGE_TAB_LIST, pyatspi.ROLE_SPLIT_PANE] 65 isNonSpellCheckChild = lambda x: x and x.getRole() in roles 66 if pyatspi.findDescendant(window, isNonSpellCheckChild): 67 return False 68 69 return True 70 71 def _findChangeToEntry(self, root): 72 isEntry = lambda x: x and x.getRole() == pyatspi.ROLE_ENTRY \ 73 and x.getState().contains(pyatspi.STATE_SINGLE_LINE) 74 return pyatspi.findDescendant(root, isEntry) 75 76 def _findErrorWidget(self, root): 77 isError = lambda x: x and x.getRole() == pyatspi.ROLE_LABEL \ 78 and not ":" in x.name and not x.getRelationSet() 79 return pyatspi.findDescendant(root, isError) 80 81 def _findSuggestionsList(self, root): 82 isList = lambda x: x and x.getRole() in [pyatspi.ROLE_LIST, pyatspi.ROLE_LIST_BOX] \ 83 and 'Selection' in x.get_interfaces() 84 return pyatspi.findDescendant(root, isList) 85 86 def _getSuggestionIndexAndPosition(self, suggestion): 87 attrs = self._script.utilities.objectAttributes(suggestion) 88 index = attrs.get("posinset") 89 total = attrs.get("setsize") 90 if index is None or total is None: 91 return super()._getSuggestionIndexAndPosition(suggestion) 92 93 return int(index), int(total) 94