예제 #1
0
    def nodeLevel(self, obj):
        """ Determines the level of at which this object is at by using
        the object attribute 'level'.  To be consistent with the default
        nodeLevel() this value is 0-based (Gecko return is 1-based) """

        if obj is None or obj.getRole() == pyatspi.ROLE_HEADING \
           or (obj.parent and obj.parent.getRole() == pyatspi.ROLE_MENU):
            return -1

        try:
            state = obj.getState()
        except:
            return -1
        else:
            if state.contains(pyatspi.STATE_DEFUNCT):
                # Yelp (or perhaps the work-in-progress a11y patch)
                # seems to be guilty of this.
                #
                #print "nodeLevel - obj is defunct", obj
                debug.println(debug.LEVEL_WARNING,
                              "nodeLevel - obj is defunct")
                debug.printStack(debug.LEVEL_WARNING)
                return -1

        try:
            attrs = obj.getAttributes()
        except:
            attrs = None
        if attrs is None:
            return -1
        for attr in attrs:
            if attr.startswith("level:"):
                return int(attr[6:]) - 1
        return -1
예제 #2
0
    def getObjectsFromEOCs(self, obj, offset=None, boundary=None):
        """Expands the current object replacing EMBEDDED_OBJECT_CHARACTERS
        with [obj, startOffset, endOffset, string] tuples.

        Arguments
        - obj: the object whose EOCs we need to expand into tuples
        - offset: the character offset after which
        - boundary: the pyatspi text boundary type

        Returns a list of object tuples.
        """

        if not obj:
            return []

        elif boundary and obj.getRole() == pyatspi.ROLE_TABLE:
            if obj[0] and obj[0].getRole() in [pyatspi.ROLE_CAPTION,
                                               pyatspi.ROLE_LIST]:
                obj = obj[0]
            else:
                obj = obj.queryTable().getAccessibleAt(0, 0)

            if not obj:
                debug.printStack(debug.LEVEL_WARNING)
                return []

        objects = []
        text = self.queryNonEmptyText(obj)
        if text:
            if offset == None:
                offset = max(0, text.caretOffset)

            if boundary:
                [string, start, end] = self._getTextAtOffset(obj, offset, boundary)
                if end == -1:
                    end = text.characterCount
            else:
                start = offset
                end = text.characterCount
                string = text.getText(start, end)
        else:
            string = ""
            start = 0
            end = 1

        unicodeText = string
        objects.append([obj, start, end, unicodeText])

        pattern = re.compile(self._script.EMBEDDED_OBJECT_CHARACTER)
        matches = re.finditer(pattern, unicodeText)

        offset = 0
        for m in matches:
            # Adjust the last object's endOffset to the last character
            # before the EOC.
            #
            childOffset = m.start(0) + start
            lastObj = objects[-1]
            lastObj[2] = childOffset
            if lastObj[1] == lastObj[2]:
                # A zero-length object is an indication of something
                # whose sole contents was an EOC.  Delete it from the
                # list.
                #
                objects.pop()
            else:
                # Adjust the string to reflect just this segment.
                #
                lastObj[3] = unicodeText[offset:m.start(0)]

            offset = m.start(0) + 1
 
            # Recursively tack on the child's objects.
            #
            childIndex = self._script.getChildIndex(obj, childOffset)
            child = obj[childIndex]
            objects.extend(self.getObjectsFromEOCs(child, 0, boundary))

            # Tack on the remainder of the original object, if any.
            #
            if end > childOffset + 1:
                restOfText = unicodeText[offset:len(unicodeText)]
                objects.append([obj, childOffset + 1, end, restOfText])
 
        if obj.getRole() in [pyatspi.ROLE_IMAGE, pyatspi.ROLE_TABLE]:
            # Imagemaps that don't have alternative text won't implement
            # the text interface, but they will have children (essentially
            # EOCs) that we need to get. The same is true for tables.
            #
            toAdd = []
            for child in obj:
                toAdd.extend(self.getObjectsFromEOCs(child, 0, boundary))
            if len(toAdd):
                if self.isSameObject(objects[-1][0], obj):
                    objects.pop()
                objects.extend(toAdd)

        return objects