1# Orca 2# 3# Copyright 2005-2009 Sun Microsystems Inc. 4# Copyright 2010 Joanmarie Diggs 5# 6# This library is free software; you can redistribute it and/or 7# modify it under the terms of the GNU Lesser General Public 8# License as published by the Free Software Foundation; either 9# version 2.1 of the License, or (at your option) any later version. 10# 11# This library is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14# Lesser General Public License for more details. 15# 16# You should have received a copy of the GNU Lesser General Public 17# License along with this library; if not, write to the 18# Free Software Foundation, Inc., Franklin Street, Fifth Floor, 19# Boston MA 02110-1301 USA. 20 21__id__ = "$Id$" 22__version__ = "$Revision$" 23__date__ = "$Date$" 24__copyright__ = "Copyright (c) 2005-2009 Sun Microsystems Inc., " \ 25 "Copyright (c) 2010 Joanmarie Diggs" 26__license__ = "LGPL" 27 28import pyatspi 29 30import orca.messages as messages 31import orca.settings as settings 32import orca.settings_manager as settings_manager 33import orca.speech_generator as speech_generator 34 35_settingsManager = settings_manager.getManager() 36 37######################################################################## 38# # 39# Speech Generator # 40# # 41######################################################################## 42 43class SpeechGenerator(speech_generator.SpeechGenerator): 44 45 # pylint: disable-msg=W0142 46 47 def __init__(self, script): 48 speech_generator.SpeechGenerator.__init__(self, script) 49 50 def _generateAncestors(self, obj, **args): 51 """The Swing toolkit has labelled panels that do not implement the 52 AccessibleText interface, but displayedText returns a meaningful 53 string that needs to be used if displayedLabel returns None. 54 """ 55 args['requireText'] = False 56 result = speech_generator.SpeechGenerator._generateAncestors( 57 self, obj, **args) 58 del args['requireText'] 59 return result 60 61 def _generateNewAncestors(self, obj, **args): 62 """Returns an array of strings (and possibly voice and audio 63 specifications) that represent the text of the ancestors for 64 the object. This is typically used to present the context for 65 an object (e.g., the names of the window, the panels, etc., 66 that the object is contained in). If the 'priorObj' attribute 67 of the args dictionary is set, only the differences in 68 ancestry between the 'priorObj' and the current obj will be 69 computed. Otherwise, no ancestry will be computed. The 70 'priorObj' is typically set by Orca to be the previous object 71 with focus. 72 """ 73 result = [] 74 if args.get('role', obj.getRole()) == pyatspi.ROLE_MENU: 75 # We're way too chatty here -- at least with the Swing2 76 # demo. Users entering a menu want to know they've gone 77 # into a menu; not a huge ancestry. 78 # 79 return result 80 result.extend(speech_generator.SpeechGenerator.\ 81 _generateNewAncestors(self, obj, **args)) 82 return result 83 84 def _generateNumberOfChildren(self, obj, **args): 85 """Returns an array of strings (and possibly voice and audio 86 specifications) that represents the number of children the 87 object has.""" 88 89 if _settingsManager.getSetting('onlySpeakDisplayedText') \ 90 or _settingsManager.getSetting('speechVerbosityLevel') == settings.VERBOSITY_LEVEL_BRIEF: 91 return [] 92 93 result = [] 94 acss = self.voice(speech_generator.SYSTEM) 95 if obj and obj.getState().contains(pyatspi.STATE_EXPANDED) \ 96 and obj.getRole() == pyatspi.ROLE_LABEL and obj.childCount: 97 result.append(messages.itemCount(obj.childCount)) 98 result.extend(acss) 99 else: 100 result.extend(speech_generator.SpeechGenerator.\ 101 _generateNumberOfChildren(self, obj, **args)) 102 103 return result 104 105 def _generatePositionInList(self, obj, **args): 106 """Returns an array of strings (and possibly voice and audio 107 specifications) that represent the relative position of an 108 object in a list. 109 """ 110 111 if _settingsManager.getSetting('onlySpeakDisplayedText'): 112 return [] 113 114 listObj = None 115 if obj and obj.getRole() == pyatspi.ROLE_COMBO_BOX: 116 hasRole = lambda x: x and x.getRole() == pyatspi.ROLE_LIST 117 allLists = pyatspi.findAllDescendants(obj, hasRole) 118 if len(allLists) == 1: 119 listObj = allLists[0] 120 121 if not listObj: 122 return speech_generator.SpeechGenerator._generatePositionInList( 123 self, obj, **args) 124 125 result = [] 126 acss = self.voice(speech_generator.SYSTEM) 127 name = self._generateName(obj) 128 position = -1 129 index = total = 0 130 131 for child in listObj: 132 nextName = self._generateName(child) 133 if not nextName or nextName[0] in ["", "Empty", "separator"] \ 134 or not child.getState().contains(pyatspi.STATE_VISIBLE): 135 continue 136 137 index += 1 138 total += 1 139 140 if nextName == name: 141 position = index 142 143 if (_settingsManager.getSetting('enablePositionSpeaking') \ 144 or args.get('forceList', False)) \ 145 and position >= 0: 146 result.append(self._script.formatting.getString( 147 mode='speech', stringType='groupindex') \ 148 % {"index" : position, "total" : total}) 149 result.extend(acss) 150 return result 151 152 def generateSpeech(self, obj, **args): 153 result = [] 154 if obj.getRole() == pyatspi.ROLE_CHECK_BOX \ 155 and obj.parent.getRole() == pyatspi.ROLE_MENU: 156 oldRole = self._overrideRole(pyatspi.ROLE_CHECK_MENU_ITEM, args) 157 result.extend(speech_generator.SpeechGenerator.\ 158 generateSpeech(self, obj, **args)) 159 self._restoreRole(oldRole, args) 160 161 if args.get('formatType', 'unfocused') == 'basicWhereAmI' \ 162 and obj.getRole() == pyatspi.ROLE_TEXT: 163 spinbox = self._script.utilities.ancestorWithRole( 164 obj, [pyatspi.ROLE_SPIN_BUTTON], None) 165 if spinbox: 166 obj = spinbox 167 result.extend(speech_generator.SpeechGenerator.\ 168 generateSpeech(self, obj, **args)) 169 return result 170