def isFocusOnFindDialog(self): """Return an indication of whether the current locus of focus is on the Find button or the combo box in the Find dialog. """ obj = orca_state.locusOfFocus rolesList1 = [ rolenames.ROLE_PUSH_BUTTON, rolenames.ROLE_FILLER, rolenames.ROLE_FILLER, rolenames.ROLE_DIALOG, rolenames.ROLE_APPLICATION ] rolesList2 = [ rolenames.ROLE_COMBO_BOX, rolenames.ROLE_PANEL, rolenames.ROLE_FILLER, rolenames.ROLE_FILLER, rolenames.ROLE_DIALOG, rolenames.ROLE_APPLICATION ] # Translators: this is used to tell us if the focus is on the # "Find" button in gedit's Find dialog. It must match what # gedit is using. We hate keying off stuff like this, but # we're forced to do so in this case. # if (self.isDesiredFocusedItem(obj, rolesList1) \ and obj.name == _("Find")) \ or (self.isDesiredFocusedItem(obj, rolesList2) \ and obj.parent.parent.parent.parent.name == _("Find")): return True else: return False
def isFocusOnFindDialog(self): """Return an indication of whether the current locus of focus is on the Find button or the combo box in the Find dialog. """ obj = orca_state.locusOfFocus rolesList1 = [rolenames.ROLE_PUSH_BUTTON, rolenames.ROLE_FILLER, rolenames.ROLE_FILLER, rolenames.ROLE_DIALOG, rolenames.ROLE_APPLICATION] rolesList2 = [rolenames.ROLE_COMBO_BOX, rolenames.ROLE_PANEL, rolenames.ROLE_FILLER, rolenames.ROLE_FILLER, rolenames.ROLE_DIALOG, rolenames.ROLE_APPLICATION] # Translators: this is used to tell us if the focus is on the # "Find" button in gedit's Find dialog. It must match what # gedit is using. We hate keying off stuff like this, but # we're forced to do so in this case. # if (self.isDesiredFocusedItem(obj, rolesList1) \ and obj.name == _("Find")) \ or (self.isDesiredFocusedItem(obj, rolesList2) \ and obj.parent.parent.parent.parent.name == _("Find")): return True else: return False
def onStateChanged(self, event): """Called whenever an object's state changes. Arguments: - event: the Event """ if not event.type.startswith("object:state-changed:busy"): default.Script.onStateChanged(self, event) return if not event.source or event.source.getRole() != pyatspi.ROLE_DOCUMENT_FRAME or not self._isBrowser: return if event.detail1: # Translators: this is in reference to loading a web page # or some other content. # self.presentMessage(_("Loading. Please wait.")) elif event.source.name: # Translators: this is in reference to loading a web page # or some other content. # self.presentMessage(_("Finished loading %s.") % event.source.name) else: # Translators: this is in reference to loading a web page # or some other content. # self.presentMessage(_("Finished loading."))
def presentStatusBar(self, obj): """Presents information about the metacity status bar.""" # We have to stop speech, as Metacity has a key grab and we're not # getting keys # speech.stop() # If the window was iconified, then obj.name will be surronded by # brackets. If this is the case, remove them before comparing the # name against the various window names. See bug #522797 for more # details. # objName = obj.name if objName and len(objName): if objName[0] == "[" and objName[-1] == "]": objName = objName[1:-1] # Do we know about this window? Traverse through our list of apps # and go through the toplevel windows in each to see if we know # about this one. If we do, it's accessible. If we don't, it is # not. # found = False for app in self.utilities.knownApplications(): i = 0 try: childCount = app.childCount except: continue while i < childCount: try: win = app.getChildAtIndex(i) except: win = None if win is None: print("app error " + app.name) elif win.name == objName: found = True i = i + 1 try: text = obj.name except: text = objName # Translators: the "Workspace " and "Desk " strings are # the prefix of what metacity shows when you press # Ctrl+Alt and the left or right arrow keys to switch # between workspaces. The goal here is to find a match # with that prefix. # if text.startswith(_("Workspace ")) or text.startswith(_("Desk ")): pass elif not found: text += ". " + messages.INACCESSIBLE self.displayBrailleMessage(text) speech.speak(text)
def onStateChanged(self, event): """Called whenever an object's state changes. Arguments: - event: the Event """ if event.source.getRole() == pyatspi.ROLE_FRAME \ and event.type.startswith("object:state-changed:busy"): # The busy cursor gets set/unset frequently. It's only worth # presenting if we're in the Search entry (handles both search # and catalog refreshes). # if not self.isSearchEntry(orca_state.locusOfFocus): return if event.detail1 == 1 and not self._isBusy: # Translators: this is in reference to loading a web page # or some other content. # msg = _("Loading. Please wait.") speech.speak(msg) self.displayBrailleMessage( msg, flashTime=settings.brailleFlashTime) self._isBusy = True elif event.detail1 == 0 and self._isBusy: # Translators: this is in reference to loading a web page # or some other content. # msg = _("Finished loading.") speech.speak(msg) self.displayBrailleMessage( msg, flashTime=settings.brailleFlashTime) self._isBusy = False return if script_settings.presentLoggedErrors \ and not self._presentedStatusBarIcon \ and event.source.getRole() == pyatspi.ROLE_PANEL \ and event.type.startswith("object:state-changed:showing") \ and event.detail1: obj = self.findStatusBarIcon() while obj and not self.utilities.isSameObject(obj, event.source): obj = obj.parent if obj: # Translators: The Package Manager application notifies the # user of minor errors by displaying an icon in the status # bar and adding them to an error log rather than displaying # the error in a dialog box. This is the message Orca will # present to inform the user that this has occurred. # msg = _("An error occurred. View the error log for details.") speech.speak(msg) self.displayBrailleMessage( msg, flashTime=settings.brailleFlashTime) self._presentedStatusBarIcon = True default.Script.onStateChanged(self, event)
def checkForTableBoundary(self, oldFocus, newFocus): """Check to see if we've crossed any table boundaries, speaking the appropriate details when we have. Arguments: - oldFocus: Accessible that is the old locus of focus - newFocus: Accessible that is the new locus of focus """ if oldFocus == None or newFocus == None: return [oldFocusIsTable, oldFocusRows, oldFocusColumns] = \ self.getTableAndDimensions(oldFocus) [newFocusIsTable, newFocusRows, newFocusColumns] = \ self.getTableAndDimensions(newFocus) # [[[TODO: JD - It is possible to move focus into the object # that contains the object that contains the text object. We # need to detect this and adjust accordingly.]]] if not oldFocusIsTable and newFocusIsTable: # We've entered a table. Announce the dimensions. # line = _("table with %d rows and %d columns.") % \ (newFocusRows, newFocusColumns) speech.speak(line) elif oldFocusIsTable and not newFocusIsTable: # We've left a table. Announce this fact. # speech.speak(_("leaving table.")) elif oldFocusIsTable and newFocusIsTable: # See if we've crossed a cell boundary. If so, speak # what has changed (per Mike). # [oldRow, oldCol] = \ self.getCellCoordinates(oldFocusIsTable, oldFocus) [newRow, newCol] = \ self.getCellCoordinates(newFocusIsTable, newFocus) # We can't count on being in the first/last cell # of the new row -- only the first/last cell of # the new row that contains data. # if newRow != oldRow: # Translators: this represents the row and column we're # on in a table. # line = _("row %d, column %d") % (newRow, newCol) speech.speak(line) elif newCol != oldCol: # Translators: this represents the column we're # on in a table. # line = _("column %d") % newCol speech.speak(line)
def checkForTableBoundary (self, oldFocus, newFocus): """Check to see if we've crossed any table boundaries, speaking the appropriate details when we have. Arguments: - oldFocus: Accessible that is the old locus of focus - newFocus: Accessible that is the new locus of focus """ if oldFocus == None or newFocus == None: return [oldFocusIsTable, oldFocusRows, oldFocusColumns] = \ self.getTableAndDimensions(oldFocus) [newFocusIsTable, newFocusRows, newFocusColumns] = \ self.getTableAndDimensions(newFocus) # [[[TODO: JD - It is possible to move focus into the object # that contains the object that contains the text object. We # need to detect this and adjust accordingly.]]] if not oldFocusIsTable and newFocusIsTable: # We've entered a table. Announce the dimensions. # line = _("table with %d rows and %d columns.") % \ (newFocusRows, newFocusColumns) speech.speak(line) elif oldFocusIsTable and not newFocusIsTable: # We've left a table. Announce this fact. # speech.speak(_("leaving table.")) elif oldFocusIsTable and newFocusIsTable: # See if we've crossed a cell boundary. If so, speak # what has changed (per Mike). # [oldRow, oldCol] = \ self.getCellCoordinates(oldFocusIsTable, oldFocus) [newRow, newCol] = \ self.getCellCoordinates(newFocusIsTable, newFocus) # We can't count on being in the first/last cell # of the new row -- only the first/last cell of # the new row that contains data. # if newRow != oldRow: # Translators: this represents the row and column we're # on in a table. # line = _("row %d, column %d") % (newRow, newCol) speech.speak(line) elif newCol != oldCol: # Translators: this represents the column we're # on in a table. # line = _("column %d") % newCol speech.speak(line)
def bookmarkCurrentWhereAmI(self, inputEvent): """ Report "Where am I" information for this bookmark relative to the current pointer location.""" index = (inputEvent.hw_code, self.getURIKey()) try: path, characterOffset = self._bookmarks[index] obj = self.pathToObj(path) except KeyError: self._script.systemBeep() return [cur_obj, cur_characterOffset] = self._script.getCaretContext() # Are they the same object? if self._script.utilities.isSameObject(cur_obj, obj): # Translators: this announces that the current object is the same # object pointed to by the bookmark. # self._script.presentMessage(_('bookmark is current object')) return # Are their parents the same? elif self._script.utilities.isSameObject(cur_obj.parent, obj.parent): # Translators: this announces that the current object's parent and # the parent of the object pointed to by the bookmark are the same. # self._script.presentMessage( _('bookmark and current object have same parent')) return # Do they share a common ancestor? # bookmark's ancestors bookmark_ancestors = [] p = obj.parent while p: bookmark_ancestors.append(p) p = p.parent # look at current object's ancestors to compare to bookmark's ancestors p = cur_obj.parent while p: if bookmark_ancestors.count(p) > 0: rolename = rolenames.getSpeechForRoleName(p) # Translators: this announces that the bookmark and the current # object share a common ancestor # self._script.presentMessage(_('shared ancestor %s') % rolename) return p = p.parent # Translators: This announces that a comparison between the bookmark # and the current object can not be determined. # self._script.presentMessage(_('comparison unknown'))
def __init__(self, app): """Creates a new script for the given application. Arguments: - app: the application to create a script for. """ self.debugLevel = debug.LEVEL_FINEST default.Script.__init__(self, app) # Acroread documents are contained in an object whose rolename # is "Document". "Link" is also capitalized in acroread. We # need to make these known to Orca for speech and braille output. # self.ROLE_DOCUMENT = "Document" rolenames.rolenames[self.ROLE_DOCUMENT] = \ rolenames.Rolename(self.ROLE_DOCUMENT, # Translators: short braille for the # rolename of a document. # _("doc"), # Translators: long braille for the # rolename of a document. # _("Document"), # Translators: spoken words for the # rolename of a document. # _("document")) self.ROLE_LINK = "Link" rolenames.rolenames[self.ROLE_LINK] = \ rolenames.rolenames[rolenames.ROLE_LINK] # To handle the multiple, identical object:text-caret-moved events # and possible focus events that result from a single key press # self.currentInputEvent = None # To handle the case when we get an object:text-caret-moved event # for some text we just left, but which is still showing on the # screen. # self.lastCaretMovedLine = None # To minimize chattiness related to focused events when the Find # toolbar is active. # self.findToolbarActive = False self.findToolbarName = None self.preFindLine = None
def _getTutorialForText(self, obj, alreadyFocused, forceTutorial): """Get the tutorial string for a text object. Arguments: - obj: the text component - alreadyFocused: False if object just received focus - forceTutorial: used for when whereAmI really needs the tutorial string Returns a list of tutorial utterances to be spoken for the object. """ utterances = tutorialgenerator.TutorialGenerator.\ _getTutorialForText(self, obj, alreadyFocused, forceTutorial) if utterances and self._script.isSearchEntry(obj): # Translators: This is the tutorial string associated with a # specific search field in the Packagemanager application. # It is designed to inform the user how to move directly to # the search results after the search has been completed. # utterances.append(_("Use Ctrl+L to move focus to the results.")) self._debugGenerator("_getTutorialForText", obj, alreadyFocused, utterances) return utterances
def _getBrailleRegionsForToggleButton(self, obj): """Get the braille for a radio button. If the button already had focus, then only the state is displayed. Arguments: - obj: the check box Returns a list where the first element is a list of Regions to display and the second element is the Region which should get focus. """ self._debugGenerator("_getBrailleRegionsForRadioButton", obj) text = "" text = self._script.appendString(text, self._script.getDisplayedLabel(obj)) text = self._script.appendString(text, self._script.getDisplayedText(obj)) # First special toggle button is the one in the toolbar and # that it has no name Application should implement an # accessible name in this component, but until this is made We # speech/braille "display more options" when the focus is in # one of these toggle buttons. # roleList = [rolenames.ROLE_TOGGLE_BUTTON, rolenames.ROLE_TOOL_BAR] if self._script.isDesiredFocusedItem(obj, roleList) and not obj.name: text += _("Display more options") # Second special case is each one of the four graphics toggle # buttons in the main window Application should implement an # accessible relationship between the button and the label, # but until this is made we append for each one the button the # label that should be associated and its state (checked or # not) # rolesList = [rolenames.ROLE_TOGGLE_BUTTON,\ rolenames.ROLE_FILLER,\ rolenames.ROLE_FILLER,\ rolenames.ROLE_PANEL,\ rolenames.ROLE_PANEL] if self._script.isDesiredFocusedItem(obj, rolesList): debug.println(debug.LEVEL_FINEST, "planner.onFocus - main window: " \ + "one of the four graphic toggle buttons.") filler = obj.parent allLabels = self._script.findByRole(filler, rolenames.ROLE_LABEL) text += allLabels[0].name text = self._script.appendString( settings.brailleRadioButtonIndicators[ obj.state.count(atspi.Accessibility.STATE_CHECKED)], text) text = self._script.appendString(text, self._getTextForRole(obj)) regions = [] componentRegion = braille.Component(obj, text) regions.append(componentRegion) return [regions, componentRegion]
def _isSpellCheckListItemFocus(self, event): """Check if this event is for a list item in the spell checking dialog and whether it has a FOCUSED state. Arguments: - event: the Event Return True is this event is for a list item in the spell checking dialog and it doesn't have a FOCUSED state, Otherwise return False. """ rolesList = [pyatspi.ROLE_LIST_ITEM, \ pyatspi.ROLE_LIST, \ pyatspi.ROLE_DIALOG, \ pyatspi.ROLE_APPLICATION] if self.utilities.hasMatchingHierarchy(event.source, rolesList): dialog = event.source.parent.parent # Translators: this is what the name of the spell checking # dialog in Thunderbird begins with. The translated form # has to match what Thunderbird is using. We hate keying # off stuff like this, but we're forced to do so in this case. # if dialog.name.startswith(_("Check Spelling")): state = event.source.getState() if not state.contains(pyatspi.STATE_FOCUSED): return True return False
def _generateDisplayedText(self, obj, **args): """Returns an array of strings for use by braille that represents all the text being displayed by the object. [[[WDW - consider returning an empty array if this is not a text object.]]] """ result = [] # This is the black triangle at the far right of the toolbar. # handleRibbonButton = \ obj and not obj.name \ and obj.getRole() == pyatspi.ROLE_TOGGLE_BUTTON \ and obj.parent.getRole() == pyatspi.ROLE_TOOL_BAR # This is one of the Gantt, Tasks, Resources, etc., buttons on the # left hand side of the main window. # handleTabButton = \ obj and not obj.name \ and obj.getRole() == pyatspi.ROLE_TOGGLE_BUTTON \ and obj.parent.getRole() == pyatspi.ROLE_FILLER \ and len(obj.parent) == 2 if handleRibbonButton: result.append(_("Display more options")) elif handleTabButton: result.append(self._script.utilities.displayedText(obj.parent[1])) else: result.extend( braille_generator.BrailleGenerator._generateDisplayedText( self, obj, **args)) return result
def onChildrenChanged(self, event): """Called whenever a child object changes in some way. Arguments: - event: the text inserted Event """ # Check to see if a new chat room tab has been created and if it # has, then announce its name. See bug #469098 for more details. # if event.type.startswith("object:children-changed:add"): rolesList = [pyatspi.ROLE_PAGE_TAB_LIST, pyatspi.ROLE_FILLER, pyatspi.ROLE_FRAME] if self.utilities.hasMatchingHierarchy(event.source, rolesList): # As it's possible to get this component hierarchy in other # places than the chat room (i.e. the Preferences dialog), # we check to see if the name of the frame is the same as one # of its children. If it is, then it's a chat room tab event. # For a final check, we only announce the new chat tab if the # last child has a name. # nameFound = False frameName = event.source.parent.parent.name for child in event.source: if frameName and (frameName == child.name): nameFound = True if nameFound: child = event.source[-1] if child.name: line = _("New chat tab %s") % child.name speech.speak(line)
def _generateLabelAndName(self, obj, **args): """Gets the label and the name if the name is different from the label. """ result = [] # This is the black triangle at the far right of the toolbar. # handleRibbonButton = \ obj and not obj.name \ and obj.getRole() == pyatspi.ROLE_TOGGLE_BUTTON \ and obj.parent.getRole() == pyatspi.ROLE_TOOL_BAR # This is one of the Gantt, Tasks, Resources, etc., buttons on the # left hand side of the main window. # handleTabButton = \ obj and not obj.name \ and obj.getRole() == pyatspi.ROLE_TOGGLE_BUTTON \ and obj.parent.getRole() == pyatspi.ROLE_FILLER \ and len(obj.parent) == 2 if handleRibbonButton: result.append(_("Display more options")) elif handleTabButton: result.append(self._script.utilities.displayedText(obj.parent[1])) else: result.extend( speech_generator.SpeechGenerator._generateLabelAndName( self, obj, **args)) return result
def onWindowCreate(self, event): """Called whenever a window is created in the notify-osd application. Arguments: - event: the Event. """ try: ivalue = event.source.queryValue() value = ivalue.currentValue except NotImplementedError: value = -1 utterances = [] message = "" if value < 0: # Translators: This denotes a notification to the user of some sort. # utterances.append(_('Notification')) utterances.append(self.voices.get(settings.SYSTEM_VOICE)) message = '%s %s' % (event.source.name, event.source.description) utterances.append(message) utterances.append(self.voices.get(settings.DEFAULT_VOICE)) else: # A gauge notification, e.g. the Ubuntu volume notification that # appears when you press the multimedia keys. # message = '%s %d' % (event.source.name, value) utterances.append(message) utterances.append(self.voices.get(settings.SYSTEM_VOICE)) speech.speak(utterances, None, True) self.displayBrailleMessage(message, flashTime=settings.brailleFlashTime) notification_messages.saveMessage(message)
def onChildrenChanged(self, event): """Called whenever a child object changes in some way. Arguments: - event: the text inserted Event """ # Check to see if a new chat room tab has been created and if it # has, then announce its name. See bug #469098 for more details. # if event.type.startswith("object:children-changed:add"): rolesList = [rolenames.ROLE_PAGE_TAB_LIST, \ rolenames.ROLE_FILLER, \ rolenames.ROLE_FRAME] if self.isDesiredFocusedItem(event.source, rolesList): childCount = event.source.childCount # As it's possible to get this component hierarchy in other # places than the chat room (i.e. the Preferences dialog), # we check to see if the name of the frame is the same as one # of its children. If it is, then it's a chat room tab event. # For a final check, we only announce the new chat tab if the # last child has a name. # nameFound = False frameName = event.source.parent.parent.name for i in range(0, childCount): child = event.source.child(i) if frameName and (frameName == child.name): nameFound = True if nameFound: child = event.source.child(childCount - 1) if child.name: line = _("New chat tab %s") % child.name speech.speak(line)
def _tableCellPresentation(self, cell, arg): """Presents the table cell or indicates that one was not found. Overridden here to avoid the double-speaking of the dynamic headers. Arguments: - obj: the accessible object under consideration. - arg: an optional argument which may need to be included in the criteria (e.g. the level of a heading). """ # TODO - JD: This really should be dealt with via a formatting # string, once we work out how to implement formatting strings # throughout the Gecko code. In the meantime, this method will # result in a consistent user experience between applications. # if not cell: return if settings.speakCellHeaders: self._presentCellHeaders(cell, arg) [obj, characterOffset] = self._getCaretPosition(cell) self._setCaretPosition(obj, characterOffset) self._script.updateBraille(obj) blank = self._isBlankCell(cell) if not blank: for child in cell: speech.speak(self._script.utilities.displayedText(child)) else: # Translators: "blank" is a short word to mean the # user has navigated to an empty line. # speech.speak(_("blank")) if settings.speakCellCoordinates: [row, col] = self.getCellCoordinates(cell) # Translators: this represents the (row, col) position of # a cell in a table. # self._script.presentMessage(_("Row %(row)d, column %(column)d.") \ % {"row" : row + 1, "column" : col + 1}) spanString = self._getCellSpanInfo(cell) if spanString and settings.speakCellSpan: self._script.presentMessage(spanString)
def onNameChanged(self, event): """Called whenever a property on an object changes. Arguments: - event: the Event """ obj = event.source # If the user has just deleted an open mail message, then we want to # try to speak the new name of the open mail message frame and also # present the first line of that message to be consistent with what # we do when a new message window is opened. See bug #540039 for more # details. # rolesList = [pyatspi.ROLE_DOCUMENT_FRAME, pyatspi.ROLE_INTERNAL_FRAME, pyatspi.ROLE_FRAME, pyatspi.ROLE_APPLICATION] if self.utilities.hasMatchingHierarchy(event.source, rolesList): lastKey, mods = self.utilities.lastKeyAndModifiers() if lastKey == "Delete": speech.speak(obj.name) [obj, offset] = self.findFirstCaretContext(obj, 0) self.setCaretPosition(obj, offset) return # If we get a "object:property-change:accessible-name" event for # the first item in the Suggestions lists for the spell checking # dialog, then speak the first two labels in that dialog. These # will by the "Misspelled word:" label and the currently misspelled # word. See bug #535192 for more details. # rolesList = [pyatspi.ROLE_LIST_ITEM, pyatspi.ROLE_LIST, pyatspi.ROLE_DIALOG, pyatspi.ROLE_APPLICATION] if self.utilities.hasMatchingHierarchy(obj, rolesList): dialog = obj.parent.parent # Translators: this is what the name of the spell checking # dialog in Thunderbird begins with. The translated form # has to match what Thunderbird is using. We hate keying # off stuff like this, but we're forced to do so in this case. # if dialog.name.startswith(_("Check Spelling")): if obj.getIndexInParent() == 0: badWord = self.utilities.displayedText(dialog[1]) if self.textArea != None: # If we have a handle to the Thunderbird message text # area, then extract out all the text objects, and # create a list of all the words found in them. # allTokens = [] text = self.utilities.substring(self.textArea, 0, -1) tokens = text.split() allTokens += tokens self.speakMisspeltWord(allTokens, badWord)
def setupInputEventHandlers(self): debug.println(self.debugLevel, "gnome-mud.setupInputEventHandlers.") default.Script.setupInputEventHandlers(self) self.inputEventHandlers["readPreviousMessageHandler"] = \ input_event.InputEventHandler( Script.readPreviousMessage, _("Read the latest n messages in the incoming messages text \ area."))
def _generateTableCellRow(self, obj, **args): """Get the speech for a table cell row or a single table cell if _settingsManager.getSetting('readTableCellRow') is False. If this isn't inside a spread sheet, just return the utterances returned by the default table cell speech handler. Arguments: - obj: the table cell Returns a list of utterances to be spoken for the object. """ result = [] if self._script.isSpreadSheetCell(obj): if _settingsManager.getSetting('readTableCellRow'): parent = obj.parent parentTable = parent.queryTable() index = self._script.utilities.cellIndex(obj) row = parentTable.getRowAtIndex(index) column = parentTable.getColumnAtIndex(index) # This is an indication of whether we should speak all the # table cells (the user has moved focus up or down a row), # or just the current one (focus has moved left or right in # the same row). # speakAll = True if "lastRow" in self._script.pointOfReference and \ "lastColumn" in self._script.pointOfReference: pointOfReference = self._script.pointOfReference speakAll = (pointOfReference["lastRow"] != row) or \ ((row == 0 or row == parentTable.nRows-1) and \ pointOfReference["lastColumn"] == column) if speakAll: [startIndex, endIndex] = \ self._script.getSpreadSheetRowRange(obj) for i in range(startIndex, endIndex+1): cell = parentTable.getAccessibleAt(row, i) showing = cell.getState().contains( \ pyatspi.STATE_SHOWING) if showing: result.extend(self._generateRealTableCell( cell, **args)) else: result.extend(self._generateRealTableCell(obj, **args)) else: result.extend(self._generateRealTableCell(obj, **args)) else: result.extend( speech_generator.SpeechGenerator._generateTableCellRow( self, obj, **args)) if not len(result) \ and _settingsManager.getSetting('speakBlankLines'): # Translators: "blank" is a short word to mean the # user has navigated to an empty line. # result.append(_("blank")) return result
def _speakEnclosingPanel(self, obj): """Speak the enclosing panel for the object, if it is named. Going two containers up the hierarchy appears to be far enough to find a named panel, if there is one. Don't speak panels whose name begins with 'chrome://'""" self._debug("_speakEnclosingPanel") parent = obj.parent if not parent: return if parent.name != "" \ and (not parent.name.startswith("chrome://")) \ and (parent.role == rolenames.ROLE_PANEL): # Speak the parent panel name, but only once. # if parent.name != self._containingPanelName: self._containingPanelName = parent.name utterances = [] # Translators: this is the name of a panel in Thunderbird. # text = _("%s panel") % parent.name utterances.append(text) speech.speakUtterances(utterances) else: grandparent = parent.parent if grandparent \ and (grandparent.name != "") \ and (not grandparent.name.startswith("chrome://")) \ and (grandparent.role == rolenames.ROLE_PANEL): # Speak the grandparent panel name, but only once. # if grandparent.name != self._containingPanelName: self._containingPanelName = grandparent.name utterances = [] # Translators: this is the name of a panel in Thunderbird. # text = _("%s panel") % grandparent.name utterances.append(text) speech.speakUtterances(utterances)
def presentStatusBar(self, obj): """Presents information about the metacity status bar.""" # We have to stop speech, as Metacity has a key grab and we're not # getting keys # speech.stop() # Do we know about this window? Traverse through our list of apps # and go through the toplevel windows in each to see if we know # about this one. If we do, it's accessible. If we don't, it is # not. # found = False for app in self.getKnownApplications(): i = 0 while i < app.childCount: win = app.child(i) if win is None: print "app error " + app.name elif win.name == obj.name: found = True i = i + 1 text = obj.name # Translators: the "Workspace " and "Desk " strings are # the prefix of what metacity shows when you press # Ctrl+Alt and the left or right arrow keys to switch # between workspaces. The goal here is to find a match # with that prefix. # if text.startswith(_("Workspace ")) or text.startswith(_("Desk ")): pass elif not found: # Translators: inaccessible means that the application cannot # be read by Orca. This usually means the application is not # friendly to the assistive technology infrastructure. # text += ". " + _("inaccessible") braille.displayMessage(text) speech.speak(text)
def _speakEnclosingPanel(self, obj): """Speak the enclosing panel for the object, if it is named. Going two containers up the hierarchy appears to be far enough to find a named panel, if there is one. Don't speak panels whose name begins with 'chrome://'""" self._debug("_speakEnclosingPanel") parent = obj.parent if not parent: return if parent.name != "" \ and (not parent.name.startswith("chrome://")) \ and (parent.getRole() == pyatspi.ROLE_PANEL): # Speak the parent panel name, but only once. # if parent.name != self._containingPanelName: self._containingPanelName = parent.name utterances = [] # Translators: this is the name of a panel in Thunderbird. # text = _("%s panel") % parent.name utterances.append(text) speech.speak(utterances) else: grandparent = parent.parent if grandparent \ and (grandparent.name != "") \ and (not grandparent.name.startswith("chrome://")) \ and (grandparent.getRole() == pyatspi.ROLE_PANEL): # Speak the grandparent panel name, but only once. # if grandparent.name != self._containingPanelName: self._containingPanelName = grandparent.name utterances = [] # Translators: this is the name of a panel in Thunderbird. # text = _("%s panel") % grandparent.name utterances.append(text) speech.speak(utterances)
def _generateRoleName(self, obj, **args): if _settingsManager.getSetting('onlySpeakDisplayedText'): return [] result = [] acss = self.voice(speech_generator.SYSTEM) role = args.get('role', obj.getRole()) force = args.get('force', False) doNotSpeak = [pyatspi.ROLE_UNKNOWN] if not force: doNotSpeak.extend([pyatspi.ROLE_FORM, pyatspi.ROLE_LABEL, pyatspi.ROLE_MENU_ITEM, pyatspi.ROLE_LIST_ITEM, pyatspi.ROLE_PARAGRAPH, pyatspi.ROLE_SECTION, pyatspi.ROLE_TABLE_CELL]) if not (role in doNotSpeak): if role == pyatspi.ROLE_IMAGE: link = self._script.utilities.ancestorWithRole( obj, [pyatspi.ROLE_LINK], [pyatspi.ROLE_DOCUMENT_FRAME]) if link: result.append(self.getLocalizedRoleName(link)) if role == pyatspi.ROLE_HEADING: level = self._script.utilities.headingLevel(obj) if level: # Translators: the %(level)d is in reference to a heading # level in HTML (e.g., For <h3>, the level is 3) # and the %(role)s is in reference to a previously # translated rolename for the heading. # result.append(_("%(role)s level %(level)d") % { 'role': self.getLocalizedRoleName(obj, role), 'level': level}) else: result.append(self.getLocalizedRoleName(obj, role)) else: result.append(self.getLocalizedRoleName(obj, role)) if result: result.extend(acss) if role == pyatspi.ROLE_LINK \ and obj.childCount and obj[0].getRole() == pyatspi.ROLE_IMAGE: # If this is a link with a child which is an image, we # want to indicate that. # acss = self.voice(speech_generator.HYPERLINK) result.append(self.getLocalizedRoleName(obj[0])) result.extend(acss) return result
def setupInputEventHandlers(self): """Defines InputEventHandler fields for this script that can be called by the key and braille bindings. In this particular case, we just want to be able to add a handler to toggle whether we prefix chat room messages with the name of the chat room. """ debug.println(self.debugLevel, "gaim.setupInputEventHandlers.") default.Script.setupInputEventHandlers(self) self.inputEventHandlers["togglePrefixHandler"] = input_event.InputEventHandler( Script.togglePrefix, _("Toggle whether we prefix chat room messages with the name of the chat room.") ) # In gaim/pidgin, we are overriding the default script's bookmark # feature and keybindings to provide chat room message history. # self.inputEventHandlers["goToBookmark"] = input_event.InputEventHandler( Script.readPreviousMessage, _("Speak and braille a previous chat room message.") )
def togglePrefix(self, inputEvent): """ Toggle whether we prefix chat room messages with the name of the chat room. Arguments: - inputEvent: if not None, the input event that caused this action. """ global prefixChatMessage debug.println(self.debugLevel, "gaim.togglePrefix.") line = _("speak chat room name.") prefixChatMessage = not prefixChatMessage if not prefixChatMessage: line = _("Do not speak chat room name.") speech.speak(line) return True
def setupInputEventHandlers(self): """Defines InputEventHandler fields for this script that can be called by the key and braille bindings. In this particular case, we just want to be able to define our own sayAll() method. """ default.Script.setupInputEventHandlers(self) self.inputEventHandlers["sayAllHandler"] = \ input_event.InputEventHandler( Script.sayAll, _("Speaks entire document."))
def onWindowCreate(self, event): """Called whenever a window is created in the notification-daemon application. Arguments: - event: the Event. """ a = self.findByRole(event.source, rolenames.ROLE_LABEL) texts = [self.getDisplayedText(acc) for acc in a] # Translators: This denotes a notification to the user of some sort. # text = _('Notification %s') % ' '.join(texts) speech.speak(text, None, True)
def setupInputEventHandlers(self): """Defines InputEventHandler fields for this script that can be called by the key and braille bindings. In this particular case, we just want to be able to add a handler to toggle whether we prefix chat room messages with the name of the chat room. """ debug.println(self.debugLevel, "gaim.setupInputEventHandlers.") default.Script.setupInputEventHandlers(self) self.inputEventHandlers["togglePrefixHandler"] = \ input_event.InputEventHandler( Script.togglePrefix, _("Toggle whether we prefix chat room messages with the name of the chat room.")) # In gaim/pidgin, we are overriding the default script's bookmark # feature and keybindings to provide chat room message history. # self.inputEventHandlers["goToBookmark"] = \ input_event.InputEventHandler( Script.readPreviousMessage, _("Speak and braille a previous chat room message."))
def _generateToggleState(self, obj, **args): """Treat push buttons (which act like toggle buttons) and toggle buttons in the toolbar specially. This is so we can have more natural sounding speech such as "bold on", "bold off", etc.""" acss = self.voice(speech_generator.SYSTEM) result = [] role = args.get('role', obj.getRole()) if role in [pyatspi.ROLE_PUSH_BUTTON, pyatspi.ROLE_TOGGLE_BUTTON] \ and obj.parent.getRole() == pyatspi.ROLE_TOOL_BAR: if obj.getState().contains(pyatspi.STATE_CHECKED): # Translators: this represents the state of a check box # result.append(_("on")) else: # Translators: this represents the state of a check box # result.append(_("off")) result.extend(acss) elif role == pyatspi.ROLE_TOGGLE_BUTTON: result.extend(speech_generator.SpeechGenerator._generateToggleState( self, obj, **args)) return result
def addBookmark(self, inputEvent): """ Add an in-page accessible object bookmark for this key and webpage URI. """ # form bookmark dictionary key index = (inputEvent.hw_code, self.getURIKey()) # convert the current object to a path and bookmark it obj, characterOffset = self._script.getCaretContext() path = self._objToPath() self._bookmarks[index] = path, characterOffset # Translators: this announces that a bookmark has been entered # utterances = [(_('entered bookmark'))] utterances.extend(self._script.speechGenerator.generateSpeech(obj)) speech.speak(utterances)
def onWindowCreate(self, event): """Called whenever a window is created in the notification-daemon application. Arguments: - event: the Event. """ a = self.utilities.descendantsWithRole(event.source, pyatspi.ROLE_LABEL) print a texts = [self.utilities.displayedText(acc) for acc in a] # Translators: This denotes a notification to the user of some sort. # text = _('Notification %s') % ' '.join(texts) speech.speak(text, None, True)
def saveBookmarks(self, inputEvent): """ Save the bookmarks for this script. """ saved = {} # save obj as a path instead of an accessible for index, bookmark in self._bookmarks.iteritems(): saved[index] = bookmark[0], bookmark[1] try: self.saveBookmarksToDisk(saved) # Translators: this announces that a bookmark has been saved to # disk # self._script.presentMessage(_('bookmarks saved')) except IOError: # Translators: this announces that a bookmark could not be saved to # disk # self._script.presentMessage(_('bookmarks could not be saved')) # Notify the observers for o in self._saveObservers: o()
def onShowingChanged(self, event): """Callback for object:state-changed:showing accessibility events.""" obj = event.source if obj.getRole() != pyatspi.ROLE_PUSH_BUTTON \ or not obj.getState().contains(pyatspi.STATE_VISIBLE): return default.Script.onShowingChanged(self, event) # Translators: the "Stop" string must match what gnome-search-tool # is using. We hate keying off stuff like this, but we're forced # to do so in this case. if obj.name == _("Stop"): self.searching = True if not self.fileTable: frame = self.utilities.topLevelObject(obj) allTables = self.utilities.descendantsWithRole( frame, pyatspi.ROLE_TABLE) self.fileTable = allTables[0] GLib.idle_add(self._speakSearching) return # Translators: the "Find" string must match what gnome-search-tool # is using. We hate keying off stuff like this, but we're forced # to do so in this case. if obj.name == _("Find") and self.searching: self.searching = False self.presentMessage(messages.SEARCH_COMPLETE) if self.fileTable.getState().contains(pyatspi.STATE_SENSITIVE): try: fileCount = self.fileTable.queryTable().nRows self.presentMessage(messages.filesFound(fileCount)) except NotImplementedError: self.presentMessage(messages.FILES_NOT_FOUND) return default.Script.onShowingChanged(self, event)
def _speakSearching(self): """If we are still searching, let the user know. Then start another timer to go off again and repeat this process. """ if not self.searching: return False currentTime = time.time() if not self.startTime or \ (currentTime > (self.startTime + self.searchInterval)): speech.speak(_("Searching.")) self.startTime = time.time() return True
def getAppPreferencesGUI(self): """Return a GtkVBox contain the application unique configuration GUI items for the current application. """ global prefixChatMessage vbox = gtk.VBox(False, 0) vbox.set_border_width(12) gtk.Widget.show(vbox) # Translators: If this checkbox is checked, then Orca will speak # the name of the chat room. # label = _("Speak Chat Room name") self.speakNameCheckButton = gtk.CheckButton(label) gtk.Widget.show(self.speakNameCheckButton) gtk.Box.pack_start(vbox, self.speakNameCheckButton, False, False, 0) gtk.ToggleButton.set_active(self.speakNameCheckButton, prefixChatMessage) return vbox
def utterMessage(self, chatRoomName, message): """ Speak/braille a chat room message. messages are kept. Arguments: - chatRoomName: name of the chat room this message came from. - message: the chat room message. """ global prefixChatMessage text = "" if prefixChatMessage: if chatRoomName and chatRoomName != "": text += _("Message from chat room %s") % chatRoomName + " " if message and message != "": text += message if text != "": braille.displayMessage(text) speech.speak(text)
def onCaretMoved(self, event): """Called whenever the caret moves. Arguments: - event: the Event """ debug.printObjectEvent(self.debugLevel, event, event.source.toString()) # self.printAncestry(event.source) # If we've received a text caret moved event and the current locus # of focus is on the Find button on the Find dialog or the combo # box in the Find dialog and the last input event was a Return, # and if the current line contains the phrase we were looking for, # then speak the current text line, to give an indication of what # we've just found. # if self.isFocusOnFindDialog() \ and orca_state.lastNonModifierKeyEvent.event_string == "Return": debug.println(self.debugLevel, "gedit.onCaretMoved - find dialog.") allComboBoxes = self.findByRole(orca_state.locusOfFocus.app, rolenames.ROLE_COMBO_BOX) phrase = self.getDisplayedText(allComboBoxes[0]) [text, caretOffset, startOffset] = \ self.getTextLineAtCaret(event.source) if text.lower().find(phrase) != -1: # Translators: this indicates a find command succeeded in # finding something. # speech.speak(_("Phrase found.")) utterances = self.speechGenerator.getSpeech(event.source, True) speech.speakUtterances(utterances) # For everything else, pass the caret moved event onto the parent # class to be handled in the default way. default.Script.onCaretMoved(self, event)
def onStateChanged(self, event): """Called whenever an object's state changes. Arguments: - event: the Event """ debug.printObjectEvent(self.debugLevel, event, event.source.toString()) # self.printAncestry(event.source) rolesList = [rolenames.ROLE_PUSH_BUTTON, \ rolenames.ROLE_FILLER, \ rolenames.ROLE_FILLER, \ rolenames.ROLE_FILLER, \ rolenames.ROLE_FRAME, \ rolenames.ROLE_APPLICATION] visible = event.source.state.count( \ atspi.Accessibility.STATE_VISIBLE) # Check to see if we have just had an "object:state-changed:showing" # event for the Stop button. If the name is "Stop", and one of its # states is VISIBLE, that means we have started a search. As the # search progresses, regularly inform the user of this by speaking # "Searching" (assuming the search tool has focus). # # Translators: the "Stop" string must match what gnome-search-tool # is using. We hate keying off stuff like this, but we're forced # to do so in this case. # if self.isDesiredFocusedItem(event.source, rolesList) and \ event.source.name == _("Stop") and visible: debug.println(self.debugLevel, "gnome-search-tool.onNameChanged - " \ + "search started.") self.searching = True # If we don't already have a handle to the table containing the # list of files found, then get it now. # if not self.fileTable: frame = self.getTopLevel(event.source) allTables = self.findByRole(frame, rolenames.ROLE_TABLE) self.fileTable = allTables[0] gobject.idle_add(self._speakSearching) # Check to see if we have just had an "object:state-changed:showing" # event for the Find button. If the name is "Find", and one of its # states is VISIBLE and we are currently searching, that means we # have just stopped a search. Inform the user that the search is # complete and tell them how many files were found. # # Translators: the "Find" string must match what gnome-search-tool # is using. We hate keying off stuff like this, but we're forced # to do so in this case. # if self.isDesiredFocusedItem(event.source, rolesList) and \ event.source.name == _("Find") and visible and self.searching: debug.println(self.debugLevel, "gnome-search-tool.onNameChanged - " \ + "search completed.") self.searching = False speech.speak(_("Search complete.")) sensitive = self.fileTable.state.count( \ atspi.Accessibility.STATE_SENSITIVE) if sensitive: fileCount = self.fileTable.table.nRows noFilesString = ngettext("%d file found", "%d files found", fileCount) % fileCount speech.speak(noFilesString) else: speech.speak(_("No files found.")) # Pass the event onto the parent class to be handled in the default way. # default.Script.onStateChanged(self, event)
def onNameChanged(self, event): """Called whenever a property on an object changes. Arguments: - event: the Event """ brailleGen = self.brailleGenerator speechGen = self.speechGenerator debug.printObjectEvent(self.debugLevel, event, event.source.toString()) # self.printAncestry(event.source) # 1) check spelling dialog. # # Check to see if if we've had a property-change event for the # accessible name for the label containing the current misspelt # word in the check spelling dialog. # This (hopefully) means that the user has just corrected a # spelling mistake, in which case, speak/braille the current # misspelt word plus its context. # # Note that in order to make sure that this event is for the # check spelling dialog, a check is made of the localized name of the # frame. Translators for other locales will need to ensure that # their translation of this string matches what gedit uses in # that locale. rolesList = [ rolenames.ROLE_LABEL, rolenames.ROLE_PANEL, rolenames.ROLE_FILLER, rolenames.ROLE_FRAME ] if self.isDesiredFocusedItem(event.source, rolesList): frame = event.source.parent.parent.parent # Translators: this is the name of the "Check Spelling" window # in gedit and must be the same as what gedit uses. We hate # keying off stuff like this, but we're forced to do so in this # case. # if frame.name.startswith(_("Check Spelling")): debug.println(self.debugLevel, "gedit.onNameChanged - check spelling dialog.") self.readMisspeltWord(event, event.source.parent) # Fall-thru to process the event with the default handler. # 2) find dialog - phrase not found. # # If we've received an "object:property-change:accessible-name" for # the status bar and the current locus of focus is on the Find # button on the Find dialog or the combo box in the Find dialog # and the last input event was a Return and the name for the current # event source is "Phrase not found", then speak it. # # [[[TODO: richb - "Phrase not found" is spoken twice because we # apparently get two identical "object:property-change:accessible-name" # events.]]] # Translators: the "Phrase not found" is the result of a failed # find command. It must be the same as what gedit uses. We hate # keying off stuff like this, but we're forced to do so in this # case. # if event.source.role == rolenames.ROLE_STATUSBAR \ and self.isFocusOnFindDialog() \ and orca_state.lastNonModifierKeyEvent.event_string == "Return" \ and event.source.name == _("Phrase not found"): debug.println(self.debugLevel, "gedit.onNameChanged - phrase not found.") speech.speak(event.source.name) # Pass the event onto the parent class to be handled in the default way. default.Script.onNameChanged(self, event)
def locusOfFocusChanged(self, event, oldLocusOfFocus, newLocusOfFocus): """Called when the visual object with focus changes. Arguments: - event: if not None, the Event that caused the change - oldLocusOfFocus: Accessible that is the old locus of focus - newLocusOfFocus: Accessible that is the new locus of focus """ brailleGen = self.brailleGenerator speechGen = self.speechGenerator debug.printObjectEvent(self.debugLevel, event, event.source.toString()) # self.printAncestry(event.source) # 1) Text area (for caching handle for spell checking purposes). # # This works in conjunction with code in section 2). Check to see if # focus is currently in the gedit text area. If it is, then, if this # is the first time, save a pointer to the scroll pane which contains # the text being editted. # # Note that this drops through to then use the default event # processing in the parent class for this "focus:" event. rolesList = [ rolenames.ROLE_TEXT, rolenames.ROLE_SCROLL_PANE, rolenames.ROLE_FILLER, rolenames.ROLE_PAGE_TAB, rolenames.ROLE_PAGE_TAB_LIST, rolenames.ROLE_SPLIT_PANE ] if self.isDesiredFocusedItem(event.source, rolesList): debug.println(self.debugLevel, "gedit.locusOfFocusChanged - text area.") self.textArea = event.source.parent # Fall-thru to process the event with the default handler. # 2) check spelling dialog. # # Check to see if the Spell Check dialog has just appeared and got # focus. If it has, then speak/braille the current misspelt word # plus its context. # # Note that in order to make sure that this focus event is for the # check spelling dialog, a check is made of the localized name of the # option pane. Translators for other locales will need to ensure that # their translation of this string matches what gedit uses in # that locale. rolesList = [ rolenames.ROLE_TEXT, rolenames.ROLE_FILLER, rolenames.ROLE_PANEL, rolenames.ROLE_FILLER, rolenames.ROLE_FRAME ] if self.isDesiredFocusedItem(event.source, rolesList): frame = event.source.parent.parent.parent.parent # Translators: this is the name of the "Check Spelling" window # in gedit and must be the same as what gedit uses. We hate # keying off stuff like this, but we're forced to do so in this # case. # if frame.name.startswith(_("Check Spelling")): debug.println( self.debugLevel, "gedit.locusOfFocusChanged - check spelling dialog.") self.readMisspeltWord(event, event.source.parent.parent) # Fall-thru to process the event with the default handler. # For everything else, pass the focus event onto the parent class # to be handled in the default way. default.Script.locusOfFocusChanged(self, event, oldLocusOfFocus, newLocusOfFocus)
def locusOfFocusChanged(self, event, oldLocusOfFocus, newLocusOfFocus): """Called when the visual object with focus changes. Arguments: - event: if not None, the Event that caused the change - oldLocusOfFocus: Accessible that is the old locus of focus - newLocusOfFocus: Accessible that is the new locus of focus """ brailleGen = self.brailleGenerator speechGen = self.speechGenerator details = debug.getAccessibleDetails(self.debugLevel, event.source) debug.printObjectEvent(self.debugLevel, event, details) # [[[TODO - JD: what follows here should be replaced with methods # in this script's speech and braille generators. That will require # making each generator, moving this script into a new directory, # etc.]]] # # Here we handle the case when focus is in the "Work online/offline" # button near the status bar that has an image without a description. # We speak and braille "Online/Offline button" here, until the # developer of the application adds a description to the images # associated with the button, which shows the online or offline # work mode. # rolesList = [ pyatspi.ROLE_PUSH_BUTTON, pyatspi.ROLE_FILLER, pyatspi.ROLE_FILLER, pyatspi.ROLE_FRAME ] # We are checking if the button with the focus is the button to # turn on/off the work mode in liferea. This push button is # hierarchically located in the main window of the application # (frame), inside a filler and inside another filler. # if self.utilities.hasMatchingHierarchy(event.source, rolesList): # If we are focusing this button we construct a utterance and # a braille region to speak/braille "online/offline button". # Here we declare utterances and add the localized string # "online/offline". # utterances = [] utterances.append(_("Work online / offline")) # Here we extend the utterances with the speech generator for # the object with focus (the push button). # utterances.extend(speechGen.generateSpeech(event.source)) # Finally we speak/braille the utterances/regions. # speech.speak(utterances) regions = brailleGen.generateBraille(event.source) regions[0].insert(0, self.getNewBrailleRegion(utterances[0] + " ")) self.displayBrailleRegions(regions) return # Here we handle the case when the focus is in the headlines table. # See comment #3 of bug #350233. # http://bugzilla.gnome.org/show_bug.cgi?id=350233 # if orca_state.locusOfFocus.getRole() == \ pyatspi.ROLE_TABLE_COLUMN_HEADER: table = event.source.parent hasRole = lambda x: x and x.getRole() == pyatspi.ROLE_TABLE_CELL cells = pyatspi.findAllDescendants(event.source, hasRole) eventsynthesizer.clickObject(cells[1], 1) default.Script.locusOfFocusChanged(self, event, oldLocusOfFocus, newLocusOfFocus)
def readMisspeltWord(self, event, panel): """Speak/braille the current misspelt word plus its context. The spell check dialog contains a "paragraph" which shows the context for the current spelling mistake. After speaking/brailling the default action for this component, that a selection of the surronding text from that paragraph with the misspelt word is also spoken. Arguments: - event: the event. - panel: the panel in the check spelling dialog containing the label with the misspelt word. """ # Braille the default action for this component. # self.updateBraille(orca_state.locusOfFocus) # Look for the label containing the misspelled word. # There will be three labels in the top panel in the Check # Spelling dialog. Look for the one that isn't a label to # another component. # allLabels = self.findByRole(panel, rolenames.ROLE_LABEL) for label in allLabels: # Translators: these are labels from the gedit spell checking # dialog and must be the same strings gedit uses. We hate # keying off stuff like this, but we're forced to do so in # in this case. # if label.name.startswith(_("Change to:")) or \ label.name.startswith(_("Misspelled word:")): continue else: badWord = label.name break # Note that we often get two or more of these focus or property-change # events each time there is a new misspelt word. We extract the # current text caret position and the misspelt word and compare # them against the values saved from the last time this routine # was called. If they are the same then we ignore it. if self.textArea != None: allText = self.findByRole(self.textArea, rolenames.ROLE_TEXT) caretPosition = allText[0].text.caretOffset debug.println(self.debugLevel, \ "gedit.readMisspeltWord: type=%s word=%s caret position=%d" \ % (event.type, badWord, caretPosition)) if (caretPosition == self.lastCaretPosition) and \ (badWord == self.lastBadWord) and \ (event.type == self.lastEventType): return # The indication that spell checking is complete is when the # "misspelt" word is set to "Completed spell checking". Ugh! # Try to detect this and let the user know. # # Translators: this string must be the same that is used by # gedit. We hate keying off stuff like this, but we're # forced to do so in this case. # if badWord == _("Completed spell checking"): utterance = _("Spell checking is complete.") speech.speak(utterance) utterance = _("Press Tab and Return to terminate.") speech.speak(utterance) return # If we have a handle to the gedit text area, then extract out # all the text objects, and create a list of all the words found # in them. # allTokens = [] for i in range(0, len(allText)): text = self.getText(allText[i], 0, -1) tokens = text.split() allTokens += tokens self.speakMisspeltWord(allTokens, badWord) # Save misspelt word information for comparison purposes # next time around. # self.lastCaretPosition = caretPosition self.lastBadWord = badWord self.lastEventType = event.type
def locusOfFocusChanged(self, event, oldLocusOfFocus, newLocusOfFocus): """Called when the visual object with focus changes. Arguments: - event: if not None, the Event that caused the change - oldLocusOfFocus: Accessible that is the old locus of focus - newLocusOfFocus: Accessible that is the new locus of focus """ brailleGen = self.brailleGenerator speechGen = self.speechGenerator debug.printObjectEvent(self.debugLevel, event, event.source.toString()) # Here we handle the case when focus is in the "Work online/offline" # button near the status bar that has an image without a description. # We speak and braille "Online/Offline button" here, until the # developer of the application adds a description to the images # associated with the button, which shows the online or offline # work mode. # rolesList = [ rolenames.ROLE_PUSH_BUTTON, rolenames.ROLE_FILLER, rolenames.ROLE_FILLER, rolenames.ROLE_FRAME ] # We are checking if the button with the focus is the button to # turn on/off the work mode in liferea. This push button is # hierarchically located in the main window of the application # (frame), inside a filler and inside another filler. # if self.isDesiredFocusedItem(event.source, rolesList): # If we are focusing this button we construct a utterance and # a braille region to speak/braille "online/offline button". # Here we declare utterances and add the localized string # "online/offline". # utterances = [] utterances.append(_("Work online / offline")) # Here we extend the utterances with the speech generator for # the object with focus (the push button). # utterances.extend(speechGen.getSpeech(event.source, False)) # Finally we speak/braille the utterances/regions. # speech.speakUtterances(utterances) regions = brailleGen.getBrailleRegions(event.source) regions[0].insert(0, braille.Region(utterances[0] + " ")) braille.displayRegions(regions) return # Here we handle the case when the focus is in the headlines table. # See comment #3 of bug #350233. # http://bugzilla.gnome.org/show_bug.cgi?id=350233 # if orca_state.locusOfFocus.role == rolenames.ROLE_TABLE_COLUMN_HEADER: table = event.source.parent cells = self.findByRole(table, rolenames.ROLE_TABLE_CELL) eventsynthesizer.clickObject(cells[1], 1) default.Script.locusOfFocusChanged(self, event, oldLocusOfFocus, newLocusOfFocus)
speech.speak(f.read()) f = os.popen("acpi") braille.displayMessage(f.read(80)) f.close() return True def decirHoraYFecha(script, inputEvent=None): speech.speak(strftime("Son las %H y %M, %A, %d de %B de %Y", localtime())) braille.displayMessage(strftime("%H:%M | %d/%m/%Y", localtime())) return True decirInfoBateriaHandler = input_event.InputEventHandler( decirInfoBateria, _("Lee el estado de la baterĂa")) decirHoraYFechaHandler = input_event.InputEventHandler( decirHoraYFecha, _("Dicela hora y fecha")) teclas = keybindings.KeyBindings() teclas.add( keybindings.KeyBinding("h", 1 << settings.MODIFIER_ORCA, 1 << settings.MODIFIER_ORCA, decirHoraYFechaHandler)) teclas.add( keybindings.KeyBinding("e", 1 << settings.MODIFIER_ORCA, 1 << settings.MODIFIER_ORCA, decirInfoBateriaHandler)) settings.keyBindingsMap = {} settings.keyBindingsMap["default"] = teclas
def _getSpeechForToggleButton(self, obj, already_focused): utterances=[] tmp=[] # Application should implement an accessible name in this # component, but until this is made We speech/braille "display # more options" when the focus is in one of these toggle # buttons. # roleList=[rolenames.ROLE_TOGGLE_BUTTON,\ rolenames.ROLE_TOOL_BAR] if self._script.isDesiredFocusedItem(obj, roleList) and not obj.name: if not already_focused: tmp.append(_("Display more options")) tmp.extend(self._getDefaultSpeech(obj, already_focused)) if obj.state.count(atspi.Accessibility.STATE_CHECKED): tmp.append(_("pressed")) else: tmp.append(_("not pressed")) utterances.extend(tmp) utterances.extend(self._getSpeechForObjectAvailability(obj)) else: if obj.state.count(atspi.Accessibility.STATE_CHECKED): utterances.append(_("pressed")) else: utterances.append(_("not pressed")) return utterances # Application should implement an accessible relationship # between the button and the label, but until this is made we # append for each one the button the label that should be # associated and its state (checked or not) # roleList = [rolenames.ROLE_TOGGLE_BUTTON,\ rolenames.ROLE_FILLER,\ rolenames.ROLE_FILLER,\ rolenames.ROLE_PANEL,\ rolenames.ROLE_PANEL] if self._script.isDesiredFocusedItem(obj, roleList): debug.println(debug.LEVEL_FINEST, "planner.onFocus - main window: " \ + "one of the four graphic toggle buttons.") if not already_focused: filler = obj.parent allLabels = self._script.findByRole(filler, rolenames.ROLE_LABEL) tmp.append(allLabels[0].name) tmp.extend(self._getDefaultSpeech(obj, already_focused)) if obj.state.count(atspi.Accessibility.STATE_CHECKED): tmp.append(_("pressed")) else: tmp.append(_("not pressed")) utterances.extend(tmp) utterances.extend(self._getSpeechForObjectAvailability(obj)) else: if obj.state.count(atspi.Accessibility.STATE_CHECKED): utterances.append(_("pressed")) else: utterances.append(_("not pressed")) return utterances return self._getSpeechForLabel(obj, already_focused)