def _iterNodesByType(self, nodeType, direction="next", pos=None): if not pos: pos = self.makeTextInfo(textInfos.POSITION_FIRST if direction == "next" else textInfos.POSITION_LAST) obj = pos.innerTextInfo._startObj if nodeType == "container": while obj != self.rootNVDAObject: if obj.role == controlTypes.Role.TABLE: ti = self.makeTextInfo(obj) yield browseMode.TextInfoQuickNavItem(nodeType, self, ti) return obj = obj.parent return roles = self.NODE_TYPES_TO_ROLES.get(nodeType) if not roles: raise NotImplementedError # Find the first embedded object in the requested direction. # Use the text, as enumerating IAccessibleHypertext means more cross-process calls. offset = pos.innerTextInfo._start._startOffset if direction == "next": text = obj.IAccessibleTextObject.text( offset + 1, obj.IAccessibleTextObject.nCharacters) embed = text.find(textUtils.OBJ_REPLACEMENT_CHAR) if embed != -1: embed += offset + 1 else: if offset > 0: text = obj.IAccessibleTextObject.text(0, offset) embed = text.rfind(textUtils.OBJ_REPLACEMENT_CHAR) else: # We're at the start; we can't go back any further. embed = -1 log.debug("%s embedded object from offset %d: %d" % (direction, offset, embed)) hli = -1 if embed == -1 else obj.iaHypertext.hyperlinkIndex(embed) while True: if hli != -1: for embObj in self._iterEmbeddedObjs(obj.iaHypertext, hli, direction): if embObj.role in roles: ti = self.makeTextInfo(embObj) yield browseMode.TextInfoQuickNavItem( nodeType, self, ti) # No more embedded objects here. # We started in an embedded object, so continue in the parent. if obj == self.rootNVDAObject: log.debug("At root, stopping") break # Can't go any further. log.debug("Continuing in parent") # Get the index of the embedded object we just came from. parent = obj.parent if not getattr(parent, 'IAccessibleTextObject', None): obj = parent continue hl = obj.IAccessibleObject.QueryInterface(IA2.IAccessibleHyperlink) offset = hl.startIndex obj = parent hli = obj.iaHypertext.hyperlinkIndex(offset) # Continue the walk from the next embedded object. hli += 1 if direction == "next" else -1
def UIAParagraphQuicknavIterator(document, position, direction="next"): if position: curPosition = position else: curPosition = document.makeTextInfo( textInfos.POSITION_LAST if direction == "previous" else textInfos.POSITION_FIRST) stop = False firstLoop = True while not stop: tempInfo = curPosition.copy() tempInfo.expand(textInfos.UNIT_CHARACTER) styleIDValue = getUIATextAttributeValueFromRange( tempInfo._rangeObj, UIA_StyleIdAttributeId) if styleIDValue == StyleId_Normal: if not firstLoop or not position: tempInfo.expand(textInfos.UNIT_PARAGRAPH) yield browseMode.TextInfoQuickNavItem("paragraph", document, tempInfo) stop = (curPosition.move(textInfos.UNIT_PARAGRAPH, 1 if direction == "next" else -1) == 0) firstLoop = False