Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/tests/tree.py
blob: 6f6100475272890f4cce67cea8794733fa0a11b6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import time

from gi.repository import Atspi

def get_root():
    return Node(Atspi.get_desktop(0))

def _retry_find(func):
    def wrapped(*args, **kwargs):
        result = None
        n_retries = 1

        while n_retries <= 10:
            print "Try %d, name=%s role_name=%s" % \
                  (n_retries,
                   kwargs.get("name", None),
                   kwargs.get("role_name", None))

            result = func(*args, **kwargs)
            expect_none = kwargs.get("expect_none", False)
            if (not expect_none and result) or \
               (expect_none and not result):
                return result

            time.sleep(5)
            n_retries = n_retries + 1

        get_root().dump()

        return result

    return wrapped

class Node:
    def __init__(self, accessible):
        self._accessible = accessible

    def dump(self):
        self._crawl_accessible(self, 0)

    def do_action(self, name):
        for i in range(self._accessible.get_n_actions()):
            if Atspi.Action.get_name(self._accessible, i) == name:
                self._accessible.do_action(i)

    def click(self, button=1):
        point = self._accessible.get_position(Atspi.CoordType.SCREEN)
        Atspi.generate_mouse_event(point.x, point.y, "b%sc" % button)

    @property
    def name(self):
        return self._accessible.get_name()

    @property
    def role_name(self):
        return self._accessible.get_role_name()

    @property
    def text(self):
        return Atspi.Text.get_text(self._accessible, 0, -1)

    def get_children(self):
        children = []

        for i in range(self._accessible.get_child_count()):
            child = self._accessible.get_child_at_index(i)

            # We sometimes get none children from atspi
            if child is not None:
                children.append(Node(child))

        return children

    @_retry_find
    def find_children(self, name=None, role_name=None):
        def predicate(node):
            return self._predicate(node, name, role_name)

        descendants = []
        self._find_all_descendants(self, predicate, descendants)
        if not descendants:
            return []

        return descendants

    @_retry_find
    def find_child(self, name=None, role_name=None, expect_none=False):
        def predicate(node):
            return self._predicate(node, name, role_name)

        node = self._find_descendant(self, predicate)
        if node is None:
            return None

        return node

    def __str__(self):
        return "[%s | %s]" % (self.name, self.role_name)

    def _predicate(self, node, name, role_name):
        if name is not None and name != node.name:
            return False

        if role_name is not None and role_name != node.role_name:
            return False

        return True

    def _find_descendant(self, node, predicate):
        if predicate(node):
            return node

        for child in node.get_children():
            descendant = self._find_descendant(child, predicate)
            if descendant is not None:
                return descendant

        return None

    def _find_all_descendants(self, node, predicate, matches):
        if predicate(node):
            matches.append(node)

        for child in node.get_children():
            self._find_all_descendants(child, predicate, matches)

    def _crawl_accessible(self, node, depth):
        print "  " * depth + str(node)

        for child in node.get_children():
            self._crawl_accessible(child, depth + 1)