~ubuntu-branches/ubuntu/vivid/dogtail/vivid-proposed

« back to all changes in this revision

Viewing changes to dogtail/procedural.py

  • Committer: Bazaar Package Importer
  • Author(s): Jose Carlos Garcia Sogo
  • Date: 2006-12-16 10:57:30 UTC
  • mfrom: (1.2.1 upstream) (3.1.1 edgy)
  • Revision ID: james.westby@ubuntu.com-20061216105730-utt6mcidfssawo7j
Tags: 0.6.1-3
pyhton-at-spi has to be added as dependency (Closes: #402752)

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
All the classes here are intended to be single-instance, except for Action.
4
4
"""
5
5
__author__ = 'Zack Cerza <zcerza@redhat.com>'
 
6
##############################################################################
 
7
#                                                                            #
 
8
# WARNING: Here There Be Dragons (TM)                                        #
 
9
#                                                                            #
 
10
# If you don't understand how to use this API, you almost certainly don't    #
 
11
# want to read the code first. We make use of some very non-intuitive        #
 
12
# features of Python in order to make the API very simplistic. Therefore,    #
 
13
# you should probably only read this code if you're already familiar with    #
 
14
# some of Python's advanced features. You have been warned. ;)               #
 
15
#                                                                            #
 
16
##############################################################################
6
17
 
7
18
import tree
8
 
from predicate import GenericPredicate, IsADialogNamed
 
19
from predicate import GenericPredicate, IsADialogNamed, IsAnApplicationNamed
9
20
from config import config
 
21
import rawinput
10
22
from time import sleep
11
23
 
12
24
#FocusError = "FocusError: %s not found"
13
25
class FocusError(Exception):
14
 
        pass
 
26
    pass
 
27
 
 
28
import errors
 
29
def focusFailed():
 
30
    errors.warn('The requested object was not found')
15
31
 
16
32
ENOARGS = "At least one argument is needed"
17
33
 
18
34
class FocusBase:
19
 
        """
20
 
        The base for every class in the module. Does nothing special, really.
21
 
        """
22
 
        def __getattr__ (self, name):
23
 
                # Fold all the Node's AT-SPI properties into the Focus object.
24
 
                try: return getattr(self.node, name)
25
 
                except AttributeError: raise AttributeError, name
26
 
        
27
 
        def __setattr__ (self, name, value):
28
 
                # Fold all the Node's AT-SPI properties into the Focus object.
29
 
                if name == 'node': 
30
 
                        self.__dict__[name] = value
31
 
                else:
32
 
                        try: setattr(self.node, name, value)
33
 
                        except AttributeError: raise AttributeError, name
34
 
        
 
35
    """
 
36
    The base for every class in the module. Does nothing special, really.
 
37
    """
 
38
    node = None
 
39
 
 
40
    def __getattr__ (self, name):
 
41
        # Fold all the Node's AT-SPI properties into the Focus object.
 
42
        try: return getattr(self.node, name)
 
43
        except AttributeError: 
 
44
            raise AttributeError, name
 
45
 
 
46
    def __setattr__ (self, name, value):
 
47
        # Fold all the Node's AT-SPI properties into the Focus object.
 
48
        if name == 'node':
 
49
            self.__dict__[name] = value
 
50
        else:
 
51
            try: setattr(self.node, name, value)
 
52
            except AttributeError: 
 
53
                raise AttributeError, name
 
54
 
35
55
class FocusApplication (FocusBase):
36
 
        """
37
 
        Keeps track of which application is currently focused.
38
 
        """
39
 
        desktop = tree.root
40
 
        def __call__ (self, name = '', description = ''):
41
 
                """
42
 
                If name or description are specified, search for an application that matches and refocus on it.
43
 
                """
44
 
                if not name and not description:
45
 
                        raise TypeError, ENOARGS
46
 
                # search for an application.
47
 
                matched = False
48
 
                for app in self.desktop.children:
49
 
                        nameMatch = app.name == name
50
 
                        descriptionMatch = app.description == description
51
 
                        if nameMatch and descriptionMatch:
52
 
                                FocusApplication.node = app
53
 
                                FocusDialog.node = None
54
 
                                FocusWidget.node = None
55
 
                                matched = True
56
 
                                break
57
 
                if not matched: raise FocusError, name
 
56
    """
 
57
    Keeps track of which application is currently focused.
 
58
    """
 
59
    desktop = tree.root
 
60
    def __call__ (self, name):
 
61
        """
 
62
        Search for an application that matches and refocus on the given name.
 
63
        """
 
64
        try:
 
65
            predicate = IsAnApplicationNamed(name)
 
66
            app = self.desktop.findChild(predicate, recursive = False, retry = False)
 
67
        except tree.SearchError, desc:
 
68
            if config.fatalErrors: raise FocusError, name
 
69
            else:
 
70
                focusFailed()
 
71
                return
 
72
        if app: 
 
73
            FocusApplication.node = app
 
74
            FocusDialog.node = None
 
75
            FocusWidget.node = None
58
76
 
59
77
class FocusDesktop (FocusBase):
60
 
        """
61
 
        This isn't used yet, and may never be used.
62
 
        """     
63
 
        pass
 
78
    """
 
79
    This isn't used yet, and may never be used.
 
80
    """
 
81
    pass
64
82
 
65
83
class FocusDialog (FocusBase):
66
 
        """
67
 
        Keeps track of which dialog is currently focused.
68
 
        """
69
 
        def __call__ (self, name = '', description = ''):
70
 
                """
71
 
                If name or description are specified, search for a dialog that matches and refocus on it.
72
 
                """
73
 
                if not name and not description:
74
 
                        raise TypeError, ENOARGS
75
 
                result = None
76
 
                try:
77
 
                        result = FocusApplication.node.findChild(IsADialogNamed(name), requireResult=False, recursive = False)
78
 
                except AttributeError: pass
79
 
                if result: 
80
 
                        FocusDialog.node = result
81
 
                        FocusWidget.node = None
82
 
                else: raise FocusError, name
 
84
    """
 
85
    Keeps track of which dialog is currently focused.
 
86
    """
 
87
    def __call__ (self, name):
 
88
        """
 
89
        Search for a dialog that matches the given name and refocus on it.
 
90
        """
 
91
        result = None
 
92
        predicate = IsADialogNamed(name)
 
93
        try:
 
94
            result = FocusApplication.node.findChild(predicate, requireResult=False, recursive = False)
 
95
        except AttributeError: pass
 
96
        if result:
 
97
            FocusDialog.node = result
 
98
            FocusWidget.node = None
 
99
        else: 
 
100
            if config.fatalErrors: raise FocusError, predicate.debugName
 
101
            else:
 
102
                focusFailed()
 
103
                return
83
104
 
84
105
class FocusWidget (FocusBase):
85
 
        """
86
 
        Keeps track of which widget is currently focused.
87
 
        """
88
 
        def __call__ (self, name = '', roleName = '', description = ''):
89
 
                """
90
 
                If name, roleName or description are specified, search for a widget that matches and refocus on it.
91
 
                """
92
 
                if not name and not roleName and not description:
93
 
                        raise TypeError, ENOARGS
94
 
                
95
 
                # search for a widget.
96
 
                result = None
97
 
                try:
98
 
                        result = FocusWidget.node.findChild(GenericPredicate(name = name, roleName = roleName, description = description), requireResult = False, retry = False)
99
 
                except AttributeError: pass
100
 
                if result: FocusWidget.node = result
101
 
                else:
102
 
                        try:
103
 
                                result = FocusDialog.node.findChild(GenericPredicate(name = name, roleName = roleName, description = description), requireResult = False, retry = False)
104
 
                        except AttributeError: pass
105
 
                if result: FocusWidget.node = result
106
 
                else: 
107
 
                        try:
108
 
                                result = FocusApplication.node.findChild(GenericPredicate(name = name, roleName = roleName, description = description), requireResult = False, retry = False)
109
 
                                if result: FocusWidget.node = result
110
 
                        except AttributeError: raise FocusError, name
111
 
                
112
 
                if result == None:
113
 
                        FocusWidget.node = result
114
 
                        raise FocusError, name
 
106
    """
 
107
    Keeps track of which widget is currently focused.
 
108
    """
 
109
    def __call__ (self, name = '', roleName = '', description = ''):
 
110
        """
 
111
        If name, roleName or description are specified, search for a widget that matches and refocus on it.
 
112
        """
 
113
        if not name and not roleName and not description:
 
114
            raise TypeError, ENOARGS
 
115
 
 
116
        # search for a widget.
 
117
        result = None
 
118
        predicate = GenericPredicate(name = name, roleName = roleName, description = description)
 
119
        try:
 
120
            result = FocusWidget.node.findChild(predicate, requireResult = False, retry = False)
 
121
        except AttributeError: pass
 
122
        if result: FocusWidget.node = result
 
123
        else:
 
124
            try:
 
125
                result = FocusDialog.node.findChild(predicate, requireResult = False, retry = False)
 
126
            except AttributeError: pass
 
127
        if result: FocusWidget.node = result
 
128
        else:
 
129
            try:
 
130
                result = FocusApplication.node.findChild(predicate, requireResult = False, retry = False)
 
131
                if result: FocusWidget.node = result
 
132
            except AttributeError: 
 
133
                if config.fatalErrors: raise FocusError, name
 
134
                else:
 
135
                    focusFailed()
 
136
                    return
 
137
 
 
138
        if result == None:
 
139
            FocusWidget.node = result
 
140
            if config.fatalErrors: raise FocusError, predicate.debugName
 
141
            else:
 
142
                focusFailed()
 
143
                return
115
144
 
116
145
class Focus (FocusBase):
117
 
        """
118
 
        The container class for the focused application, dialog and widget.
119
 
        """
120
 
 
121
 
        def __getattr__ (self, name):
122
 
                raise AttributeError, name
123
 
        def __setattr__(self, name, value):
124
 
                if name in ('application', 'dialog', 'widget'):
125
 
                        self.__dict__[name] = value
126
 
                else:
127
 
                        raise AttributeError, name
128
 
        
129
 
        desktop = tree.root
130
 
        application = FocusApplication()
131
 
        app = application # shortcut :)
132
 
        dialog = FocusDialog()
133
 
        widget = FocusWidget()
134
 
        
135
 
        def button (self, name):
136
 
                """
137
 
                A shortcut to self.widget(name, roleName = 'push button')
138
 
                """
139
 
                self.widget(name = name, roleName = 'push button')
140
 
        
141
 
        def frame (self, name):
142
 
                """
143
 
                A shortcut to self.widget(name, roleName = 'frame')
144
 
                """
145
 
                self.widget(name = name, roleName = 'frame')
146
 
        
147
 
        def icon (self, name):
148
 
                """
149
 
                A shortcut to self.widget(name, roleName = 'icon')
150
 
                """
151
 
                self.widget(name = name, roleName = 'icon')
152
 
        
153
 
        def menu (self, name):
154
 
                """
155
 
                A shortcut to self.widget(name, roleName = 'menu')
156
 
                """
157
 
                self.widget(name = name, roleName = 'menu')
158
 
        
159
 
        def menuItem (self, name):
160
 
                """
161
 
                A shortcut to self.widget(name, roleName = 'menu item')
162
 
                """
163
 
                self.widget(name = name, roleName = 'menu item')
164
 
        
165
 
        def table (self, name = ''):
166
 
                """
167
 
                A shortcut to self.widget(name, roleName 'table')
168
 
                """
169
 
                self.widget(name = name, roleName = 'table')
170
 
        
171
 
        def tableCell (self, name = ''):
172
 
                """
173
 
                A shortcut to self.widget(name, roleName 'table cell')
174
 
                """
175
 
                self.widget(name = name, roleName = 'table cell')
176
 
        
177
 
        def text (self, name = ''):
178
 
                """
179
 
                A shortcut to self.widget(name, roleName = 'text')
180
 
                """
181
 
                self.widget(name = name, roleName = 'text')
182
 
        
183
 
        def window (self, name):
184
 
                """
185
 
                A shortcut to self.widget(name, roleName = 'window')
186
 
                """
187
 
                self.widget(name = name, roleName = 'window')
 
146
    """
 
147
    The container class for the focused application, dialog and widget.
 
148
    """
 
149
 
 
150
    def __getattr__ (self, name):
 
151
        raise AttributeError, name
 
152
    def __setattr__(self, name, value):
 
153
        if name in ('application', 'dialog', 'widget'):
 
154
            self.__dict__[name] = value
 
155
        else:
 
156
            raise AttributeError, name
 
157
 
 
158
    desktop = tree.root
 
159
    application = FocusApplication()
 
160
    app = application # shortcut :)
 
161
    dialog = FocusDialog()
 
162
    widget = FocusWidget()
 
163
 
 
164
    def button (self, name):
 
165
        """
 
166
        A shortcut to self.widget(name, roleName = 'push button')
 
167
        """
 
168
        self.widget(name = name, roleName = 'push button')
 
169
 
 
170
    def frame (self, name):
 
171
        """
 
172
        A shortcut to self.widget(name, roleName = 'frame')
 
173
        """
 
174
        self.widget(name = name, roleName = 'frame')
 
175
 
 
176
    def icon (self, name):
 
177
        """
 
178
        A shortcut to self.widget(name, roleName = 'icon')
 
179
        """
 
180
        self.widget(name = name, roleName = 'icon')
 
181
 
 
182
    def menu (self, name):
 
183
        """
 
184
        A shortcut to self.widget(name, roleName = 'menu')
 
185
        """
 
186
        self.widget(name = name, roleName = 'menu')
 
187
 
 
188
    def menuItem (self, name):
 
189
        """
 
190
        A shortcut to self.widget(name, roleName = 'menu item')
 
191
        """
 
192
        self.widget(name = name, roleName = 'menu item')
 
193
 
 
194
    def table (self, name = ''):
 
195
        """
 
196
        A shortcut to self.widget(name, roleName 'table')
 
197
        """
 
198
        self.widget(name = name, roleName = 'table')
 
199
 
 
200
    def tableCell (self, name = ''):
 
201
        """
 
202
        A shortcut to self.widget(name, roleName 'table cell')
 
203
        """
 
204
        self.widget(name = name, roleName = 'table cell')
 
205
 
 
206
    def text (self, name = ''):
 
207
        """
 
208
        A shortcut to self.widget(name, roleName = 'text')
 
209
        """
 
210
        self.widget(name = name, roleName = 'text')
 
211
 
 
212
    def window (self, name):
 
213
        """
 
214
        A shortcut to self.widget(name, roleName = 'window')
 
215
        """
 
216
        self.widget(name = name, roleName = 'window')
188
217
 
189
218
class Action (FocusWidget):
190
 
        """
191
 
        Aids in executing AT-SPI actions, refocusing the widget if necessary.
192
 
        """
193
 
        def __init__ (self, action):
194
 
                """
195
 
                action is a string with the same name as the AT-SPI action you wish to execute using this class.
196
 
                """
197
 
                self.action = action
198
 
        
199
 
        def __call__ (self, name = '', roleName = '', description = '', delay = config.actionDelay):
200
 
                """
201
 
                If name, roleName or description are specified, first search for a widget that matches and refocus on it.
202
 
                Then execute the action.
203
 
                """
204
 
                if name or roleName or description:
205
 
                        FocusWidget.__call__(self, name = name, roleName = roleName, description = description)
206
 
                self.node.doAction(self.action)
207
 
                sleep(delay)
208
 
        
209
 
        def __getattr__ (self, attr):
210
 
                return getattr(FocusWidget.node, attr)
211
 
 
212
 
        def __setattr__ (self, attr, value):
213
 
                if attr == 'action': 
214
 
                        self.__dict__[attr] = value
215
 
                else: setattr(FocusWidget, attr, value)
216
 
 
217
 
        def button (self, name):
218
 
                """
219
 
                A shortcut to self(name, roleName = 'push button')
220
 
                """
221
 
                self.__call__(name = name, roleName = 'push button')
222
 
        
223
 
        def menu (self, name):
224
 
                """
225
 
                A shortcut to self(name, roleName = 'menu')
226
 
                """
227
 
                self.__call__(name = name, roleName = 'menu')
228
 
        
229
 
        def menuItem (self, name):
230
 
                """
231
 
                A shortcut to self(name, roleName = 'menu item')
232
 
                """
233
 
                self.__call__(name = name, roleName = 'menu item')
234
 
        
235
 
        def table (self, name = ''):
236
 
                """
237
 
                A shortcut to self(name, roleName 'table')
238
 
                """
239
 
                self.__call__(name = name, roleName = 'table')
240
 
        
241
 
        def tableCell (self, name = ''):
242
 
                """
243
 
                A shortcut to self(name, roleName 'table cell')
244
 
                """
245
 
                self.__call__(name = name, roleName = 'table cell')
246
 
        
247
 
        def text (self, name = ''):
248
 
                """
249
 
                A shortcut to self(name, roleName = 'text')
250
 
                """
251
 
                self.__call__(name = name, roleName = 'text')
 
219
    """
 
220
    Aids in executing AT-SPI actions, refocusing the widget if necessary.
 
221
    """
 
222
    def __init__ (self, action):
 
223
        """
 
224
        action is a string with the same name as the AT-SPI action you wish to execute using this class.
 
225
        """
 
226
        self.action = action
 
227
 
 
228
    def __call__ (self, name = '', roleName = '', description = '', delay = config.actionDelay):
 
229
        """
 
230
        If name, roleName or description are specified, first search for a widget that matches and refocus on it.
 
231
        Then execute the action.
 
232
        """
 
233
        if name or roleName or description:
 
234
            FocusWidget.__call__(self, name = name, roleName = roleName, description = description)
 
235
        self.node.doAction(self.action)
 
236
        sleep(delay)
 
237
 
 
238
    def __getattr__ (self, attr):
 
239
        return getattr(FocusWidget.node, attr)
 
240
 
 
241
    def __setattr__ (self, attr, value):
 
242
        if attr == 'action':
 
243
            self.__dict__[attr] = value
 
244
        else: setattr(FocusWidget, attr, value)
 
245
 
 
246
    def button (self, name):
 
247
        """
 
248
        A shortcut to self(name, roleName = 'push button')
 
249
        """
 
250
        self.__call__(name = name, roleName = 'push button')
 
251
 
 
252
    def menu (self, name):
 
253
        """
 
254
        A shortcut to self(name, roleName = 'menu')
 
255
        """
 
256
        self.__call__(name = name, roleName = 'menu')
 
257
 
 
258
    def menuItem (self, name):
 
259
        """
 
260
        A shortcut to self(name, roleName = 'menu item')
 
261
        """
 
262
        self.__call__(name = name, roleName = 'menu item')
 
263
 
 
264
    def table (self, name = ''):
 
265
        """
 
266
        A shortcut to self(name, roleName 'table')
 
267
        """
 
268
        self.__call__(name = name, roleName = 'table')
 
269
 
 
270
    def tableCell (self, name = ''):
 
271
        """
 
272
        A shortcut to self(name, roleName 'table cell')
 
273
        """
 
274
        self.__call__(name = name, roleName = 'table cell')
 
275
 
 
276
    def text (self, name = ''):
 
277
        """
 
278
        A shortcut to self(name, roleName = 'text')
 
279
        """
 
280
        self.__call__(name = name, roleName = 'text')
252
281
 
253
282
class Click (Action):
254
 
        """
255
 
        A special case of Action, Click will eventually handle raw mouse events.
256
 
        """
257
 
        primary = 1
258
 
        middle = 2
259
 
        secondary = 3
260
 
        def __init__ (self):
261
 
                Action.__init__(self, 'click')
262
 
        
263
 
        def __call__ (self, name = '', roleName = '', description = '', raw = False, button = primary, delay = config.actionDelay):
264
 
                """
265
 
                If coords or button are specified, execute a raw mouse event. If not, just pass the rest of the arguments to Action.
266
 
                """
267
 
                if raw and button:
268
 
                        # We're doing a raw mouse click
269
 
                        FocusWidget.__call__(self, name = name, roleName = roleName, description = description)
270
 
                        Click.node.rawClick(button)
271
 
                        sleep(delay)
272
 
                else:
273
 
                        Action.__call__(self, name = name, roleName = roleName, description = description, delay = delay)
 
283
    """
 
284
    A special case of Action, Click will eventually handle raw mouse events.
 
285
    """
 
286
    primary = 1
 
287
    middle = 2
 
288
    secondary = 3
 
289
    def __init__ (self):
 
290
        Action.__init__(self, 'click')
 
291
 
 
292
    def __call__ (self, name = '', roleName = '', description = '', raw = False, button = primary, delay = config.actionDelay):
 
293
        """
 
294
        If coords or button are specified, execute a raw mouse event. If not, just pass the rest of the arguments to Action.
 
295
        """
 
296
        if raw and button:
 
297
            # We're doing a raw mouse click
 
298
            FocusWidget.__call__(self, name = name, roleName = roleName, description = description)
 
299
            Click.node.rawClick(button)
 
300
            sleep(delay)
 
301
        else:
 
302
            Action.__call__(self, name = name, roleName = roleName, description = description, delay = delay)
 
303
 
 
304
class Select (Action):
 
305
    """
 
306
    Aids in selecting and deselecting widgets, i.e. page tabs
 
307
    """
 
308
    select = 'select'
 
309
    deselect = 'deselect'
 
310
    def __init__(self, action):
 
311
        """
 
312
        action must be 'select' or 'deselect'.
 
313
        """
 
314
        if action not in (self.select, self.deselect):
 
315
            raise ValueError, action
 
316
        Action.__init__(self, action)
 
317
 
 
318
    def __call__ (self, name = '', roleName = '', description = '', delay = config.actionDelay):
 
319
        """
 
320
        If name, roleName or description are specified, first search for a widget that matches and refocus on it.
 
321
        Then execute the action.
 
322
        """
 
323
        if name or roleName or description:
 
324
            FocusWidget.__call__(self, name = name, roleName = roleName, description = description)
 
325
        func = getattr(self.node, self.action)
 
326
        func()
 
327
        sleep(delay)
 
328
        
 
329
def type(text):
 
330
    if focus.widget.node:
 
331
        focus.widget.node.typeText(text)
 
332
    else:
 
333
        rawinput.typeText(text)
 
334
 
 
335
def keyCombo(combo):
 
336
    if focus.widget.node:
 
337
        focus.widget.node.keyCombo(combo)
 
338
    else:
 
339
        rawinput.keyCombo(combo)
274
340
 
275
341
def run(application, arguments = '', appName = ''):
276
 
        from utils import run as utilsRun
277
 
        utilsRun(application + arguments, appName = appName)
278
 
        focus.application(application)
279
 
        
 
342
    from utils import run as utilsRun
 
343
    utilsRun(application + arguments, appName = appName)
 
344
    focus.application(application)
280
345
 
281
346
focus = Focus()
282
347
click = Click()
283
348
activate = Action('activate')
284
349
openItem = Action('open')
285
350
menu = Action('menu')
286
 
 
 
351
select = Select(Select.select)
 
352
deselect = Select(Select.deselect)