| Trees | Indices | Help |
|
|---|
|
|
1 '''
2 Defines a L{AEScript <AEScript.AEScript>} for the Firefox web browser.
3
4 @var DOCUMENT_ROLE: Role name of the top of a document view.
5 @type DOCUMENT_ROLE: string
6 @var DOCUMENT_MODE: Document structure browsing mode
7 @type DOCUMENT_MODE: integer
8 @var TABLE_MODE: Table structure browsing mode
9 @type TABLE_MODE: integer
10 @var WIDGET_MODE: Interactive widget browsing mode
11 @type WIDGET_MODE: integer
12 @var TOTAL_MODES: Total number of defined modes
13 @type TOTAL_MODES: integer
14
15 @author: Peter Parente
16 @author: Scott Haeger
17 @organization: IBM Corporation
18 @copyright: Copyright (c) 2005, 2007 IBM Corporation
19 @license: The BSD License
20
21 All rights reserved. This program and the accompanying materials are made
22 available under the terms of the BSD license which accompanies
23 this distribution, and is available at
24 U{http://www.opensource.org/licenses/bsd-license.php}
25 '''
26 # import useful modules for Scripts
27 from AccessEngine import AEScript, AccessEngineAPI
28 #from AccessEngine.AEPor import AEPor
29 from Tools.i18n import _
30 from AccessEngine.AEConstants import *
31 from AccessEngine import AEConstants
32 import time, urlparse, urllib2
33
34 __uie__ = dict(kind='script', tier='Minefield', all_tiers=False)
35
36 DOCUMENT_ROLE = 'document frame'
37
38 # Navigation modes
39 DOCUMENT_MODE = 0
40 TABLE_MODE = 1
41 WIDGET_MODE = 2
42 TOTAL_MODES = 3
43
45 '''
46 Defines settings specific to Firefox.
47
48 BoundReview (boolean): Keep review functions within the Firefox document when
49 reviewing begins inside the document, or let them walk across document
50 boundaries?
51
52 AutoMode(boolean): When True, modes are automatically updated on a L{AEPor}
53 change.
54
55 SearchDepth (integer): Number of nodes visited before iterative searches are
56 cancelled. Affects all find, goto, and where am I? functions.
57 '''
59 self.newBool('BoundReview', True, _('Bound review to document?'),
60 _('When set, the review keys will not navigate outside '
61 'the current web page when reviewing starts in the page. '
62 'Otherwise, review keys can walk out of the document.'))
63 self.newBool('AutoMode', True,
64 _('Automatically change navigation mode?'),
65 _('When set, the navigation mode is automatically set to the '
66 'most specific reading mode when the point of regard changes. '
67 'Otherwise, reading modes are not updated.'))
68 self.newNumeric('SearchDepth', 500, _('Search Depth'), 0, 5000, 0,
69 _('Number of nodes visited before iterative searches '
70 'are cancelled. Affects all find, goto, and where '
71 'am I? functions.'))
72
85
87 '''
88 Defines hotkeys to improve document browsing and chrome access for the
89 Firefox web browser.
90
91 Flowcharts:
92 Review task chaining: keyboard event -> BoundReview(All Review) ->
93 HandleAutofocus -> ConvReviewReg.
94 Convenience review chaining: keyboard event -> ConvReview ->
95 BoundReview(All Review) -> HandleAutofocus -> ConvReviewReg.
96 Review skip: ShouldSkip -> FFShouldSkip.
97 Read role: ReadReviewRole(ReadNewRole)
98
99 @cvar STATE: L{AEState} object that holds user setting values.
100 @type STATE: L{AEState}
101 @cvar SKIPPED_ITEMS: Additional items to be skipped when reviewing.
102 @type SKIPPED_ITEMS: tuple
103 @cvar SKIPPED_ROLES: Additional roles to be skipped when reviewing.
104 @type SKIPPED_ROLES: tuple
105 @cvar WIDGET_ROLES: A dictionary where the keys are roles which will
106 prevent the convenience review keys from being registered. When a value is
107 not None, it is a state that must be contained in this accessible's state set
108 before convenience review keys are registered.
109 @type WIDGET_ROLES: dictionary
110
111 @ivar convkey_reg: Are convenience review keys registered?
112 @type convkey_reg: boolean
113 @ivar nav_element_reg: Are element navigation keys registered?
114 @type nav_element_reg: boolean
115 @ivar currentmode: The current navigation mode.
116 @type currentmode: integer
117 @ivar doc_pors: Dictionary containing saved pors. Key is doc frame of web
118 page to be restored.
119 @type doc_pors: dictionary
120 @ivar cached_pointer: L{AEPor} saved during caret event. Used to restore POR
121 during certain restoration scenerios involving chrome.
122 @type cached_pointer: L{AEPor}
123 @ivar lastporinfocus: L{AEPor} saved during restoration routine to help
124 differentiate tab browsing from Tab/Tab-Shift events.
125 @type last_focus_por: L{AEPor}
126 @ivar lastdocinfocus: L{AEPor} saved during restoration routine to help
127 differentiate tab browsing from Tab/Tab-Shift events.
128 @type lastdocinfocus: L{AEPor}
129 @ivar viewlost: Flag that indicates a view lost event has just occurred.
130 Used during the saved L{AEPor} restoration routine.
131 @type viewlost: boolean
132
133 '''
134 CONTAINERS_BY_ROLE =('image', 'form', 'list', 'calendar', 'menu', 'menu bar',
135 'page tab', 'tool bar', 'application', 'tree', 'tree table', 'entry')
136 TRIVIAL_WIDGETS = ('push button', '', 'document frame', 'check box', 'image')
137 STATE = FirefoxScriptState
138 SKIPPED_ITEMS = ()
139 SKIPPED_ROLES = ()
140
142 self.doc_pors = {}
143 self.cached_pointer = None
144 self.lastporinfocus = None
145 self.lastdocinfocus = None
146 self.viewlost = False
147
148 # Navigation mode related
149 self.nav_element_reg = False
150 self.convkey_reg = False
151 self.currentmode = WIDGET_MODE
152 self.savedmode = None
153
154
155 # set an audio device as the default output
156 AccessEngineAPI.setScriptIdealOutput('audio')
157
158 ## Register for events
159 #AccessEngineAPI.registerTask(ExtraCarets(None))
160 #AccessEngineAPI.registerTask(PointerCache(None))
161
162 ## Register general review related tasks
163 #AccessEngineAPI.registerTask(FirefoxReview('firefox review'))
164 #AccessEngineAPI.registerTask(ReadReviewRole('firefox review role'))
165 #AccessEngineAPI.registerTask(ReviewShouldSkip('firefox review should skip'))
166 #AccessEngineAPI.registerTask(FFReadNewContainer('firefox read new container'))
167
168 ## POR restoration related (Firefox tabbing, app switching, menu selection)
169 #AccessEngineAPI.registerTask(HandleDocumentPORView(None, all=True))
170 #AccessEngineAPI.registerTask(HandleDocumentPORFocus(None, all=True))
171
172 ## Register convenience review key related. Registration order matters
173 ## ModeChangerOnView and ModeChangerOnFocus must come after
174 ## HandleDocumentPORView and HandleDocumentPORFocus, respectively.
175 #AccessEngineAPI.registerTask(ConvReview('firefox convenience review'))
176 #AccessEngineAPI.registerTask(ModeChangerOnFocus('firefox mode changer focus',
177 #all=True))
178 #AccessEngineAPI.registerTask(ModeChangerOnView('firefox mode changer view',
179 #all=True))
180 #AccessEngineAPI.registerTask(ModeChangerOnUser('firefox mode changer user'))
181
182 ## Register user triggered move/announcement events
183 #AccessEngineAPI.registerTask(GoToActiveDoc('firefox go to activedoc'))
184 #AccessEngineAPI.registerTask(FFWhereAmINow('firefox where am i now'))
185 #AccessEngineAPI.registerTask(GoToDocStart('firefox go to doc start'))
186 #AccessEngineAPI.registerTask(GoToDocEnd('firefox go to doc end'))
187 #AccessEngineAPI.registerTask(GoToItemStart('firefox go to item start'))
188 #AccessEngineAPI.registerTask(GoToItemEnd('firefox go to item end'))
189 #AccessEngineAPI.registerTask(GoToContainer('firefox go to container'))
190 #AccessEngineAPI.registerTask(SkipContainer('firefox skip container'))
191 ## navigation by element
192 #AccessEngineAPI.registerTask(GoToElement('firefox go to next anchor'))
193 #AccessEngineAPI.registerTask(GoToElement('firefox go to next embed'))
194 #AccessEngineAPI.registerTask(GoToElement('firefox go to next button'))
195 #AccessEngineAPI.registerTask(GoToElement('firefox go to next check box'))
196 #AccessEngineAPI.registerTask(GoToElement('firefox go to next combo box'))
197 #AccessEngineAPI.registerTask(GoToElement('firefox go to next entry'))
198 #AccessEngineAPI.registerTask(GoToElement('firefox go to next form'))
199 #AccessEngineAPI.registerTask(GoToElement('firefox go to next form control'))
200 #AccessEngineAPI.registerTask(GoToElement('firefox go to next image'))
201 #AccessEngineAPI.registerTask(GoToElement('firefox go to next heading'))
202 #AccessEngineAPI.registerTask(GoToElement('firefox go to next list'))
203 #AccessEngineAPI.registerTask(GoToElement('firefox go to next list item'))
204 #AccessEngineAPI.registerTask(GoToElement('firefox go to next section'))
205 #AccessEngineAPI.registerTask(GoToElement('firefox go to next radio button'))
206 #AccessEngineAPI.registerTask(GoToElement('firefox go to next table'))
207 #AccessEngineAPI.registerTask(GoToElement('firefox go to next unvisited link'))
208 #AccessEngineAPI.registerTask(GoToElement('firefox go to next visited link'))
209 #AccessEngineAPI.registerTask(GoToElement('firefox go to prev anchor'))
210 #AccessEngineAPI.registerTask(GoToElement('firefox go to prev embed'))
211 #AccessEngineAPI.registerTask(GoToElement('firefox go to prev button'))
212 #AccessEngineAPI.registerTask(GoToElement('firefox go to prev check box'))
213 #AccessEngineAPI.registerTask(GoToElement('firefox go to prev combo box'))
214 #AccessEngineAPI.registerTask(GoToElement('firefox go to prev entry'))
215 #AccessEngineAPI.registerTask(GoToElement('firefox go to prev form'))
216 #AccessEngineAPI.registerTask(GoToElement('firefox go to prev form control'))
217 #AccessEngineAPI.registerTask(GoToElement('firefox go to prev image'))
218 #AccessEngineAPI.registerTask(GoToElement('firefox go to prev heading'))
219 #AccessEngineAPI.registerTask(GoToElement('firefox go to prev list'))
220 #AccessEngineAPI.registerTask(GoToElement('firefox go to prev list item'))
221 #AccessEngineAPI.registerTask(GoToElement('firefox go to prev section'))
222 #AccessEngineAPI.registerTask(GoToElement('firefox go to prev radio button'))
223 #AccessEngineAPI.registerTask(GoToElement('firefox go to prev table'))
224 #AccessEngineAPI.registerTask(GoToElement('firefox go to prev unvisited link'))
225 #AccessEngineAPI.registerTask(GoToElement('firefox go to prev visited link'))
226 ## navigation by landmark
227 #AccessEngineAPI.registerTask(GoToElement('firefox go to next banner'))
228 #AccessEngineAPI.registerTask(GoToElement('firefox go to next content info'))
229 #AccessEngineAPI.registerTask(GoToElement('firefox go to next definition'))
230 #AccessEngineAPI.registerTask(GoToElement('firefox go to next main'))
231 #AccessEngineAPI.registerTask(GoToElement('firefox go to next navigation'))
232 #AccessEngineAPI.registerTask(GoToElement('firefox go to next note'))
233 #AccessEngineAPI.registerTask(GoToElement('firefox go to next search'))
234 #AccessEngineAPI.registerTask(GoToElement('firefox go to next secondary'))
235 #AccessEngineAPI.registerTask(GoToElement('firefox go to next see also'))
236 #AccessEngineAPI.registerTask(GoToElement('firefox go to prev banner'))
237 #AccessEngineAPI.registerTask(GoToElement('firefox go to prev content info'))
238 #AccessEngineAPI.registerTask(GoToElement('firefox go to prev definition'))
239 #AccessEngineAPI.registerTask(GoToElement('firefox go to prev main'))
240 #AccessEngineAPI.registerTask(GoToElement('firefox go to prev navigation'))
241 #AccessEngineAPI.registerTask(GoToElement('firefox go to prev note'))
242 #AccessEngineAPI.registerTask(GoToElement('firefox go to prev search'))
243 #AccessEngineAPI.registerTask(GoToElement('firefox go to prev secondary'))
244 #AccessEngineAPI.registerTask(GoToElement('firefox go to prev see also'))
245 ## navigation by relation
246 #AccessEngineAPI.registerTask(CyclicGoToElement('firefox go to next similar'))
247 #AccessEngineAPI.registerTask(CyclicGoToElement('firefox go to prev similar'))
248 #AccessEngineAPI.registerTask(CyclicGoToElement('firefox go to next different'))
249 #AccessEngineAPI.registerTask(CyclicGoToElement('firefox go to prev different'))
250
251 ## read document URL
252 #AccessEngineAPI.registerTask(ReadDocAddressAndTitle('firefox read document address'))
253 ## read link preview
254 #AccessEngineAPI.registerTask(ReadLinkPreview('firefox read link preview'))
255 ## Register state watching tasks
256 #AccessEngineAPI.registerTask(HandleAutocomplete('firefox say autocomplete',
257 #tier=True))
258 ## Register saved POR flushing task. Runs once every minute.
259 #AccessEngineAPI.registerTask(SavedPORFlusher('firefox saved por flusher', 60000))
260
261 ## Add keyboard modifiers
262 #kbd = AccessEngineAPI.getInputDevice(None, 'keyboard')
263 #AccessEngineAPI.addInputModifiers(self, kbd, kbd.AEK_CAPS_LOCK)
264 #AccessEngineAPI.addInputModifiers(self, kbd, kbd.AEK_CONTROL_R)
265 #AccessEngineAPI.addInputModifiers(self, kbd, kbd.AEK_CONTROL_L)
266 #AccessEngineAPI.addInputModifiers(self, kbd, kbd.AEK_SHIFT_R)
267 #AccessEngineAPI.addInputModifiers(self, kbd, kbd.AEK_SHIFT_L)
268
269 ## Register keyboard commands for reading document address and move to
270 ## active doc frame.
271 #AccessEngineAPI.registerCommand(kbd, 'firefox read document address', False,
272 #[kbd.AEK_CAPS_LOCK, kbd.AEK_Y])
273 #AccessEngineAPI.registerCommand(kbd, 'firefox go to activedoc', False,
274 #[kbd.AEK_CAPS_LOCK, kbd.AEK_HOME])
275 #AccessEngineAPI.registerCommand(kbd, 'firefox go to container', False,
276 #[kbd.AEK_CAPS_LOCK,kbd.AEK_UP])
277 #AccessEngineAPI.registerCommand(kbd, 'firefox skip container', False,
278 #[kbd.AEK_CAPS_LOCK,kbd.AEK_RIGHT])
279
280 #AccessEngineAPI.registerCommand(kbd, 'firefox mode changer user', False,
281 #[kbd.AEK_CAPS_LOCK, kbd.AEK_SPACE])
282
283 ## chain to other tasks. See Script docstring for task flowcharts.
284 #AccessEngineAPI.chainTask('firefox review role', CHAIN_AROUND, 'read new role')
285 #AccessEngineAPI.chainTask('firefox review should skip', CHAIN_AROUND,
286 #'review should skip')
287 #AccessEngineAPI.chainTask('firefox where am i now', CHAIN_AROUND,
288 #'where am i now')
289 #AccessEngineAPI.chainTask('firefox read new container', CHAIN_BEFORE,
290 #'read new container')
291
292 ## register the firefox review task around all the basic review tasks that
293 ## move the pointer so we can account for specific cases and features
294 #review_script = AccessEngineAPI.getScriptByName(self.tier, 'ReviewScript')
295 #names = review_script.getTaskKeys()
296 #for name in names:
297 #if (((name.startswith('review previous') or # reviewing, not peeking
298 #name.startswith('review next')) and
299 #not name.endswith('peek'))):
300 #AccessEngineAPI.chainTask('firefox review', CHAIN_AROUND, name)
301
303 return _('Firefox')
304
308
309 #def getDocFrame(self, por):
310 #'''
311 #Determines if a L{AEPor} is within or equal to the doc frame.
312
313 #@param por: L{AEPor} in question
314 #@type por: L{AEPor}
315 #@return: Is por within doc frame?
316 #@rtype: tuple
317 #'''
318 #if por == None:
319 #return None
320 #if AccessEngineAPI.hasAccRole(DOCUMENT_ROLE, por):
321 #return por
322 #return AccessEngineAPI.findAccByRole(DOCUMENT_ROLE, por=por, ancestor=True)
323
324 #def needsWidgetMode(self, por):
325 #'''
326 #Determines if the given L{AEPor} is a candidate to switch modes to widget
327 #mode.
328
329 #@param por: Some point of regard
330 #@type por: L{AEPor}
331 #@return: Will the control need the arrow keys?
332 #@rtype: boolean
333 #'''
334 #role = AccessEngineAPI.getAccRole(por=por)
335 #return (AccessEngineAPI.hasAccState('focusable', por) and \
336 #role not in self.TRIVIAL_WIDGETS)
337
338 #def needsFocus(self, por):
339 #'''
340 #Determines if the given L{AEPor} should receive focus according to the
341 #user settings and the accessible's role, states, and actions.
342
343 #@return: Does the given L{AEPor} need to be given focus according to the
344 #user settings and the states of the accessible?
345 #@rtype: boolean
346 #'''
347 #role = AccessEngineAPI.getAccRole(por=por)
348 #if self.script_state.AutoMode:
349 #return (AccessEngineAPI.hasAccState('focusable', por) and \
350 #not AccessEngineAPI.hasAccState('focused', por))
351 #else:
352 #return (AccessEngineAPI.hasAccState('focusable', por) and \
353 #not AccessEngineAPI.hasAccState('focused', por) and \
354 #role in self.TRIVIAL_WIDGETS)
355
356 #def getActiveDocFrame(self):
357 #'''
358 #Returns the active document frame as a L{AEPor}.
359
360 #@return: Point of regard to the document frame accessible
361 #@rtype: L{AEPor}
362 #'''
363 #frame = AccessEngineAPI.getViewRootAcc()
364 #relations = AccessEngineAPI.getAccRelations('embeds', por=frame)
365 ## Good enough for now. Might need to change this in future if more than one
366 ## relation is in the relation set.
367 #if relations:
368 #return relations[0]
369 #else:
370 #return None
371
372 #def getDocURI(self):
373 #return AccessEngineAPI.getAccAttrs(por=self.getActiveDocFrame())['DocURL']
374
375 #def getLastSearchAcc(self):
376 #'''
377 #Returns the last accessible to be searched. Returns either the panel
378 #containing the next doc frame or the accessible returned by getEndAcc.
379
380 #@return: Point of regard to the last accessible to be searched
381 #@rtype: L{AEPor}
382 #'''
383 #grandparent = AccessEngineAPI.getParentAcc(por= \
384 #AccessEngineAPI.getParentAcc(por=self.script.getActiveDocFrame()))
385 #peer = AccessEngineAPI.getNextPeerAcc(por=grandparent)
386 #if peer is None:
387 #return AccessEngineAPI.getEndAcc()
388 #else:
389 #return AccessEngineAPI.getChildAcc(0, por=peer)
390
391 #def isLayoutTable(self, por, role):
392 #'''
393 #Determines if a table or cell is for layout only using Firefox's
394 #suggestion in the layout-guess attribute.
395
396 #@param por: Point of regard to a potential layout table or cell
397 #@type por: L{AEPor}
398 #@param role: Pre-determined role of the L{AEPor}
399 #@type role: string
400 #'''
401 #if role == 'table cell':
402 #table = AccessEngineAPI.getParentAcc(por=por)
403 #if table is None:
404 #return False
405 #attrs = AccessEngineAPI.getAccAttrs(por=table)
406 #try:
407 #return (attrs is not None and attrs['layout-guess'] == 'true')
408 #except (AttributeError, KeyError):
409 #return False
410 #elif role == 'table':
411 #attrs = AccessEngineAPI.getAccAttrs(por=por)
412 #try:
413 #return (attrs is not None and attrs['layout-guess'] == 'true')
414 #except (AttributeError, KeyError):
415 #return False
416 #else:
417 #return False
418
419 ## ***** Navigation mode related *****************
420 #def setModeByPOR(self, por):
421 #'''
422 #Sets the mode based on a given L{AEPor}
423
424 #@param por: Point of regard to a potential layout table or cell
425 #@type por: L{AEPor}
426 #@return: mode type
427 #@rtype: integer
428 #'''
429 ## Don't update modes if user does not want you to.
430 #if not self.script_state.AutoMode:
431 #self.setMode(self.currentmode)
432 #return self.currentmode
433
434 ## unregister all modes if within chrome
435 #if AccessEngineAPI.getAccRole(por=por) != DOCUMENT_ROLE and \
436 #self.getDocFrame(por) is None:
437 #self.setMode(WIDGET_MODE)
438 #return WIDGET_MODE
439 ## we are in doc frame. Select mode based on POR attributes, states etc.
440 #else:
441 #if not self.needsWidgetMode(por):
442 #self.setMode(DOCUMENT_MODE)
443 #return DOCUMENT_MODE
444 #else:
445 #self.setMode(WIDGET_MODE)
446 #return WIDGET_MODE
447
448 #def setMode(self, modetype):
449 #'''
450 #Set the navigation mode based on given mode type. Calls methods that
451 #register key commands relevant to enable given mode.
452
453 #@param modetype: The type of mode to set
454 #@type por: integer
455 #@raise NameError: when modetype is not a valid mode
456 #'''
457 ## report any mode changes
458 #if modetype != self.currentmode:
459 #self.currentmode = modetype
460 #self.reportMode(modetype)
461 ## reg/unreg keys associated with each mode
462 #if modetype == DOCUMENT_MODE:
463 #self.registerNavByElement()
464 #self.registerConvReview()
465 #elif modetype == TABLE_MODE:
466 #self.registerTableReview()
467 #elif modetype == WIDGET_MODE:
468 #self.unsetAllModes()
469 #else:
470 #raise NameError
471
472 #def unsetMode(self, modetype):
473 #'''
474 #Unsets a navigation mode based on given mode type. Calls methods that
475 #unregister key commands relevant to disable a given mode.
476
477 #@param modetype: The type of mode to unset
478 #@type por: integer
479 #'''
480 #if modetype is None:
481 #return
482 #elif modetype == DOCUMENT_MODE:
483 #self.unregisterNavByElement()
484 #self.unregisterConvReview()
485 #elif modetype == TABLE_MODE:
486 #self.unregisterTableReview()
487 ## WIDGET_MODE implies all navigation keys unregistered
488 #self.currentmode = WIDGET_MODE
489
490 #def unsetCurrentMode(self):
491 #'''
492 #Unsets the current mode
493 #'''
494 #if self.currentmode is not None:
495 #self.unsetMode(self.currentmode)
496
497 #def unsetAllModes(self):
498 #'''
499 #Unset all modes.
500 #'''
501 #for i in range(TOTAL_MODES-1):
502 #self.unsetMode(i)
503
504 #def reportMode(self, mode):
505 #'''
506 #Reports (announces) given mode type.
507 #'''
508 #if mode is None:
509 #return
510 ## only announce mode changes that occur within doc frame
511 #if self.getDocFrame(self.task_por):
512 #if mode == DOCUMENT_MODE:
513 #AccessEngineAPI.sayInfo(text=_("entering document mode"))
514 #elif mode == TABLE_MODE:
515 #AccessEngineAPI.sayInfo(text=_("entering table mode"))
516 #elif mode == WIDGET_MODE:
517 #AccessEngineAPI.sayInfo(text=_("entering widget mode"))
518 #AccessEngineAPI.inhibitMayStop()
519
520 #def registerNavByElement(self):
521 #'''
522 #Registers keys related to navigation by element, navigation by landmark,
523 #and navigation by relation.
524 #'''
525 #if not self.nav_element_reg:
526 #kbd = AccessEngineAPI.getInputDevice(None, 'keyboard')
527 #AccessEngineAPI.registerCommand(kbd, 'firefox go to next anchor', False, [kbd.AEK_A])
528 #AccessEngineAPI.registerCommand(kbd, 'firefox go to next embed', False, [kbd.AEK_D])
529 #AccessEngineAPI.registerCommand(kbd, 'firefox go to next button', False, [kbd.AEK_B])
530 #AccessEngineAPI.registerCommand(kbd, 'firefox go to next check box', False, [kbd.AEK_X])
531 #AccessEngineAPI.registerCommand(kbd, 'firefox go to next combo box', False, [kbd.AEK_C])
532 #AccessEngineAPI.registerCommand(kbd, 'firefox go to next entry', False, [kbd.AEK_E])
533 #AccessEngineAPI.registerCommand(kbd, 'firefox go to next form', False, [kbd.AEK_F])
534 #AccessEngineAPI.registerCommand(kbd, 'firefox go to next form control', False, [kbd.AEK_G])
535 #AccessEngineAPI.registerCommand(kbd, 'firefox go to next image', False, [kbd.AEK_I])
536 #AccessEngineAPI.registerCommand(kbd, 'firefox go to next heading', False, [kbd.AEK_H])
537 #AccessEngineAPI.registerCommand(kbd, 'firefox go to next list', False, [kbd.AEK_L])
538 #AccessEngineAPI.registerCommand(kbd, 'firefox go to next list item', False, [kbd.AEK_SEMICOLON])
539 #AccessEngineAPI.registerCommand(kbd, 'firefox go to next section', False, [kbd.AEK_S])
540 #AccessEngineAPI.registerCommand(kbd, 'firefox go to next radio button', False, [kbd.AEK_R])
541 #AccessEngineAPI.registerCommand(kbd, 'firefox go to next table', False, [kbd.AEK_T])
542 #AccessEngineAPI.registerCommand(kbd, 'firefox go to next unvisited link', False, [kbd.AEK_U])
543 #AccessEngineAPI.registerCommand(kbd, 'firefox go to next visited link', False, [kbd.AEK_V])
544 ## navigation by landmark
545 #AccessEngineAPI.registerCommand(kbd, 'firefox go to next banner', False, [kbd.AEK_OPEN_BRACKET])
546 #AccessEngineAPI.registerCommand(kbd, 'firefox go to next content info', False, [kbd.AEK_QUOTE])
547 #AccessEngineAPI.registerCommand(kbd, 'firefox go to next definition', False, [kbd.AEK_PERIOD])
548 #AccessEngineAPI.registerCommand(kbd, 'firefox go to next main', False, [kbd.AEK_M])
549 #AccessEngineAPI.registerCommand(kbd, 'firefox go to next navigation', False, [kbd.AEK_N])
550 #AccessEngineAPI.registerCommand(kbd, 'firefox go to next note', False, [kbd.AEK_O])
551 #AccessEngineAPI.registerCommand(kbd, 'firefox go to next search', False, [kbd.AEK_COMMA])
552 #AccessEngineAPI.registerCommand(kbd, 'firefox go to next secondary', False, [kbd.AEK_Y])
553 #AccessEngineAPI.registerCommand(kbd, 'firefox go to next see also', False, [kbd.AEK_P])
554 ## navigation by relation
555 #AccessEngineAPI.registerCommand(kbd, 'firefox go to next different', False, [kbd.AEK_J])
556 #AccessEngineAPI.registerCommand(kbd, 'firefox go to next similar', False, [kbd.AEK_K])
557 ## link preview
558 #modifiers = [kbd.AEK_CAPS_LOCK]
559 #for m in modifiers:
560 #AccessEngineAPI.registerCommand(kbd, 'firefox read link preview', False, [m,kbd.AEK_K])
561
562 ## now do get previous commands Shift-*
563 #modifiers = [kbd.AEK_SHIFT_R, kbd.AEK_SHIFT_L]
564 #for m in modifiers:
565 #AccessEngineAPI.registerCommand(kbd, 'firefox go to prev anchor', False, [m,kbd.AEK_A])
566 #AccessEngineAPI.registerCommand(kbd, 'firefox go to prev embed', False, [m,kbd.AEK_D])
567 #AccessEngineAPI.registerCommand(kbd, 'firefox go to prev button', False, [m,kbd.AEK_B])
568 #AccessEngineAPI.registerCommand(kbd, 'firefox go to prev check box', False, [m,kbd.AEK_X])
569 #AccessEngineAPI.registerCommand(kbd, 'firefox go to prev combo box', False, [m,kbd.AEK_C])
570 #AccessEngineAPI.registerCommand(kbd, 'firefox go to prev entry', False, [m,kbd.AEK_E])
571 #AccessEngineAPI.registerCommand(kbd, 'firefox go to prev form', False, [m,kbd.AEK_F])
572 #AccessEngineAPI.registerCommand(kbd, 'firefox go to prev form control', False, [m,kbd.AEK_G])
573 #AccessEngineAPI.registerCommand(kbd, 'firefox go to prev image', False, [m,kbd.AEK_I])
574 #AccessEngineAPI.registerCommand(kbd, 'firefox go to prev heading', False, [m,kbd.AEK_H])
575 #AccessEngineAPI.registerCommand(kbd, 'firefox go to prev list', False, [m,kbd.AEK_L])
576 #AccessEngineAPI.registerCommand(kbd, 'firefox go to prev list item', False, [m,kbd.AEK_SEMICOLON])
577 #AccessEngineAPI.registerCommand(kbd, 'firefox go to prev section', False, [m,kbd.AEK_S])
578 #AccessEngineAPI.registerCommand(kbd, 'firefox go to prev radio button', False, [m,kbd.AEK_R])
579 #AccessEngineAPI.registerCommand(kbd, 'firefox go to prev table', False, [m,kbd.AEK_T])
580 #AccessEngineAPI.registerCommand(kbd, 'firefox go to prev unvisited link', False, [m,kbd.AEK_U])
581 #AccessEngineAPI.registerCommand(kbd, 'firefox go to prev visited link', False, [m,kbd.AEK_V])
582 ## navigation by landmark
583 #AccessEngineAPI.registerCommand(kbd, 'firefox go to prev banner', False, [m,kbd.AEK_OPEN_BRACKET])
584 #AccessEngineAPI.registerCommand(kbd, 'firefox go to prev content info', False, [m,kbd.AEK_QUOTE])
585 #AccessEngineAPI.registerCommand(kbd, 'firefox go to prev definition', False, [m,kbd.AEK_PERIOD])
586 #AccessEngineAPI.registerCommand(kbd, 'firefox go to prev main', False, [m,kbd.AEK_M])
587 #AccessEngineAPI.registerCommand(kbd, 'firefox go to prev navigation', False, [m,kbd.AEK_N])
588 #AccessEngineAPI.registerCommand(kbd, 'firefox go to prev note', False, [m,kbd.AEK_O])
589 #AccessEngineAPI.registerCommand(kbd, 'firefox go to prev search', False, [m,kbd.AEK_COMMA])
590 #AccessEngineAPI.registerCommand(kbd, 'firefox go to prev secondary', False, [m,kbd.AEK_Y])
591 #AccessEngineAPI.registerCommand(kbd, 'firefox go to prev see also', False, [m,kbd.AEK_P])
592 ## navigation by relation
593 #AccessEngineAPI.registerCommand(kbd, 'firefox go to prev different', False, [m,kbd.AEK_J])
594 #AccessEngineAPI.registerCommand(kbd, 'firefox go to prev similar', False, [m,kbd.AEK_K])
595 ## some additional document mode reading commands
596 #AccessEngineAPI.registerCommand(kbd, 'firefox go to item start', False, [kbd.AEK_HOME])
597 #AccessEngineAPI.registerCommand(kbd, 'firefox go to item end', False, [kbd.AEK_END])
598 #modifiers = [kbd.AEK_CONTROL_R, kbd.AEK_CONTROL_L]
599 #for m in modifiers:
600 #AccessEngineAPI.registerCommand(kbd, 'firefox go to doc start', False, [m, kbd.AEK_HOME])
601 #AccessEngineAPI.registerCommand(kbd, 'firefox go to doc end', False, [m, kbd.AEK_END])
602 ## set our flag
603 #self.nav_element_reg = True
604
605 #def unregisterNavByElement(self):
606 #'''
607 #Unregisters keys related to navigation by element, navigation by landmark,
608 #and navigation by relation.
609 #'''
610 #if self.nav_element_reg:
611 #kbd = AccessEngineAPI.getInputDevice(None, 'keyboard')
612 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_A])
613 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_D])
614 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_B])
615 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_X])
616 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_C])
617 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_E])
618 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_F])
619 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_G])
620 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_I])
621 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_H])
622 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_L])
623 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_SEMICOLON])
624 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_S])
625 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_R])
626 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_T])
627 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_U])
628 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_V])
629 ## navigation by landmark
630 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_OPEN_BRACKET])
631 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_QUOTE])
632 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_PERIOD])
633 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_M])
634 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_N])
635 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_O])
636 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_COMMA])
637 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_Y])
638 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_P])
639 ## navigation by relation
640 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_J])
641 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_K])
642 ## link preview
643 #modifiers = [kbd.AEK_CAPS_LOCK]
644 #for m in modifiers:
645 #AccessEngineAPI.unregisterCommand(kbd, [m,kbd.AEK_K])
646
647 ## now do get previous commands Shift-*
648 #modifiers = [kbd.AEK_SHIFT_R, kbd.AEK_SHIFT_L]
649 #for m in modifiers:
650 #AccessEngineAPI.unregisterCommand(kbd, [m,kbd.AEK_A])
651 #AccessEngineAPI.unregisterCommand(kbd, [m,kbd.AEK_D])
652 #AccessEngineAPI.unregisterCommand(kbd, [m,kbd.AEK_B])
653 #AccessEngineAPI.unregisterCommand(kbd, [m,kbd.AEK_X])
654 #AccessEngineAPI.unregisterCommand(kbd, [m,kbd.AEK_C])
655 #AccessEngineAPI.unregisterCommand(kbd, [m,kbd.AEK_E])
656 #AccessEngineAPI.unregisterCommand(kbd, [m,kbd.AEK_F])
657 #AccessEngineAPI.unregisterCommand(kbd, [m,kbd.AEK_G])
658 #AccessEngineAPI.unregisterCommand(kbd, [m,kbd.AEK_I])
659 #AccessEngineAPI.unregisterCommand(kbd, [m,kbd.AEK_H])
660 #AccessEngineAPI.unregisterCommand(kbd, [m,kbd.AEK_L])
661 #AccessEngineAPI.unregisterCommand(kbd, [m,kbd.AEK_SEMICOLON])
662 #AccessEngineAPI.unregisterCommand(kbd, [m,kbd.AEK_S])
663 #AccessEngineAPI.unregisterCommand(kbd, [m,kbd.AEK_R])
664 #AccessEngineAPI.unregisterCommand(kbd, [m,kbd.AEK_T])
665 #AccessEngineAPI.unregisterCommand(kbd, [m,kbd.AEK_U])
666 #AccessEngineAPI.unregisterCommand(kbd, [m,kbd.AEK_V])
667 ## navigation by landmark
668 #AccessEngineAPI.unregisterCommand(kbd, [m,kbd.AEK_OPEN_BRACKET])
669 #AccessEngineAPI.unregisterCommand(kbd, [m,kbd.AEK_QUOTE])
670 #AccessEngineAPI.unregisterCommand(kbd, [m,kbd.AEK_PERIOD])
671 #AccessEngineAPI.unregisterCommand(kbd, [m,kbd.AEK_M])
672 #AccessEngineAPI.unregisterCommand(kbd, [m,kbd.AEK_N])
673 #AccessEngineAPI.unregisterCommand(kbd, [m,kbd.AEK_O])
674 #AccessEngineAPI.unregisterCommand(kbd, [m,kbd.AEK_COMMA])
675 #AccessEngineAPI.unregisterCommand(kbd, [m,kbd.AEK_Y])
676 #AccessEngineAPI.unregisterCommand(kbd, [m,kbd.AEK_P])
677 ## navigation by relation
678 #AccessEngineAPI.unregisterCommand(kbd, [m,kbd.AEK_J])
679 #AccessEngineAPI.unregisterCommand(kbd, [m,kbd.AEK_K])
680 ## some additional document mode reading commands
681 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_HOME])
682 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_END])
683 #modifiers = [kbd.AEK_CONTROL_R, kbd.AEK_CONTROL_L]
684 #for m in modifiers:
685 #AccessEngineAPI.unregisterCommand(kbd, [m, kbd.AEK_HOME])
686 #AccessEngineAPI.unregisterCommand(kbd, [m, kbd.AEK_END])
687 ## set our flag
688 #self.nav_element_reg = False
689
690 #def registerConvReview(self):
691 #'''
692 #Registers convenience review keys. Does not attempt to register if
693 #already registered
694 #'''
695 #if not self.convkey_reg:
696 #kbd = AccessEngineAPI.getInputDevice(None, 'keyboard')
697 #AccessEngineAPI.registerCommand(kbd, 'firefox convenience review', False,
698 #[kbd.AEK_LEFT])
699 #AccessEngineAPI.registerCommand(kbd, 'firefox convenience review', False,
700 #[kbd.AEK_RIGHT])
701 #AccessEngineAPI.registerCommand(kbd, 'firefox convenience review', False,
702 #[kbd.AEK_UP])
703 #AccessEngineAPI.registerCommand(kbd, 'firefox convenience review', False,
704 #[kbd.AEK_DOWN])
705
706 #modifiers = [[kbd.AEK_CONTROL_R], [kbd.AEK_CONTROL_L]]
707 #keys = [kbd.AEK_LEFT, kbd.AEK_RIGHT]
708 #for modifier in modifiers:
709 #for key in keys:
710 #AccessEngineAPI.registerCommand(kbd, 'firefox convenience review', False,
711 #modifier+[key])
712 #self.convkey_reg = True
713
714 #def unregisterConvReview(self):
715 #'''
716 #Unregisters convenience review keys. Does not attempt to unregister if
717 #already unregistered
718 #'''
719 #if self.convkey_reg:
720 #kbd = AccessEngineAPI.getInputDevice(None, 'keyboard')
721 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_LEFT])
722 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_RIGHT])
723 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_UP])
724 #AccessEngineAPI.unregisterCommand(kbd, [kbd.AEK_DOWN])
725
726 #modifiers = [[kbd.AEK_CONTROL_R], [kbd.AEK_CONTROL_L]]
727 #keys = [kbd.AEK_LEFT, kbd.AEK_RIGHT]
728 #for modifier in modifiers:
729 #for key in keys:
730 #AccessEngineAPI.unregisterCommand(kbd, modifier+[key])
731 #self.convkey_reg = False
732
733 #def registerTableReview(self):
734 #'''
735 #Registers keys related to table navigation.
736 #'''
737 #pass
738 ## print 'FirefoxScript: registerTableReview not implemented'
739
740 #def unregisterTableReview(self):
741 #'''
742 #Unregisters keys related to table navigation.
743 #'''
744 #pass
745 ## print 'FirefoxScript: unregisterTableReview not implemented'
746
747 ## ****** Search and go to predicates ******
748 #def rolePredicate(self, por, role=None, **kwargs):
749 #''' Generic predicate used for a single role comparison '''
750 #return (AccessEngineAPI.hasAccRole(role, por=por))
751
752 #def attrPredicate(self, por, key=None, value=None, **kwargs):
753 #''' Generic predicate used for a single key/value attribute comparison '''
754 #testattrs = AccessEngineAPI.getAccAttrs(por=por)
755 #if testattrs is None:
756 #return False
757 #try:
758 #if testattrs[key] == value:
759 #return True
760 #except (TypeError, KeyError):
761 #return False
762
763 #def entryPredicate(self, por):
764 #''' Predicate used for finding entry/password text accessibles '''
765 #role = AccessEngineAPI.getAccRole(por=por)
766 #return (role == 'entry' or role == 'password text')
767
768 #def formcontrolPredicate(self, por):
769 #''' Predicate used for finding next form control '''
770 #try:
771 #attrs = AccessEngineAPI.getAccAttrs(por=por)
772 #return attrs['tag'] == 'INPUT' or attrs['tag'] == 'SELECT'
773 #except (TypeError, KeyError):
774 #return False
775
776 #def unvisitedlinkPredicate(self, por):
777 #''' Predicate used for finding an unvisited link '''
778 #try:
779 #return (AccessEngineAPI.getAccAttrs(por=por)['tag'] == 'A' \
780 #and not AccessEngineAPI.hasAccState('visited', por=por))
781 #except (TypeError, KeyError):
782 #return False
783
784 #def visitedlinkPredicate(self, por):
785 #''' Predicate used for finding a visited link '''
786 #try:
787 #return (AccessEngineAPI.getAccAttrs(por=por)['tag'] == 'A' \
788 #and AccessEngineAPI.hasAccState('visited', por=por))
789 #except (TypeError, KeyError):
790 #return False
791
792 #def tablePredicate(self, por, **kwargs):
793 #return (AccessEngineAPI.getAccRole(por=por) == 'table' and \
794 #not self.isLayoutTable(por, 'table'))
795
796
797 #class HandleAutocomplete(Task.StateTask):
798 #'''
799 #Announces autocomplete menu opening
800 #'''
801 #def execute(self, por, name, value, **kwargs):
802 #if name == 'visible' and value == 1:
803 #role = self.getAccRole(por)
804 #if role == 'tree' or role == 'tree table':
805 #self.sayState(text=_('autocomplete menu opened'))
806
807 #class ModeChangerOnView(Task.ViewTask):
808 #'''
809 #Sets the proper reading mode on a view event. The mode will always be set
810 #to WIDGET_MODE on a view lost event, while the view gained event will
811 #pass and let the focus gained event do the work.
812 #'''
813 #def executeLost(self, por, **kwargs):
814 #if self.script.savedmode is None:
815 #self.script.savedmode = self.script.currentmode
816 #self.script.setMode(WIDGET_MODE)
817
818 #class ModeChangerOnFocus(Task.FocusTask):
819 #'''
820 #Sets proper reading mode on a focus event. The mode is based on the saved
821 #mode (obtained when leaving doc frame), if available, or the current L{AEPor}.
822 #'''
823 #def executeLost(self, por, **kwargs):
824 #if not self.script.getDocFrame(por):
825 #if self.script.savedmode is None:
826 #self.script.savedmode = self.script.currentmode
827 #self.script.setMode(WIDGET_MODE)
828
829 #def executeGained(self, por, **kwargs):
830 ## if in doc frame restore saved mode if possible else set mode according to
831 ## current por
832 #if self.script.getDocFrame(por):
833 #if self.script.savedmode is not None:
834 #self.script.setMode(self.script.savedmode)
835 #self.script.savedmode = None
836 #else:
837 #self.script.setModeByPOR(por)
838 ## in chrome. store mode and set to WIDGET_MODE
839 #else:
840 #if self.script.savedmode is None:
841 #self.script.savedmode = self.script.currentmode
842 #self.script.setMode(WIDGET_MODE)
843
844 #class ModeChangerOnUser(Task.InputTask):
845 #'''
846 #Allows the user to enter or leave the suggested navigation mode.
847
848 #@todo: adhere to new mode method
849 #@param por: Point of regard to test
850 #@type por: L{AEPor}
851 #'''
852 #def execute(self, **kwargs):
853 #if self.script_state.AutoMode:
854 #if self.script.currentmode == DOCUMENT_MODE:
855 #currentmode = self.script.setModeByPOR(self.task_por)
856 #if currentmode == DOCUMENT_MODE:
857 #self.sayInfo(text=_('still in document mode'))
858 #elif self.script.currentmode == TABLE_MODE:
859 #pass
860 #elif self.script.currentmode == WIDGET_MODE:
861 #self.script.setMode(DOCUMENT_MODE)
862 ## set focus if need be
863 #if self.script.needsFocus(self.task_por):
864 #self.setAccPOR()
865 #else:
866 #if self.script.currentmode == DOCUMENT_MODE:
867 #self.script.setMode(WIDGET_MODE)
868 #else:
869 #self.script.setMode(DOCUMENT_MODE)
870 ## set focus if need be
871 #if self.script.needsFocus(self.task_por):
872 #self.setAccPOR()
873
874 #class ConvReview(Task.InputTask):
875 #'''
876 #Provides convenience key functionality by calling the appropriate
877 #review task.
878
879 #Review keys are registered/unregistered with the focus and view event
880 #handlers, L{ModeChangerOnFocus} and L{ModeChangerOnView} respectively. They
881 #force the review keys to be active only within a document frame.
882 #'''
883 #def execute(self, gesture=None, **kwargs):
884 #kbd = self.AccessEngineAPI.getInputDevice(None, 'keyboard')
885 ## handle item first, most common
886 #if kbd.AEK_UP in gesture:
887 #self.doTask('review previous item')
888 #elif kbd.AEK_DOWN in gesture:
889 #self.doTask('review next item')
890 ## check for word before character, since it's the more specific case
891 #elif kbd.AEK_LEFT in gesture and \
892 #(kbd.AEK_CONTROL_R in gesture or kbd.AEK_CONTROL_L in gesture):
893 #self.doTask('review previous word')
894 #elif kbd.AEK_RIGHT in gesture and \
895 #(kbd.AEK_CONTROL_R in gesture or kbd.AEK_CONTROL_L in gesture):
896 #self.doTask('review next word')
897 ## now check character
898 #elif kbd.AEK_LEFT in gesture:
899 #self.doTask('review previous char')
900 #elif kbd.AEK_RIGHT in gesture:
901 #self.doTask('review next char')
902
903 #class HandleDocumentPORView(Task.ViewTask):
904 #'''
905 #Returns to the last user point of regard in a document after the Firefox
906 #window is reactivated.
907 #'''
908 #def executeLost(self, por, **kwargs):
909 #'''
910 #Store the pointer using it's doc frame as key.
911 #'''
912 #self.script.viewlost = True
913 #doc = self.script.getDocFrame(self.getPointerPOR())
914 #if doc is not None:
915 #self.script.doc_pors[doc] = self.getPointerPOR()
916 ## clear cached pointer that is set during caret event
917 #self.script.cached_pointer = None
918
919 #class HandleDocumentPORFocus(Task.FocusTask):
920 #'''
921 #Tracks the last position reviewed in a document so that it may become the
922 #user's L{AEPor} again after focus is restored to the document.
923 #'''
924 #def executeGained(self, por, **kwargs):
925 #'''
926 #Try to restore the pointer. Use the current doc frame as index into
927 #script.doc_pors.
928 #'''
929 ## clear cached pointer that is set during caret event and only used in
930 ## executeLost.
931 #self.script.cached_pointer = None
932
933 ## get a local copy of viewlost. viewlost is set in view executeLost and
934 ## is used for restoration after an application switch
935 #viewlost = self.script.viewlost
936 #self.script.viewlost = False
937
938 ## get a local copy of the last por that was in focus. This is used to
939 ## help differentiate menu selections from tab/tab-shift events.
940 #lastporinfocus = self.script.lastporinfocus
941 #self.script.lastporinfocus = por
942
943 ## is the user tabbing or tab browsing
944 #currentdocinfocus = self.script.getActiveDocFrame()
945 #if self.script.lastdocinfocus is None or \
946 #self.script.lastdocinfocus != currentdocinfocus:
947 #tabbrowsing = True
948 #else:
949 #tabbrowsing = False
950 #self.script.lastdocinfocus = currentdocinfocus
951
952 ## try to restore the saved POR for all tab browsing events
953 #if tabbrowsing:
954 ## try to restore pointer for this doc frame
955 #try:
956 ## only restore if we are within doc frame
957 #if self.script.getDocFrame(self.task_por):
958 ## announce window title if restoration will occur
959 #if self.script.doc_pors.has_key(currentdocinfocus):
960 #self.inhibitMayStop()
961 #self.sayWindow()
962 ## try to do restoration
963 #self.doTask('pointer to por',
964 #por=self.script.doc_pors[currentdocinfocus])
965 ## consume the next selector to block selector announcements
966 #AccessEngineAPI.blockNTasks(1, Task.SelectorTask)
967 ## register/unregister convenience keys after pointer move
968 #self.script.setModeByPOR(self.task_por)
969 ## don't propagate task chain
970 #return False
971 #else:
972 #return True
973 #except KeyError:
974 ## the selector event will make announcement
975 #return False
976 ## user is hitting tab/tab-shift.
977 #else:
978 #lastrole = self.getAccRole(lastporinfocus)
979
980 ## Try to restore only for certain cases that are misinterpreted
981 ## as a tab/tab-shift event. This includes when a view lost event
982 ## occured
983 #if viewlost or ((lastrole == 'menu' or lastrole == 'menu item') \
984 #and self.script.getDocFrame(por)):
985 #try:
986 ## only restore if we are within doc frame
987 #if self.script.getDocFrame(self.task_por):
988 #self.doTask('pointer to por',
989 #por=self.script.doc_pors[currentdocinfocus])
990 ## consume the next selector to block selector announcements
991 #AccessEngineAPI.blockNTasks(1, Task.SelectorTask)
992 ## register/unregister convenience keys after pointer move
993 #self.script.setModeByPOR(self.task_por)
994 ## don't propagate task chain
995 #return False
996 #else:
997 #return True
998 #except KeyError:
999 ## let propagated events make announcements
1000 #return True
1001
1002 #def executeLost(self, por, **kwargs):
1003 #'''
1004 #Store the pointer using it's container doc frame as index if both task_por and
1005 #pointer are with doc frame.
1006 #'''
1007 ## get the cached pointer from caret event or the current pointer
1008 #pointer = self.script.cached_pointer or self.getPointerPOR()
1009 ## If the current por is the doc frame, make sure pointer is also within
1010 ## the doc frame. Store it if it is.
1011 #if self.hasAccRole(DOCUMENT_ROLE, por):
1012 #if self.script.getDocFrame(pointer) is not None:
1013 #self.script.doc_pors[por] = pointer
1014 #else:
1015 ## find doc frame of current pointer. Store pointer if found.
1016 #doc = self.script.getDocFrame(pointer)
1017 #if doc is not None:
1018 #self.script.doc_pors[doc] = pointer
1019 ## clear cached pointer that is set during caret event
1020 #self.script.cached_pointer = None
1021
1022
1023 #class PointerCache(Task.CaretTask):
1024 #'''
1025 #Saves pointer for document, fixes case where tabbing from page with focus in
1026 #document frame to page with focus in URL bar. Without this fix a caret event
1027 #switches the pointer before the focus event. Must be the
1028 #first caret event handler.
1029 #'''
1030 #def execute(self, por, **kwargs):
1031 #if self.script.getDocFrame(self.getPointerPOR()) and \
1032 #not self.script.getDocFrame(por):
1033 #self.script.cached_pointer = self.getPointerPOR()
1034
1035
1036 #class ExtraCarets(Task.CaretTask):
1037 #'''
1038 #Ignores extra caret events sent after selection of in-page content that
1039 #this is not editable.
1040 #'''
1041 #def execute(self, por, **kwargs):
1042 #if not self.hasAccState('editable'):
1043 #return False
1044
1045 #class ReadDocAddressAndTitle(Task.InputTask):
1046 #'''
1047 #Reads the address of the current document.
1048 #'''
1049 #def execute(self, cycle_count, **kwargs):
1050 #'''
1051 #Cyclical task. 1) Announces the window title. 2) Does a search of the
1052 #accessible hierarchy for the urlbar then finds the entry field in
1053 #the urlbar to announce its text.
1054 #'''
1055 #self.stopNow()
1056 #if cycle_count % 3 == 0:
1057 #self.sayWindow()
1058 #elif cycle_count % 3 == 1:
1059 #attrs = self.getAccAttrs(por=self.script.getActiveDocFrame())
1060 #self.sayItem(text=_(attrs['DocURL']))
1061 #else:
1062 #self._readPageSummary()
1063
1064 #def _readPageSummary(self):
1065 #'''
1066 #Reads the quantity of headings, forms, tables, visited and unvisited links,
1067 #plus the locale.
1068
1069 #@todo: optimize with L{Collections}.
1070 #'''
1071 #headings = 0
1072 #forms = 0
1073 #tables = 0
1074 #vlinks = 0
1075 #uvlinks = 0
1076 #nodetotal = 0
1077
1078 ## set start of iteration
1079 #startpor = self.script.getActiveDocFrame()
1080 ## set end of iteration, either next tab panel or last acc
1081 #endpor = self.script.getLastSearchAcc()
1082 ## begin traversal of document
1083 #for i in self.iterNextItems(por=startpor, wrap=True):
1084 ## track the number of nodes seen
1085 #nodetotal += 1
1086 ## safety net in case of cyclical navigation/ very long document
1087 #if nodetotal > self.script_state.SearchDepth:
1088 #self.sayInfo(_('search depth reached'))
1089 #return
1090 ## some politeness
1091 #if nodetotal == 200:
1092 #self.sayInfo(text=_('one moment please'))
1093 #time.sleep(.1)
1094 #if not nodetotal % 1000:
1095 #self.sayInfo(text=_('%d nodes searched' %nodetotal))
1096 #time.sleep(.1)
1097 ## search is over when endpor is seen
1098 #if i == endpor:
1099 #break
1100 #role = self.getAccRole(por=i)
1101 #if role == 'heading':
1102 #headings += 1
1103 #elif role == 'form':
1104 #forms += 1
1105 #elif role == 'table' and self.script.isLayoutTable(i, role):
1106 #tables += 1
1107 #elif self.script.visitedlinkPredicate(i):
1108 #vlinks += 1
1109 #elif self.script.unvisitedlinkPredicate(i):
1110 #uvlinks += 1
1111 ## get our locale
1112 #locale = self.getAccAppLocale()
1113 ## form output and send it
1114 #text = (headings, forms, tables, vlinks, uvlinks, locale)
1115 #template = _('%d headings. %d forms. %d tables. %d visited links. \
1116 #%d unvisited links. locale is %s')
1117 #self.sayInfo(text=text, template=template)
1118
1119 #class FirefoxReview(Task.InputTask):
1120 #'''
1121 #This task is chained around all previous/next review tasks so that it can
1122 #handle cases specific to Firefox. It provides the following features.
1123
1124 #1. Registration and unregistration of convenience review keys when reviewing
1125 #over unfocusable and focusable elements in the document frame.
1126 #2. Giving focus to focusable elements encountered during review while
1127 #respecting user settings.
1128 #3. Bounding the review to the active document while respecting user settings.
1129 #'''
1130 #def _isInDoc(self, por=None):
1131 #'''
1132 #@return: Is the given L{AEPor} inside the document frame or is it the
1133 #document frame itself?
1134 #@rtype: boolean
1135 #'''
1136 #return (AccessEngineAPI.findAccByRole(DOCUMENT_ROLE, por, ancestor=True) is not None
1137 #or self.hasAccRole(DOCUMENT_ROLE, por))
1138
1139 #def _needsBounding(self):
1140 #'''
1141 #@return: Should the review be bounded to the current document frame
1142 #according to the user settings?
1143 #@rtype: boolean
1144 #'''
1145 #return self.getScriptSettingVal('BoundReview')
1146
1147 #def _setScroll(self, por):
1148 #'''
1149 #Scrolls the screen to bring the por visible trying to account for bullets
1150 #and other oddities.
1151
1152 #@param por: Point of regard to scroll in view
1153 #@type por: L{AEPor}
1154 #'''
1155 #role = self.getAccRole(por=por)
1156 #if role == 'list item' or role == 'menu item':
1157 #if self.getAnchorTaskId().find(' next ') > 0:
1158 #por = self.getNextItem(por=por, wrap=True)
1159 #else:
1160 #por = self.getPrevItem(por=por, wrap=True)
1161 #self.setAccCaret(por=por)
1162
1163 #def execute(self, **kwargs):
1164 ## start off assuming we're going to call the arounded review task
1165 #original = True
1166 ## start off assuming we're going to let other tasks execute in the chain
1167 #propagate = True
1168 ## check if we're inside or outside the document to start
1169 #in_doc = self._isInDoc()
1170 ## check whether the next/previous chunk we're reviewing is inside or
1171 ## outside the document
1172 #self.doTask('%s peek' % self.getAnchorTaskId(),
1173 #onlyvisible=False, chain=False)
1174 #next_por = self.getTempVal('peek')
1175 #next_in_doc = self._isInDoc(next_por)
1176 ## now determine whether we're 1) in doc to in doc, 2) out of doc to in doc,
1177 ## 3) in doc to out of doc, or 4) out of doc to out of doc
1178 ## navigating within document or into the document (1 and 2)
1179 #if next_in_doc:
1180 ## moving caret programmatically scrolls screen and brings por into view.
1181 ## need to set the next item to account for lists. Must be called before
1182 ## any other set focus type calls
1183 #self._setScroll(next_por)
1184 ## check if the item should get the focus
1185 ## edge case where we just entered doc frame from chrome
1186 #if not in_doc:
1187 ## set the focus to the document frame as we pass by it
1188 #self.setAccFocus(self.script.getActiveDocFrame())
1189 #elif self.script.needsFocus(next_por):
1190 ## set focus to a manipulable
1191 #self.setAccPOR(next_por)
1192 ## inhibit the focus announcement to follow
1193 #original = False
1194 #propagate = False
1195 ## register/unregister convenience review keys
1196 #self.script.setModeByPOR(next_por)
1197 #elif in_doc and not next_in_doc:
1198 ## navigating out of the document (3)
1199 ## check if the user wants the review to hit a wall here
1200 #if self._needsBounding():
1201 ## we're at the edge of a document, set the review return value properly
1202 #anchor = self.getAnchorTaskId()
1203 #if anchor.startswith('review next'):
1204 ## at the end
1205 #self.tier.setTempVal('review', AEConstants.REVIEW_NO_NEXT_ITEM)
1206 #elif anchor.startswith('review previous'):
1207 ## at the beginning
1208 #self.tier.setTempVal('review', AEConstants.REVIEW_NO_PREV_ITEM)
1209 ## do not call the arounded task as we're setting the bound flags
1210 ## ourselves
1211 #original = False
1212 #else:
1213 ## unregister review keys
1214 #self.script.setModeByPOR(next_por)
1215 ## navigating in the chrome (4)
1216 ## do nothing, let the review procede as normal
1217 #if original:
1218 ## execute the anchor, but do not let its immediate chains run too since
1219 ## that would end up re-executing this task ad infinitum
1220 #self.doTask(self.getAnchorTaskId(), chain=False)
1221 #return propagate
1222
1223 #class ReadReviewRole(Task.Task):
1224 #'''
1225 #Task is chained around (overrides) 'read new role'. Speaks the role
1226 #of the given L{AEPor} or substitutes an output based on the role type.
1227 #Speaks the role of the given L{AEPor} or the L{task_por} if no L{AEPor} is
1228 #given only if it is different than the last role spoken by this method or
1229 #if the RepeatRole setting is True.
1230
1231 #@param por: Point of regard to the accessible whose role should be said,
1232 #defaults to L{task_por} if None
1233 #@type por: L{AEPor}
1234 #'''
1235 #def execute(self, por=None, role=None, **kwargs):
1236 #rolename = self.getAccRoleName(por) or _('link')
1237 ## get untranslated role name
1238 #role = self.getAccRole(por)
1239 #if role == 'heading':
1240 #attrs = self.getAccAttrs()
1241 #if attrs is not None and attrs.has_key('level'):
1242 ## i18n: 1st string is translated word 'heading', second is value 1
1243 ## through 6
1244 #outtext = _("%s level %s") % (rolename, attrs['level'])
1245 #else:
1246 #outtext = rolename
1247 #else: # default case
1248 #outtext = rolename
1249
1250 #if not ((role in self.script.SKIPPED_ROLES) or
1251 #(role == 'table cell' and self.script.isLayoutTable(por, role))):
1252 ## invoke the anchor with our pre-computed text
1253 #self.doTask(self.getAnchorTaskId(), role=outtext, por=por, chain=False,
1254 #**kwargs)
1255
1256 #class ReviewShouldSkip(Task.InputTask):
1257 #'''
1258 #Task is chained after 'review should skip' and provides additional rules to
1259 #determines if the current L{AEPor} should be skipped or not based on the
1260 #role of the accessible.
1261
1262 #@param por: Point of regard to test
1263 #@type por: L{AEPor}
1264 #'''
1265 #def execute(self, peek, por=None, **kwargs):
1266 #text = self.getItemText(por)
1267 #role = self.getAccRole(por=por)
1268 #layouttable = self.script.isLayoutTable(por, role)
1269 #if (text.strip() or self.hasOneAccState(por, 'focusable', 'editable')):
1270 ## has content or can have content from the user, don't skip
1271 #self.tier.setTempVal('should skip', False)
1272 #return
1273
1274 #skipping = self.getScriptSettingVal(self.tier, 'ReviewScript', 'Skipping')
1275 #if skipping == AEConstants.SKIP_ALL:
1276 #self.tier.setTempVal('should skip', True)
1277 #elif skipping == AEConstants.SKIP_NONE:
1278 #self.tier.setTempVal('should skip', False)
1279 #elif skipping == AEConstants.SKIP_REPORT:
1280 #if not peek:
1281 #if (role == 'table' or role == 'table cell') and layouttable:
1282 ## if we're on a layout table
1283 ## update the task POR so it points to it
1284 #self.moveToPOR(por)
1285 ## DO NOT announce anything or set any skipping flags
1286 ## we didn't report anything so we don't want to inhibitMayStop
1287 ## by accident
1288 #else:
1289 ## update the task POR to the next location
1290 #self.moveToPOR(por)
1291 ## if we're not on a layout table
1292 ## then invoke the review report task
1293 #self.doTask('review skip report')
1294 ## indicate something has been skipped and reported
1295 #self.tier.setTempVal('has skipped', True)
1296 #else:
1297 ## indicate something will be skipped and reported
1298 #self.tier.setTempVal('will skip', True)
1299 ## always give the peek hint that something should be skipped
1300 #self.tier.setTempVal('should skip', True)
1301
1302 #class GoToActiveDoc(Task.InputTask):
1303 #'''
1304 #Moves pointer to the restore por location if available and user is
1305 #navigating chrome, otherwise pointer is set to the active document frame.
1306
1307 #@param por: Point of regard to test
1308 #@type por: L{AEPor}
1309 #'''
1310 #def execute(self, por=None, **kwargs):
1311 #self.stopNow()
1312 #docframe = self.script.getActiveDocFrame()
1313 #try:
1314 ## try to use it's restore por location if in chrome
1315 #if not self.script.getDocFrame(self.task_por):
1316 #self.doTask('pointer to por', por=self.script.doc_pors[docframe])
1317 #else:
1318 #self.doTask('pointer to por', por=docframe)
1319 #except:
1320 ## just set it to the current docframe
1321 #self.doTask('pointer to por', por=docframe)
1322 ## set reading mode
1323 #self.script.setModeByPOR(self.task_por)
1324
1325 #class GoToDocStart(Task.InputTask):
1326 #'''
1327 #Moves pointer to the active document frame.
1328
1329 #@param por: Point of regard to test
1330 #@type por: L{AEPor}
1331 #'''
1332 #def execute(self, por=None, **kwargs):
1333 #self.stopNow()
1334 #self.doTask('pointer to por', por=self.script.getActiveDocFrame())
1335 ## set reading mode
1336 #self.script.setModeByPOR(self.task_por)
1337
1338 #class GoToDocEnd(Task.InputTask):
1339 #'''
1340 #Moves pointer to the end of the active document frame.
1341
1342 #@param por: Point of regard to test
1343 #@type por: L{AEPor}
1344 #'''
1345 #def execute(self, por=None, **kwargs):
1346 #self.stopNow()
1347 #endacc = self.getLastAccUnder(por=self.script.getActiveDocFrame())
1348 #self.doTask('pointer to por', por=endacc)
1349 ## set reading mode
1350 #self.script.setModeByPOR(self.task_por)
1351
1352 #class GoToItemStart(Task.InputTask):
1353 #'''
1354 #Moves pointer to the start of the current item
1355
1356 #@param por: Point of regard to test
1357 #@type por: L{AEPor}
1358 #'''
1359 #def execute(self, por=None, **kwargs):
1360 #self.stopNow()
1361 #itemstart = self.getCurrItem()
1362 #self.doTask('pointer to por', por=itemstart)
1363 ## set reading mode todo: is this necessary? would modes change?
1364 #self.script.setModeByPOR(self.task_por)
1365
1366 #class GoToItemEnd(Task.InputTask):
1367 #'''
1368 #Moves pointer to the end of the current item
1369
1370 #@param por: Point of regard to test
1371 #@type por: L{AEPor}
1372 #'''
1373 #def execute(self, por=None, **kwargs):
1374 #self.stopNow()
1375 #itemend = self.getLastChar()
1376 #self.doTask('pointer to por', por=itemend)
1377 ## set reading mode todo: is this necessary? would modes change?
1378 #self.script.setModeByPOR(self.task_por)
1379
1380 #class GoToElement(Task.InputTask):
1381 #'''
1382 #Task used for searching for an element. The search criteria and
1383 #direction of search are derived from the task identity associated to this
1384 #task. The pointer is updated and the L{AEPor} is announced upon finding the
1385 #accessible, otherwise the pointer is NOT moved and an announcement declaring
1386 #that the accessible has not been found is made.
1387
1388 #Currently used by navigation by element and navigation by landmark.
1389 #'''
1390 #def execute(self, **kwargs):
1391 #pred = None
1392 ## keyword arguments passed to predicate
1393 #kwargs = {}
1394 #taskid = self.getIdentity()
1395 ## default the output name to it's role. Change the outputname to something
1396 ## else, if the need arises, within the big if statement.
1397 #outputname = taskid.split(' ')[-1]
1398 ## set predicate (and it's kwargs) and or outputname according to last word
1399 ## in task identity
1400 #if taskid.endswith('anchor'):
1401 #pred = self.script.attrPredicate
1402 #kwargs = {'key':'tag','value':'A'}
1403 #outputname = 'link'
1404 #elif taskid.endswith('embed'):
1405 #pred = self.script.attrPredicate
1406 #kwargs = {'key':'tag','value':'EMBED'}
1407 #outputname = 'embed'
1408 #elif taskid.endswith('radio button'):
1409 #pred = self.script.rolePredicate
1410 #kwargs = {'role':'radio button'}
1411 #outputname = 'radio button'
1412 #elif taskid.endswith('button'):
1413 #pred = self.script.rolePredicate
1414 #kwargs = {'role':'push button'}
1415 #outputname = 'push button'
1416 #elif taskid.endswith('check box'):
1417 #pred = self.script.rolePredicate
1418 #kwargs = {'role':'check box'}
1419 #outputname = 'check box'
1420 #elif taskid.endswith('combo box'):
1421 #pred = self.script.rolePredicate
1422 #kwargs = {'role':'combo box'}
1423 #outputname = 'combo box'
1424 #elif taskid.endswith('entry'):
1425 #pred = self.script.entryPredicate
1426 #elif taskid.endswith('form'):
1427 #pred = self.script.rolePredicate
1428 #kwargs = {'role':'form'}
1429 #elif taskid.endswith('form control'):
1430 #pred = self.script.formcontrolPredicate
1431 #outputname = 'form control'
1432 #elif taskid.endswith('image'):
1433 #pred = self.script.rolePredicate
1434 #kwargs = {'role':'image'}
1435 #elif taskid.endswith('heading'):
1436 #pred = self.script.rolePredicate
1437 #kwargs = {'role':'heading'}
1438 #elif taskid.endswith('list'):
1439 #pred = self.script.rolePredicate
1440 #kwargs = {'role':'list'}
1441 #elif taskid.endswith('list item'):
1442 #pred = self.script.attrPredicate
1443 #kwargs = {'key':'tag','value':'LI'}
1444 #outputname = 'list item'
1445 ## todo: set outputname to list item or menu item based on results
1446 #elif taskid.endswith('section'):
1447 #pred = self.script.rolePredicate
1448 #kwargs = {'role':'section'}
1449 #elif taskid.endswith('table'):
1450 #pred = self.script.tablePredicate
1451 #outputname = 'table'
1452 #elif taskid.endswith('unvisited link'):
1453 #pred = self.script.unvisitedlinkPredicate
1454 #outputname = 'unvisited link'
1455 #elif taskid.endswith('visited link'):
1456 #pred = self.script.visitedlinkPredicate
1457 #outputname = 'visited link'
1458 ## navigation by landmark
1459 #elif taskid.endswith('banner'):
1460 #pred = self.script.attrPredicate
1461 #kwargs = {'key':'xml-roles','value':'banner'}
1462 #outputname = 'banner'
1463 #elif taskid.endswith('content info'):
1464 #pred = self.script.attrPredicate
1465 #kwargs = {'key':'xml-roles','value':'contentinfo'}
1466 #outputname = 'content info'
1467 #elif taskid.endswith('definition'):
1468 #pred = self.script.attrPredicate
1469 #kwargs = {'key':'xml-roles','value':'definition'}
1470 #outputname = 'definition'
1471 #elif taskid.endswith('main'):
1472 #pred = self.script.attrPredicate
1473 #kwargs = {'key':'xml-roles','value':'main'}
1474 #outputname = 'main'
1475 #elif taskid.endswith('navigation'):
1476 #pred = self.script.attrPredicate
1477 #kwargs = {'key':'xml-roles','value':'navigation'}
1478 #outputname = 'navigation'
1479 #elif taskid.endswith('note'):
1480 #pred = self.script.attrPredicate
1481 #kwargs = {'key':'xml-roles','value':'note'}
1482 #outputname = 'note'
1483 #elif taskid.endswith('search'):
1484 #pred = self.script.attrPredicate
1485 #kwargs = {'key':'xml-roles','value':'search'}
1486 #outputname = 'search'
1487 #elif taskid.endswith('secondary'):
1488 #pred = self.script.attrPredicate
1489 #kwargs = {'key':'xml-roles','value':'secondary'}
1490 #outputname = 'secondary'
1491 #elif taskid.endswith('see also'):
1492 #pred = self.script.attrPredicate
1493 #kwargs = {'key':'xml-roles','value':'seealso'}
1494 #outputname = 'see also'
1495 #else:
1496 ## output task identity in this error state
1497 #outputname = taskid
1498
1499 #if pred is None:
1500 #self.sayError(text=_('unrecognized task name %s' %outputname))
1501 #else:
1502 #nodetotal = 0
1503 #if taskid.find('next') > 0:
1504 ## get last acc in active doc frame. It will be our stopping point.
1505 #endacc = self.script.getLastSearchAcc()
1506 ## iterate through tree and apply predicate
1507 #for nextpor in self.iterNextItems(wrap=True):
1508 ## bound to active doc frame
1509 #if nextpor == endacc:
1510 #break
1511 #nodetotal += 1
1512 ## safety net in case of cyclical navigation
1513 #if nodetotal > self.script_state.SearchDepth:
1514 #break
1515 #if pred(nextpor, **kwargs):
1516 #self.stopNow()
1517 ## get the previous item before search query and review to the next
1518 ## item. This will skip any undesirable accs
1519 #self.moveToPOR(por=self.getPrevItem(por=nextpor, wrap=True))
1520 #self.doTask('review next item')
1521 #return False
1522
1523 #elif taskid.find('prev'):
1524 #docframe = self.script.getActiveDocFrame()
1525 ## no need to search if we are at doc frame, we are already at the end.
1526 ## Continue on so error announcement is made.
1527 #if self.task_por != docframe:
1528 #for nextpor in self.iterPrevItems(wrap=True):
1529 #nodetotal += 1
1530 ## safety net in case of cyclical navigation
1531 #if nodetotal > self.script_state.SearchDepth:
1532 #break
1533 #if pred(nextpor, **kwargs):
1534 #self.stopNow()
1535 ## get the next item after search query and review to the prev
1536 ## item. This will skip any undesirable accs
1537 #self.moveToPOR(por=self.getNextItem(por=nextpor, wrap=True))
1538 #self.doTask('review previous item')
1539 #return False
1540 #if nextpor == docframe:
1541 #break
1542 #else:
1543 ## todo: is this correct?
1544 #raise NameError
1545 ## didn't find it
1546 #self.sayError(text=_('could not find %s' %outputname))
1547
1548
1549 #class CyclicGoToElement(Task.InputTask):
1550 #'''
1551 #Cyclic Task used for searching for an element. The search criteria and
1552 #direction of search are derived from the task identity associated to this
1553 #task. The pointer is updated and the L{AEPor} is announced upon finding the
1554 #accessible, otherwise the pointer is NOT moved and an announcement declaring
1555 #that the accessible is not found is made. This task does not stop on
1556 #'undesirable' accessibles as defined by L{ReviewScript} settings.
1557
1558 #Cyclic Behavior
1559 #First cycle - use tight search predicate
1560 #Second cycle - use loose search predicate
1561
1562 #Currently used by navigation by relation.
1563 #'''
1564 #task_por_attrs = None
1565 #task_por_role = None
1566 #cycle_count = 0
1567
1568 #def execute(self, **kwargs):
1569 #self.task_por_role = self.getAccRole()
1570 #self.task_por_attrs = self.getAccAttrs()
1571
1572 #taskid = self.getIdentity()
1573 #if taskid.endswith('similar'):
1574 #if self.cycle_count == 0:
1575 #pred = self._tightSimilarPred
1576 #else:
1577 #pred = self._looseSimilarPred
1578 #elif taskid.endswith('different'):
1579 #if self.cycle_count == 0:
1580 #pred = self._tightDifferentPred
1581 #else:
1582 #pred = self._looseDifferentPred
1583 #else:
1584 #return
1585 #nodetotal = 0
1586 #if taskid.find('next') > 0:
1587 ## get last acc in active doc frame. It will be our stopping point.
1588 #endacc = self.script.getLastSearchAcc()
1589 ## iterate through tree and apply predicate
1590 #for nextpor in self.iterNextItems(wrap=True):
1591 ## search is over. did not find so break to announce error
1592 #if nextpor == endacc:
1593 #break
1594 #nodetotal += 1
1595 ## safety net in case of cyclical navigation. break to announce error
1596 #if nodetotal > self.script_state.SearchDepth:
1597 #break
1598 #if pred(nextpor):
1599 #self.stopNow()
1600 ## get the previous item before search query and review to the next
1601 ## item. This will skip any undesirable accs
1602 #self.moveToPOR(por=self.getPrevItem(por=nextpor, wrap=True))
1603 #self.doTask('review next item')
1604 #self.cycle_count = 0
1605 #return False
1606 #elif taskid.find('prev'):
1607 #docframe = self.script.getActiveDocFrame()
1608 ## no need to search if we are at doc frame, we are already at the end.
1609 ## Continue on so error announcement is made.
1610 #if self.task_por != docframe:
1611 ## iterate through tree and apply predicate
1612 #for nextpor in self.iterPrevItems(wrap=True):
1613 #nodetotal += 1
1614 ## safety net in case of cyclical navigation. break to announce error
1615 #if nodetotal > self.script_state.SearchDepth:
1616 #break
1617 #if pred(nextpor):
1618 #self.stopNow()
1619 ## get the next item after search query and review to the prev
1620 ## item. This will skip any undesirable accs
1621 #self.moveToPOR(por=self.getNextItem(por=nextpor, wrap=True))
1622 #self.doTask('review previous item')
1623 #self.cycle_count = 0
1624 #return False
1625 ## search is over. did not find so break to announce error
1626 #if nextpor == docframe:
1627 #break
1628 ## didn't find it, so announce an error
1629 #if taskid.find('similar') > 0:
1630 #self.sayError(text=_('could not find %s' %self.task_por_role))
1631 #else:
1632 #self.sayError(text=_('different than %s could not be found' %self.task_por_role))
1633 #self.cycle_count += 1
1634
1635 #def _looseSimilarPred(self, por):
1636 #'''
1637 #Predicate used for finding next 'similar' accessible node using role only.
1638 #'''
1639 #return(self.task_por_role == self.getAccRole(por=por))
1640
1641 #def _tightSimilarPred(self, por):
1642 #'''
1643 #Predicate used for finding next 'similar' accessible node using role and
1644 #attributes.
1645 #'''
1646 #return(self.task_por_role == self.getAccRole(por=por) and \
1647 #self.task_por_attrs == self.getAccAttrs(por=por))
1648
1649 #def _looseDifferentPred(self, por):
1650 #'''
1651 #Predicate used for finding next 'different' accessible node using role only
1652 #'''
1653 #return(self.task_por_role != self.getAccRole(por=por))
1654
1655 #def _tightDifferentPred(self, por):
1656 #'''
1657 #Predicate used for finding next 'different' accessible node using role and
1658 #attributes.
1659 #'''
1660 #return(self.task_por_role != self.getAccRole(por=por) and \
1661 #self.task_por_attrs != self.getAccAttrs(por=por))
1662
1663 #class FFWhereAmINow(Task.InputTask):
1664 #'''
1665 #Provides addition output on top of L{BasicSpeechScript} WhereAmI?. Additional
1666 #output includes index and total information and percent read information. This
1667 #task arounds WhereAmINow.
1668 #'''
1669 #def execute(self, por=None, **kwargs):
1670 #por = por or self.task_por
1671 #kwargs = {}
1672
1673 ## set the current por match predicate
1674 ## kwargs is passed to predicate during iteration
1675 #role = self.getAccRole(por=por)
1676 #attrs = self.getAccAttrs(por=por)
1677 ## default the output name to it's role. Change the outputname to something
1678 ## else, if the need arises, within the following if statement.
1679 #outputname = self.getAccRole()
1680 ## tables are special because of layout tables
1681 #if role == 'table':
1682 #pred = self.script.tablePredicate
1683 ## links are special because of no role name
1684 #elif role == '':
1685 #pred = self.script.rolePredicate
1686 #kwargs['role'] = role
1687 #outputname = 'link'
1688 ## some special elements based on attribute tag values
1689 #elif attrs is not None and attrs.has_key('tag'):
1690 #if attrs['tag'] == 'INPUT':
1691 #pred = self.script.formcontrolPredicate
1692 #outputname = 'form control'
1693 #else:
1694 #pred = self.script.rolePredicate
1695 #kwargs['role'] = role
1696 ## default is based on role
1697 #else:
1698 #pred = self.script.rolePredicate
1699 #kwargs['role'] = role
1700 ## stop any output
1701 #self.stopNow()
1702 ## make general 'where am i now' announcement
1703 #self.doTask(self.getAnchorTaskId(), chain=False, **kwargs)
1704 ## make additional announcements if information can be obtained
1705 #time.sleep(1)
1706 #if pred is not None:
1707 ## make our one time call to the document iteration routine (expensive)
1708 #typeindex,typetotal,nodeindex,nodetotal = \
1709 #self._extractIndexInfo(pred, **kwargs)
1710 ## if we got valid information. make additional announcement. Otherwise,
1711 ## announcement from above will suffice
1712 ## output current por index/total information
1713 #if typeindex > 0:
1714 #text = (typeindex, typetotal, outputname)
1715 #template = _('%d of %d %ss in document.')
1716 #self.sayInfo(text=text, template=template)
1717 ## output container index/total information
1718 #if nodeindex > 0:
1719 #text = (int(nodeindex*100/nodetotal))
1720 #template = _('%d percent of document read')
1721 #self.sayInfo(text=text, template=template)
1722
1723 #def _extractIndexInfo(self, pred,
1724 #por=None, startpor=None, endpor=None, **kwargs):
1725 #'''
1726 #Extracts all indexing information for a given L{AEPor} Returned tuple
1727 #includes the following:
1728
1729 #nodeindex: node index of the subject por as with respect to all
1730 #accessibles.
1731 #nodetotal: overall nodes in document
1732 #typeindex: = index of subject por with respect to similar accessibles.
1733 #typetotal: = total number of similar accessibles in document
1734
1735 #@param pred: A predicate used for
1736 #@type pred: L{AEPor}
1737 #@return: Is por within doc frame?
1738 #@rtype: tuple
1739 #'''
1740 ## set current por
1741 #por = por or self.task_por
1742 ## set start of iteration
1743 #startpor = startpor or self.script.getActiveDocFrame()
1744 ## get last acc in active doc frame. It will be our stopping point.
1745 #endpor = self.script.getLastSearchAcc()
1746 ## track overall nodes and index within for the current por, used for
1747 ## percent through doc
1748 #nodeindex = -1
1749 #nodetotal = 0
1750 ## track the number of similar accessibles, either within the document if
1751 ## there is no container predicate, otherwise within the container.
1752 #typeindex = -1
1753 #typetotal = 0
1754 ## begin traversal of document
1755 #for i in self.iterNextItems(por=startpor, wrap=True):
1756 ## traversal is over when we see the endpor
1757 #if i == endpor:
1758 #break
1759 #nodetotal += 1
1760 ## safety net in case of cyclical navigation
1761 #if nodetotal > self.script_state.SearchDepth:
1762 #return (-1, 0, -1, 0)
1763 ## apply current por precicate and increment related indices/totals
1764 #if pred is not None:
1765 #if pred(i, **kwargs):
1766 #typetotal += 1
1767 #if i == por:
1768 #nodeindex = nodetotal
1769 #typeindex = typetotal
1770 #return (typeindex, typetotal, nodeindex, nodetotal)
1771
1772 #class GoToContainer(Task.InputTask):
1773 #'''
1774 #Navigate to the container root containing the pointer. Container are defined
1775 #as accessibles with roles: image, form, list, calendar, menu, menu bar, entry,
1776 #page tab, tool bar, application, tree, or tree table. Container are also
1777 #document frames that are not the active doc frame and tables that are not
1778 #layout tables.
1779 #'''
1780 #def execute(self, **kwargs):
1781 ## stop any speech output
1782 #self.stopNow()
1783 ## test the current POR, it might be a container eg. entry
1784 #role = self.getAccRole()
1785 #if role in self.script.CONTAINERS_BY_ROLE:
1786 ## task_por is a container and we are on an item. set to beginning of acc
1787 #self.task_por.item_offset=None
1788 #self.task_por.char_offset=0
1789 #self.doTask('pointer to por')
1790 #return
1791 ## go up tree until you find a container or break to announce error when doc
1792 ## frame is seen.
1793 #activedoc = self.script.getActiveDocFrame()
1794 #for p in self.iterAncestorAccs(only_visible=False,allow_trivial=False):
1795 ## our search is done. breakout to announce container not found
1796 #if p == activedoc:
1797 #break
1798 #role = self.getAccRole(por=p)
1799 #if role in self.script.CONTAINERS_BY_ROLE or \
1800 #role == 'table' and not self.script.isLayoutTable(p, role) or \
1801 #role == DOCUMENT_ROLE and p != activedoc:
1802 #self.doTask('pointer to por', por=p)
1803 ## set reading mode. no need to set focus on the container
1804 #self.script.setModeByPOR(p)
1805 #return
1806 #self.sayError(text=_('top container'))
1807
1808 #class SkipContainer(Task.InputTask):
1809 #'''
1810 #Skips containers if pointer is currently on a container, otherwise an error
1811 #message is announced. See L{GoToContainer} for list of defined containers.
1812 #'''
1813 #def execute(self, **kwargs):
1814 #self.stopNow()
1815 #lastunder = self.getLastAccUnder()
1816 #if lastunder == self.task_por:
1817 #self.sayError(text=_('no container to skip'))
1818 #else:
1819 #self.moveToPOR(lastunder)
1820 ## review task will take care of mode and focus settings
1821 #self.doTask('review next item')
1822 #self.script.setModeByPOR(self.task_por)
1823
1824 #class SavedPORFlusher(Task.TimerTask):
1825 #'''
1826 #Removes L{AEPor}s saved during restoration routine that are no longer valid.
1827 #'''
1828 #def execute(self, **kwargs):
1829 #flushed = []
1830 #for key in self.script.doc_pors.iterkeys():
1831 #attrs = self.getAccAttrs(por=key)
1832 ## invalid if the URL is not given
1833 #if attrs is not None and attrs['DocURL'] == '':
1834 #flushed.append(key)
1835 #for i in flushed:
1836 #del self.script.doc_pors[i]
1837
1838
1839 #class ReadLinkPreview(Task.InputTask):
1840 #'''
1841 #Reads information about the current link. Information includes protocol,
1842 #domain differences, and download size if available.
1843 #'''
1844 #def execute(self, **kwargs):
1845 #role = self.getAccRole()
1846 #if role != '':
1847 #self.sayError(text=_('pointer not on a link'))
1848 #return
1849 ## get our two URIs of importance (current page and the link)
1850 #link_uri = self.getAccURI(0)
1851 #doc_uri = self.script.getDocURI()
1852 ## sanity check
1853 #if link_uri is None or doc_uri is None:
1854 #self.sayError(text=_('error in determining URI'))
1855 #return
1856 ## returned tuple contains six components:
1857 ## scheme://netloc/path;parameters?query#fragment.
1858 #link_uri_info = urlparse.urlparse(link_uri)
1859 #doc_uri_info = urlparse.urlparse(doc_uri)
1860 ## setup our three possible output defaults
1861 #linkoutput = '%s link.' %link_uri_info[0]
1862 #domainoutput = ''
1863 #sizeoutput = ''
1864
1865 ## determine location differences
1866 #if link_uri_info[1] == doc_uri_info[1]:
1867 #if link_uri_info[2] == doc_uri_info[2]:
1868 #domainoutput = 'same page'
1869 #else:
1870 #domainoutput = 'same site'
1871 #else:
1872 ## check for different machine name on same site
1873 #linkdomain = link_uri_info[1].split('.')
1874 #docdomain = doc_uri_info[1].split('.')
1875 #if len(linkdomain) > 1 and docdomain > 1 and \
1876 #linkdomain[-1] == docdomain[-1] and linkdomain[-2] == docdomain[-2]:
1877 #domainoutput = 'same site'
1878 #else:
1879 #domainoutput = 'different site'
1880
1881 ## get size and other protocol specific information
1882 #if link_uri_info[0] == 'ftp' or link_uri_info[0] == 'ftps' or \
1883 #link_uri_info[0] == 'file':
1884 ## change out link output message to include filename
1885 #filename = link_uri_info[2].split('/')
1886 #linkoutput = '%s link to %s' %(link_uri_info[0], filename[-1])
1887 #sizestr = self._extractSize(link_uri)
1888 #sizeoutput = self._formatSizeOutput(sizestr)
1889 ## add addition protocol specific changes
1890 #elif link_uri_info[0] == 'javascript':
1891 #pass
1892
1893 ## format and send output message
1894 #text = (linkoutput, domainoutput, sizeoutput)
1895 #template = _('%s. %s. %s')
1896 #self.stopNow()
1897 #self.sayInfo(text=text, template=template)
1898
1899 #def _extractSize(self, uri):
1900 #'''
1901 #Get the http header for a given uri and try to extract the size (Content-length).
1902
1903 #@param uri: A Uniform Resource Identifier
1904 #@type uri: string
1905 #@return: size of file pointed to by uri as indicated by http header if
1906 #available
1907 #@rtype: string
1908 #'''
1909 #try:
1910 #x=urllib2.urlopen(uri)
1911 #try:
1912 #return x.info()['Content-length']
1913 #except KeyError:
1914 #return None
1915 #except (ValueError, urllib2.URLError, OSError):
1916 #return None
1917
1918 #def _formatSizeOutput(self, sizestr):
1919 #'''
1920 #Format the size output announcement. Changes wording based on size.
1921
1922 #@param sizestr: size in bytes as a string
1923 #@type sizestr: string
1924 #@return: The size announcement
1925 #@rtype: string
1926 #'''
1927 ## sanity check
1928 #if sizestr is None or sizestr == '':
1929 #return ''
1930 #size = int(sizestr)
1931 #if size < 10000:
1932 #return '%s bytes' %sizestr
1933 #elif size < 1000000:
1934 #out = '%.2f kilobytes' %(float(size) * .001)
1935 #return out
1936 #elif size >= 1000000:
1937 #return '%.2f megabytes' %(float(size) * .000001)
1938
1939 #class FFReadNewContainer(Task.Task):
1940 #'''
1941 #Containers should not be read in webpages. This task 'befores'
1942 #ReadNewContainer and stops task propagation to prevent it from executing.
1943 #'''
1944 #def execute(self, por=None, **kwargs):
1945 #return False
1946
| Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0beta1 on Mon Jun 30 13:06:10 2008 | http://epydoc.sourceforge.net |