def _get_UIAElementAtStartWithReplacedContent(self): """Fetches the deepest UIAElement at the start of the text range whose name has been overridden by the author (such as aria-label). """ element = self.UIAElementAtStart condition = createUIAMultiPropertyCondition( { UIAHandler.UIA_ControlTypePropertyId: self.UIAControlTypesWhereNameIsContent }, { UIAHandler.UIA_ControlTypePropertyId: UIAHandler.UIA_ListControlTypeId, UIAHandler.UIA_IsKeyboardFocusablePropertyId: True, }) # A part from the condition given, we must always match on the root of the document # so we know when to stop walking runtimeID = VARIANT() self.obj.UIAElement._IUIAutomationElement__com_GetCurrentPropertyValue( UIAHandler.UIA_RuntimeIdPropertyId, byref(runtimeID)) condition = UIAHandler.handler.clientObject.createOrCondition( UIAHandler.handler.clientObject.createPropertyCondition( UIAHandler.UIA_RuntimeIdPropertyId, runtimeID), condition) walker = UIAHandler.handler.clientObject.createTreeWalker(condition) cacheRequest = UIAHandler.handler.clientObject.createCacheRequest() cacheRequest.addProperty(UIAHandler.UIA_ControlTypePropertyId) cacheRequest.addProperty(UIAHandler.UIA_IsKeyboardFocusablePropertyId) cacheRequest.addProperty(UIAHandler.UIA_NamePropertyId) cacheRequest.addProperty(UIAHandler.UIA_AriaPropertiesPropertyId) element = walker.normalizeElementBuildCache(element, cacheRequest) while element and not UIAHandler.handler.clientObject.compareElements( element, self.obj.UIAElement): # Interactive lists controlType = element.getCachedPropertyValue( UIAHandler.UIA_ControlTypePropertyId) if controlType == UIAHandler.UIA_ListControlTypeId: isFocusable = element.getCachedPropertyValue( UIAHandler.UIA_IsKeyboardFocusablePropertyId) if isFocusable: return element # Nodes with an aria label or labelledby attribute name = element.getCachedPropertyValue( UIAHandler.UIA_NamePropertyId) if name: ariaProperties = element.getCachedPropertyValue( UIAHandler.UIA_AriaPropertiesPropertyId) if ('label=' in ariaProperties) or ('labelledby=' in ariaProperties): return element try: textRange = self.obj.UIATextPattern.rangeFromChild(element) except COMError: return text = textRange.getText(-1) if not text or text.isspace(): return element element = walker.getParentElementBuildCache(element, cacheRequest)
def getChildren(self, obj=None): if obj is None: obj = self # Collecting all children as a single request in order to make this real fast - code adopted from Outlook appModule childrenCacheRequest = UIAHandler.handler.baseCacheRequest.clone() childrenCacheRequest.addProperty(UIAHandler.UIA_NamePropertyId) childrenCacheRequest.addProperty( UIAHandler.UIA_TableItemColumnHeaderItemsPropertyId) childrenCacheRequest.TreeScope = UIAHandler.TreeScope_Children # We must filter the children for just text and image elements otherwise getCachedChildren fails completely in conversation view. childrenCacheRequest.treeFilter = createUIAMultiPropertyCondition({ UIAHandler.UIA_ControlTypePropertyId: [ UIAHandler.UIA_TextControlTypeId, UIAHandler.UIA_ImageControlTypeId ] }) cachedChildren = obj.UIAElement.buildUpdatedCache( childrenCacheRequest).getCachedChildren() return cachedChildren
def HeadingControlQuicknavIterator(itemType, document, position, direction="next"): """ A helper for L{UIAWebTreeInterceptor._iterNodesByType} that specifically yields L{HeadingControlQuickNavItem} objects found in the given document, starting the search from the given position, searching in the given direction. See L{browseMode._iterNodesByType} for details on these specific arguments. """ # Some UI Automation web implementations expose all headings as UIA elements # with a controlType of text, and a level. # Thus we can quickly search for these. # However, sometimes when ARIA is used, # the level on the element may not match the level in the text attributes. # Therefore we need to search for all levels 1 through 6, # even if a specific level is specified. # Though this is still much faster than searching text attributes alone # #9078: this must be wrapped inside a list, as Python 3 will treat this as iteration. levels = list(range(1, 7)) condition = createUIAMultiPropertyCondition({ UIAHandler.UIA_ControlTypePropertyId: UIAHandler.UIA_TextControlTypeId, UIAHandler.UIA_LevelPropertyId: levels }) levelString = itemType[7:] itemIter = UIAControlQuicknavIterator(itemType, document, position, condition, direction=direction, itemClass=HeadingControlQuickNavItem) for item in itemIter: # Verify this is the correct heading level via text attributes if item.level and (not levelString or levelString == str(item.level)): yield item
def _get_name(self): textList=[] if controlTypes.State.EXPANDED in self.states: textList.append(controlTypes.State.EXPANDED.displayString) elif controlTypes.State.COLLAPSED in self.states: textList.append(controlTypes.State.COLLAPSED.displayString) selection=None if self.appModule.nativeOm: try: selection=self.appModule.nativeOm.activeExplorer().selection.item(1) except COMError: pass if selection: try: unread=selection.unread except COMError: unread=False # Translators: when an email is unread if unread: textList.append(_("unread")) try: mapiObject=selection.mapiObject except COMError: mapiObject=None if mapiObject: v=comtypes.automation.VARIANT() res=NVDAHelper.localLib.nvdaInProcUtils_outlook_getMAPIProp( self.appModule.helperLocalBindingHandle, self.windowThreadID, mapiObject, PR_LAST_VERB_EXECUTED, ctypes.byref(v) ) if res==S_OK: verbLabel=executedVerbLabels.get(v.value,None) if verbLabel: textList.append(verbLabel) try: attachmentCount=selection.attachments.count except COMError: attachmentCount=0 # Translators: when an email has attachments if attachmentCount>0: textList.append(_("has attachment")) try: importance=selection.importance except COMError: importance=1 importanceLabel=importanceLabels.get(importance) if importanceLabel: textList.append(importanceLabel) try: messageClass=selection.messageClass except COMError: messageClass=None if messageClass=="IPM.Schedule.Meeting.Request": # Translators: the email is a meeting request textList.append(_("meeting request")) childrenCacheRequest=UIAHandler.handler.baseCacheRequest.clone() childrenCacheRequest.addProperty(UIAHandler.UIA_NamePropertyId) childrenCacheRequest.addProperty(UIAHandler.UIA_TableItemColumnHeaderItemsPropertyId) childrenCacheRequest.TreeScope=UIAHandler.TreeScope_Children # We must filter the children for just text and image elements otherwise getCachedChildren fails completely in conversation view. childrenCacheRequest.treeFilter=createUIAMultiPropertyCondition({UIAHandler.UIA_ControlTypePropertyId:[UIAHandler.UIA_TextControlTypeId,UIAHandler.UIA_ImageControlTypeId]}) cachedChildren=self.UIAElement.buildUpdatedCache(childrenCacheRequest).getCachedChildren() if not cachedChildren: # There are no children # This is unexpected here. log.debugWarning("Unable to get relevant children for UIAGridRow", stack_info=True) return super(UIAGridRow, self).name for index in range(cachedChildren.length): e=cachedChildren.getElement(index) UIAControlType=e.cachedControlType UIAClassName=e.cachedClassName # We only want to include particular children. # We only include the flagField if the object model's flagIcon or flagStatus is set. # Stops us from reporting "unflagged" which is too verbose. if selection and UIAClassName=="FlagField": try: if not selection.flagIcon and not selection.flagStatus: continue except COMError: continue # the category field should only be reported if the objectModel's categories property actually contains a valid string. # Stops us from reporting "no categories" which is too verbose. elif selection and UIAClassName=="CategoryField": try: if not selection.categories: continue except COMError: continue # And we don't care about anything else that is not a text element. elif UIAControlType!=UIAHandler.UIA_TextControlTypeId: continue name=e.cachedName columnHeaderTextList=[] if name and config.conf['documentFormatting']['reportTableHeaders']: columnHeaderItems=e.getCachedPropertyValueEx(UIAHandler.UIA_TableItemColumnHeaderItemsPropertyId,True) else: columnHeaderItems=None if columnHeaderItems: columnHeaderItems=columnHeaderItems.QueryInterface(UIAHandler.IUIAutomationElementArray) for index in range(columnHeaderItems.length): columnHeaderItem=columnHeaderItems.getElement(index) columnHeaderTextList.append(columnHeaderItem.currentName) columnHeaderText=" ".join(columnHeaderTextList) if columnHeaderText: text=u"{header} {name}".format(header=columnHeaderText,name=name) else: text=name if text: if UIAClassName=="FlagField": textList.insert(0,text) else: text+=u"," textList.append(text) return " ".join(textList)
def _iterNodesByType(self, nodeType, direction="next", pos=None): if nodeType.startswith("heading"): return UIAHeadingQuicknavIterator(nodeType, self, pos, direction=direction) elif nodeType == "error": return UIATextAttributeQuicknavIterator( ErrorUIATextInfoQuickNavItem, nodeType, self, pos, direction=direction) elif nodeType == "link": condition = UIAHandler.handler.clientObject.createPropertyCondition( UIAHandler.UIA_ControlTypePropertyId, UIAHandler.UIA_HyperlinkControlTypeId) return UIAControlQuicknavIterator(nodeType, self, pos, condition, direction) elif nodeType == "button": condition = UIAHandler.handler.clientObject.createPropertyCondition( UIAHandler.UIA_ControlTypePropertyId, UIAHandler.UIA_ButtonControlTypeId) return UIAControlQuicknavIterator(nodeType, self, pos, condition, direction) elif nodeType == "checkBox": condition = UIAHandler.handler.clientObject.createPropertyCondition( UIAHandler.UIA_ControlTypePropertyId, UIAHandler.UIA_CheckBoxControlTypeId) return UIAControlQuicknavIterator(nodeType, self, pos, condition, direction) elif nodeType == "radioButton": condition = UIAHandler.handler.clientObject.createPropertyCondition( UIAHandler.UIA_ControlTypePropertyId, UIAHandler.UIA_RadioButtonControlTypeId) return UIAControlQuicknavIterator(nodeType, self, pos, condition, direction) elif nodeType == "comboBox": condition = UIAHandler.handler.clientObject.createPropertyCondition( UIAHandler.UIA_ControlTypePropertyId, UIAHandler.UIA_ComboBoxControlTypeId) return UIAControlQuicknavIterator(nodeType, self, pos, condition, direction) elif nodeType == "graphic": condition = UIAHandler.handler.clientObject.createPropertyCondition( UIAHandler.UIA_ControlTypePropertyId, UIAHandler.UIA_ImageControlTypeId) return UIAControlQuicknavIterator(nodeType, self, pos, condition, direction) elif nodeType == "table": condition = createUIAMultiPropertyCondition({ UIAHandler.UIA_ControlTypePropertyId: [ UIAHandler.UIA_TableControlTypeId, UIAHandler.UIA_DataGridControlTypeId ] }) return UIAControlQuicknavIterator(nodeType, self, pos, condition, direction) elif nodeType == "separator": condition = UIAHandler.handler.clientObject.createPropertyCondition( UIAHandler.UIA_ControlTypePropertyId, UIAHandler.UIA_SeparatorControlTypeId) return UIAControlQuicknavIterator(nodeType, self, pos, condition, direction) elif nodeType == "focusable": condition = UIAHandler.handler.clientObject.createPropertyCondition( UIAHandler.UIA_IsKeyboardFocusablePropertyId, True) return UIAControlQuicknavIterator(nodeType, self, pos, condition, direction) elif nodeType == "list": condition = createUIAMultiPropertyCondition({ UIAHandler.UIA_ControlTypePropertyId: UIAHandler.UIA_ListControlTypeId, UIAHandler.UIA_IsKeyboardFocusablePropertyId: False }) return UIAControlQuicknavIterator(nodeType, self, pos, condition, direction) elif nodeType == "container": condition = createUIAMultiPropertyCondition( { UIAHandler.UIA.UIA_ControlTypePropertyId: UIAHandler.UIA.UIA_ListControlTypeId, UIAHandler.UIA.UIA_IsKeyboardFocusablePropertyId: False }, { UIAHandler.UIA.UIA_ControlTypePropertyId: [ UIAHandler.UIA.UIA_TableControlTypeId, UIAHandler.UIA.UIA_DataGridControlTypeId ] }, { UIAHandler.UIA_ControlTypePropertyId: UIAHandler.UIA.UIA_GroupControlTypeId, UIAHandler.UIA_AriaRolePropertyId: ["article"] }) return UIAControlQuicknavIterator(nodeType, self, pos, condition, direction) elif nodeType == "edit": condition = createUIAMultiPropertyCondition( { UIAHandler.UIA_ControlTypePropertyId: UIAHandler.UIA_EditControlTypeId, UIAHandler.UIA_ValueIsReadOnlyPropertyId: False }, { UIAHandler.UIA_ControlTypePropertyId: UIAHandler.UIA_ComboBoxControlTypeId, UIAHandler.UIA_IsTextPatternAvailablePropertyId: True }) return UIAControlQuicknavIterator(nodeType, self, pos, condition, direction) elif nodeType == "formField": condition = createUIAMultiPropertyCondition( { UIAHandler.UIA_ControlTypePropertyId: UIAHandler.UIA_EditControlTypeId, UIAHandler.UIA_ValueIsReadOnlyPropertyId: False }, { UIAHandler.UIA_ControlTypePropertyId: UIAHandler.UIA_ListControlTypeId, UIAHandler.UIA_IsKeyboardFocusablePropertyId: True }, { UIAHandler.UIA_ControlTypePropertyId: [ UIAHandler.UIA_CheckBoxControlTypeId, UIAHandler.UIA_RadioButtonControlTypeId, UIAHandler.UIA_ComboBoxControlTypeId, UIAHandler.UIA_ButtonControlTypeId ] }) return UIAControlQuicknavIterator(nodeType, self, pos, condition, direction) elif nodeType == "landmark": condition = UIAHandler.handler.clientObject.createNotCondition( UIAHandler.handler.clientObject.createPropertyCondition( UIAHandler.UIA.UIA_LandmarkTypePropertyId, 0)) return UIAControlQuicknavIterator(nodeType, self, pos, condition, direction) elif nodeType == "article": condition = createUIAMultiPropertyCondition({ UIAHandler.UIA_ControlTypePropertyId: UIAHandler.UIA.UIA_GroupControlTypeId, UIAHandler.UIA_AriaRolePropertyId: ["article"] }) return UIAControlQuicknavIterator(nodeType, self, pos, condition, direction) elif nodeType == "grouping": condition = UIAHandler.handler.clientObject.CreateAndConditionFromArray( [ UIAHandler.handler.clientObject.createPropertyCondition( UIAHandler.UIA.UIA_ControlTypePropertyId, UIAHandler.UIA.UIA_GroupControlTypeId), UIAHandler.handler.clientObject.createNotCondition( UIAHandler.handler.clientObject. createPropertyCondition( UIAHandler.UIA.UIA_NamePropertyId, "")) ]) return UIAControlQuicknavIterator(nodeType, self, pos, condition, direction) elif nodeType == "nonTextContainer": condition = createUIAMultiPropertyCondition( { UIAHandler.UIA_ControlTypePropertyId: UIAHandler.UIA_ListControlTypeId, UIAHandler.UIA_IsKeyboardFocusablePropertyId: True }, { UIAHandler.UIA_ControlTypePropertyId: UIAHandler.UIA_ComboBoxControlTypeId }) return UIAControlQuicknavIterator(nodeType, self, pos, condition, direction) elif nodeType == "embeddedObject": condition = createUIAMultiPropertyCondition({ UIAHandler.UIA_ControlTypePropertyId: UIAHandler.UIA_PaneControlTypeId, UIAHandler.UIA_AriaRolePropertyId: [u"application", u"alertdialog", u"dialog"] }) return UIAControlQuicknavIterator(nodeType, self, pos, condition, direction) raise NotImplementedError
def _get_name(self): textList=[] if controlTypes.STATE_EXPANDED in self.states: textList.append(controlTypes.stateLabels[controlTypes.STATE_EXPANDED]) elif controlTypes.STATE_COLLAPSED in self.states: textList.append(controlTypes.stateLabels[controlTypes.STATE_COLLAPSED]) selection=None if self.appModule.nativeOm: try: selection=self.appModule.nativeOm.activeExplorer().selection.item(1) except COMError: pass if selection: try: unread=selection.unread except COMError: unread=False # Translators: when an email is unread if unread: textList.append(_("unread")) try: mapiObject=selection.mapiObject except COMError: mapiObject=None if mapiObject: v=comtypes.automation.VARIANT() res=NVDAHelper.localLib.nvdaInProcUtils_outlook_getMAPIProp( self.appModule.helperLocalBindingHandle, self.windowThreadID, mapiObject, PR_LAST_VERB_EXECUTED, ctypes.byref(v) ) if res==S_OK: verbLabel=executedVerbLabels.get(v.value,None) if verbLabel: textList.append(verbLabel) try: attachmentCount=selection.attachments.count except COMError: attachmentCount=0 # Translators: when an email has attachments if attachmentCount>0: textList.append(_("has attachment")) try: importance=selection.importance except COMError: importance=1 importanceLabel=importanceLabels.get(importance) if importanceLabel: textList.append(importanceLabel) try: messageClass=selection.messageClass except COMError: messageClass=None if messageClass=="IPM.Schedule.Meeting.Request": # Translators: the email is a meeting request textList.append(_("meeting request")) childrenCacheRequest=UIAHandler.handler.baseCacheRequest.clone() childrenCacheRequest.addProperty(UIAHandler.UIA_NamePropertyId) childrenCacheRequest.addProperty(UIAHandler.UIA_TableItemColumnHeaderItemsPropertyId) childrenCacheRequest.TreeScope=UIAHandler.TreeScope_Children # We must filter the children for just text and image elements otherwise getCachedChildren fails completely in conversation view. childrenCacheRequest.treeFilter=createUIAMultiPropertyCondition({UIAHandler.UIA_ControlTypePropertyId:[UIAHandler.UIA_TextControlTypeId,UIAHandler.UIA_ImageControlTypeId]}) cachedChildren=self.UIAElement.buildUpdatedCache(childrenCacheRequest).getCachedChildren() if not cachedChildren: # There are no children # This is unexpected here. log.debugWarning("Unable to get relevant children for UIAGridRow", stack_info=True) return super(UIAGridRow, self).name for index in xrange(cachedChildren.length): e=cachedChildren.getElement(index) UIAControlType=e.cachedControlType UIAClassName=e.cachedClassName # We only want to include particular children. # We only include the flagField if the object model's flagIcon or flagStatus is set. # Stops us from reporting "unflagged" which is too verbose. if selection and UIAClassName=="FlagField": try: if not selection.flagIcon and not selection.flagStatus: continue except COMError: continue # the category field should only be reported if the objectModel's categories property actually contains a valid string. # Stops us from reporting "no categories" which is too verbose. elif selection and UIAClassName=="CategoryField": try: if not selection.categories: continue except COMError: continue # And we don't care about anything else that is not a text element. elif UIAControlType!=UIAHandler.UIA_TextControlTypeId: continue name=e.cachedName columnHeaderTextList=[] if name and config.conf['documentFormatting']['reportTableHeaders']: columnHeaderItems=e.getCachedPropertyValueEx(UIAHandler.UIA_TableItemColumnHeaderItemsPropertyId,True) else: columnHeaderItems=None if columnHeaderItems: columnHeaderItems=columnHeaderItems.QueryInterface(UIAHandler.IUIAutomationElementArray) for index in xrange(columnHeaderItems.length): columnHeaderItem=columnHeaderItems.getElement(index) columnHeaderTextList.append(columnHeaderItem.currentName) columnHeaderText=" ".join(columnHeaderTextList) if columnHeaderText: text=u"{header} {name}".format(header=columnHeaderText,name=name) else: text=name if text: if UIAClassName=="FlagField": textList.insert(0,text) else: text+=u"," textList.append(text) return " ".join(textList)