1 '''
2 Defines L{AEAccAdapter.AEAccAdapter}s for AT-SPI accessibles that manage their
3 descendants.
4
5 @author: Peter Parente
6 @organization: IBM Corporation
7 @copyright: Copyright (c) 2005, 2007 IBM Corporation
8 @license: The BSD License
9
10 @author: Frank Zenker
11 @organization: IT Science Center Ruegen gGmbH, Germany
12 @copyright: Copyright (c) 2007, 2008 ITSC Ruegen
13 @license: The BSD License
14
15 All rights reserved. This program and the accompanying materials are made
16 available under the terms of the BSD license which accompanies
17 this distribution, and is available at
18 U{http://www.opensource.org/licenses/bsd-license.php}
19 '''
20 import pyatspi
21 from DefaultInfo import *
22 from DefaultNav import *
23 from DefaultAction import *
24 from AccessEngine.AEAccInterfaces import *
25 from AccessEngine.AEPor import AEPor
26
28 '''
29 Overrides L{DefaultAccInfoAdapter} to provide information specific to
30 containers that have STATE_MANAGES_DESCENDANTS. Expects the subject to be
31 a L{AEPor}.
32 '''
33 provides = [IAccessibleInfo]
34
35 @staticmethod
37 '''
38 Tests if the given subject can be adapted by this class.
39
40 @param subject: L{AEPor} containing an accessible to test
41 @type subject: L{AEPor}
42 @return: True when the subject meets the condition named in the docstring
43 for this class, False otherwise
44 @rtype: boolean
45 '''
46 ss = subject.accessible.getState()
47 return ss.contains(pyatspi.STATE_MANAGES_DESCENDANTS)
48
50 '''
51 Gets subitems of an item in a container that manages its descendants.
52 Subitems appear to be used to indicate items that cannot be selected
53 independently of each other in a list or tree control so they are made
54 children of a dummy accessible. This is most often observed when a list or
55 tree has an icon + plus text in one of its cells.
56
57 @param acc: Accessible that may or may not have subitems
58 @type acc: C{pyatspi.Accessibility.Accessible}
59 @return: List of accessibles, including the given one
60 @rtype: list of C{pyatspi.Accessibility.Accessible}
61 '''
62 si = [acc] + [acc.getChildAtIndex(i) for i in xrange(acc.childCount)]
63 return si
64
65
67 '''
68 Gets all of the default text attributes assigned to the subject if item
69 offset is None, else the default attributes of the item offset child.
70
71 @return: Name:value pairs of the default text attributes
72 @rtype: dictionary
73 @raise LookupError: When the accessible object is dead
74 @raise IndexError: When the item offset is outside the bounds of the
75 number of children of the subject accessible
76 @raise NotImplementedError: When this accessible does not support the text
77 interface
78 '''
79 if self.item_offset is None:
80 return super(ContainerAccInfoAdapter, self).getAccDefTextAttrs()
81 c = self.accessible.getChildAtIndex(self.item_offset)
82 if c is None:
83 raise IndexError
84 return IAccessibleInfo(AEPor(c)).getAccDefTextAttrs()
85
86
88 '''
89 Gets all the text attributes of a given accessible if item offset is None
90 or the attributes of the item offset child if it is not.
91
92 @return: Name:value pairs of the text attributes at the character offset
93 @rtype: dictionary
94 @raise LookupError: When the accessible object is dead
95 @raise IndexError: When the item offset is outside the bounds of the
96 number of children of the subject accessible
97 @raise NotImplementedError: When this accessible does not support the text
98 interface
99 '''
100 if self.item_offset is None:
101 return super(ContainerAccInfoAdapter, self).getAccAllTextAttrs()
102 c = self.accessible.getChildAtIndex(self.item_offset)
103 if c is None:
104 raise IndexError
105 return IAccessibleInfo(AEPor(c)).getAccAllTextAttrs()
106
107
109 '''
110 Gets a list of L{AEPor}s referring to the selected items within the subject
111 accessible.
112
113 @return: Points of regard to selected items
114 @rtype: list of L{AEPor}s
115 @raise LookupError: When the subject accessible is dead
116 '''
117 try:
118 sel = (self.accessible).querySelection()
119 except NotImplementedError:
120 return []
121
122 return [AEPor(self.accessible, sel.getSelectedChild(i).getIndexInParent(), 0)
123 for i in range(sel.nSelectedChildren)]
124
125
127 '''
128 Gets the accessible role name of the subject if item offset is None else
129 the role name of the given item. The name is localized.
130
131 @return: Accessible role name of requested object
132 @rtype: string
133 @raise LookupError: When the subject accessible or the child is dead
134 @raise IndexError: When the item offset is outside the bounds of the
135 number of children of the subject accessible
136 '''
137 if self.item_offset is None:
138 return super(ContainerAccInfoAdapter, self).getAccRoleName()
139 try:
140 c = self.accessible.getChildAtIndex(self.item_offset)
141
142 return unicode(c.getLocalizedRoleName(), 'utf-8')
143 except AttributeError:
144 raise IndexError
145
146
148 '''
149 Gets the accessible role of the subject if item offset is None else
150 the role name of the given item.
151
152 @return: Accessible role of requested object
153 @rtype: string
154 @raise LookupError: When the subject accessible or the child is dead
155 @raise IndexError: When the item offset is outside the bounds of the
156 number of children of the subject accessible
157 '''
158 if self.item_offset is None:
159 return super(ContainerAccInfoAdapter, self).getAccRole()
160 try:
161 c = self.accessible.getChildAtIndex(self.item_offset)
162 return c.getRoleName()
163 except AttributeError:
164 raise IndexError
165
166
168 '''
169 Gets the accessible name of the subject if item offset is None else the
170 name of the given item.
171
172 @return: Accessible name of requested object
173 @rtype: string
174 @raise LookupError: When the subject accessible or the child is dead
175 @raise IndexError: When the item offset is outside the bounds of the
176 number of children of the subject accessible
177 '''
178 if self.item_offset is None:
179 return super(ContainerAccInfoAdapter, self).getAccName()
180 try:
181 c = self.accessible.getChildAtIndex(self.item_offset)
182 l = [i.name for i in self._getSubItems(c)]
183 return unicode(' '.join(l), 'utf-8')
184 except AttributeError:
185 raise IndexError
186
187
189 '''
190 Gets the accessible description of the subject if item offset is None else
191 the name of the given item.
192
193 @return: Accessible description of requested object
194 @rtype: string
195 @raise LookupError: When the subject accessible or the child is dead
196 @raise IndexError: When the item offset is outside the bounds of the
197 number of children of the subject accessible
198 '''
199 if self.item_offset is None:
200 return super(ContainerAccInfoAdapter, self).getAccDescription()
201 try:
202 c = self.accessible.getChildAtIndex(self.item_offset)
203 l = [i.description for i in self._getSubItems(c)]
204 return unicode(' '.join(l), 'utf-8')
205 except AttributeError:
206 raise IndexError
207
208
209 - def getAccItemText(self):
210 '''
211 Gets the accessible name of the subject if item offset is None else the
212 name of the given child accessible.
213
214 @return: Accessible description of requested object
215 @rtype: string
216 @raise LookupError: When the subject accessible or the child is dead
217 @raise IndexError: When the item offset is outside the bounds of the
218 number of children of the subject accessible
219 '''
220 if self.item_offset is None:
221 return super(ContainerAccInfoAdapter, self).getAccItemText()
222 try:
223 c = self.accessible.getChildAtIndex(self.item_offset)
224
225
226
227 l = [IAccessibleInfo(AEPor(i)).getAccItemText()
228 for i in self._getSubItems(c)]
229 return u' '.join(l)
230 except AttributeError:
231 raise IndexError
232
233
235 '''
236 Gets a list of names of states indicating the current state of the given
237 accessible.
238
239 @return: Names of all states
240 @rtype: list of string
241 @raise LookupError: When the subject accessible or the child is dead
242 @raise IndexError: When the item offset is outside the bounds of the
243 number of children of the subject accessible
244 '''
245 if self.item_offset is None:
246 return super(ContainerAccInfoAdapter, self).getAccStates()
247 try:
248 c = self.accessible.getChildAtIndex(self.item_offset)
249 except AttributeError:
250 raise IndexError
251 return IAccessibleInfo(AEPor(c)).getAccStates()
252
253
255 '''
256 Gets the index of an item as the item offset.
257
258 @return: Zero indexed item offset
259 @rtype: integer
260 @raise LookupError: When the table or item is no longer valid
261 '''
262 if self.item_offset is None:
263 return super(ContainerAccInfoAdapter, self).getAccIndex()
264 else:
265 return self.item_offset
266
267
269 '''
270 Gets if the subject has the given state.
271
272 @param state: Name of the state (e.g. 'focused', 'selected', 'selectable')
273 @type state: string
274 @return: Does the accessible have the given state?
275 @rtype: boolean
276 @see: L{getAccStates}
277 '''
278 if self.item_offset is None:
279 return super(ContainerAccInfoAdapter, self).hasAccState(state)
280 try:
281 c = self.accessible.getChildAtIndex(self.item_offset)
282 except AttributeError:
283 raise IndexError
284 return IAccessibleInfo(AEPor(c)).hasAccState(state)
285
286
288 '''
289 Gets if the subject has at least one of the given states.
290
291 @param states: State names(e.g. 'focused', 'selected', 'selectable')
292 @type states: string
293 @return: Does the accessible have at least one of the given states?
294 @rtype: boolean
295 '''
296 if self.item_offset is None:
297 return super(ContainerAccInfoAdapter, self).hasAccOneState(*states)
298 try:
299 c = self.accessible.getChildAtIndex(self.item_offset)
300 except AttributeError:
301 raise IndexError
302 return IAccessibleInfo(AEPor(c)).hasAccOneState(*states)
303
304
306 '''
307 Gets if the subject has all of the given states.
308
309 @param states: State names(e.g. 'focused', 'selected', 'selectable')
310 @type states: string
311 @return: Does the accessible have all of the given states?
312 @rtype: boolean
313 '''
314 if self.item_offset is None:
315 return super(ContainerAccInfoAdapter, self).hasAccAllStates(*states)
316 try:
317 c = self.accessible.getChildAtIndex(self.item_offset)
318 except AttributeError:
319 raise IndexError
320 return IAccessibleInfo(AEPor(c)).hasAccAllStates(*state)
321
322
324 '''
325 Gets the list of all action names defined by the subject.
326
327 @return: List of all action names
328 @rtype: list of string
329 @raise NotImplementedError: When the subject does not support actions
330 '''
331 if self.item_offset is None:
332 super(ContainerAccInfoAdapter, self).getAccActionNames()
333 try:
334 c = self.accessible.getChildAtIndex(self.item_offset)
335 except AttributeError:
336 raise IndexError
337 return IAccessibleInfo(AEPor(c)).getAccActionNames()
338
339
341 '''
342 Gets the list of all action descriptions defined by the subject.
343
344 @return: List of all action descriptions
345 @rtype: list of string
346 @raise NotImplementedError: When the subject does not support actions
347 '''
348 if self.item_offset is None:
349 super(ContainerAccInfoAdapter, self).getAccActionDescs()
350 try:
351 c = self.accessible.getChildAtIndex(self.item_offset)
352 except AttributeError:
353 raise IndexError
354 return IAccessibleInfo(AEPor(c)).getAccActionDescs()
355
356
358 '''
359 Gets the number of available actions on the subject.
360
361 @return: Number of actions available
362 @rtype: integer
363 @raise NotImplementedError: When the subject does not support actions
364 '''
365 if self.item_offset is None:
366 super(ContainerAccInfoAdapter, self).getAccActionCount()
367 try:
368 c = self.accessible.getChildAtIndex(self.item_offset)
369 except AttributeError:
370 raise IndexError
371 return IAccessibleInfo(AEPor(c)).getAccActionCount()
372
373
375 '''
376 Gets the key bindings associated with all available actions. Parses the
377 key bindings into tuples since some actions can have multiple ways of
378 activating them dependent on the context.
379
380 @return: List of tuples, each containing one or more string keysym names
381 indicating the keys to press in sequence to perform the action
382 @rtype: list of tuple of string
383 @raise NotImplementedError: When the subject does not support actions
384 '''
385 if self.item_offset is None:
386 super(ContainerAccInfoAdapter, self).getAccActionKeys()
387 try:
388 c = self.accessible.getChildAtIndex(self.item_offset)
389 except AttributeError:
390 raise IndexError
391 return IAccessibleInfo(AEPor(c)).getAccActionKeys()
392
393
395 '''
396 Gets the visual width and height of the subject.
397
398 @return: Width and height extents
399 @rtype: 2-tuple of integer
400 @raise LookupError: When the accessible object is dead
401 '''
402 if self.item_offset is None:
403 return super(ContainerAccInfoAdapter, self).getAccVisualExtents()
404 try:
405 c = self.accessible.getChildAtIndex(self.item_offset)
406 except AttributeError:
407
408 raise IndexError
409
410 return IAccessibleInfo(AEPor(c,None,self.char_offset)).getAccVisualExtents()
411
412
414 '''
415 Gets the focal point within the subject, where the focal point is defined
416 as the center of the active item.
417
418 @return: x,y coordinates
419 @rtype: 2-tuple of integer
420 @raise LookupError: When the accessible object is dead
421 '''
422 if self.item_offset is None:
423 return super(ContainerAccInfoAdapter, self).getAccVisualPoint()
424 try:
425 c = self.accessible.getChildAtIndex(self.item_offset)
426 except AttributeError:
427
428 raise IndexError
429
430 return IAccessibleInfo(AEPor(c,None,self.char_offset)).getAccVisualPoint()
431
433 '''
434 Overrides L{DefaultAccActionAdapter} to provide information specific to
435 containers that have STATE_MANAGES_DESCENDANTS. Expects the subject to be a
436 L{AEPor}.
437 '''
438 provides = [IAccessibleAction]
439
440 @staticmethod
442 '''
443 Tests if the given subject can be adapted by this class.
444
445 @param subject: L{AEPor} containing an accessible to test
446 @type subject: L{AEPor}
447 @return: True when the subject meets the condition named in the docstring
448 for this class, False otherwise
449 @rtype: boolean
450 '''
451 acc = subject.accessible
452 ss = acc.getState()
453 return ss.contains(pyatspi.STATE_MANAGES_DESCENDANTS)
454
455
457 '''
458 Gives the subject accessible the focus when the item offset is None or
459 one of its items when the offset is an integer.
460
461 @return: Did accessible accept (True) or refuse (False) the focus change?
462 @rtype: boolean
463 @raise LookupError: When the accessible object is dead
464 @raise NotImplementedError: When the accessible does not support an
465 interface for setting focus
466 '''
467 if self.item_offset is None:
468 super(ContainerAccActionAdapter, self).setAccFocus()
469 else:
470 child = self.accessible.getChildAtIndex(self.item_offset)
471 c = (child).queryComponent()
472 return c.grabFocus()
473
474
476 '''
477 Selects the accessible object implementing this interface when item offset
478 is None and all is False. Selects all items when item offset is None and
479 all is True. Otherwise, selects the one item indicated by the item offset
480 in the subject L{AEPor}.
481
482 @param all: Select all items?
483 @type all: boolean
484 @return: Did accessible accept (True) or refuse (False) the selection?
485 @rtype: boolean
486 @raise LookupError: When the accessible object is dead
487 @raise NotImplementedError: When the accessible does not support an
488 interface for setting the selection
489 '''
490 if self.item_offset is None:
491 return super(ContainerAccActionAdapter,self).selectAcc(all)
492 else:
493 c = (self.accessible).querySelection()
494 return c.selectChild(self.item_offset)
495
496
498 '''
499 Executes the accessible action given by the index on the item_offset.
500
501 @param index: Index of the action to execute
502 @type index: integer
503 @return: Did the action execute (True) or not (False)?
504 @rtype: boolean
505 @raise LookupError: When the accessible object is dead
506 @raise NotImplementedError: When the accessible does not support the action
507 interface
508 '''
509 if self.item_offset is None:
510 return super(ContainerAccActionAdapter,self).doAccAction(index)
511 else:
512 child = self.accessible.getChildAtIndex(self.item_offset)
513 act = (child).queryAction()
514 return act.doAction(index)
515