Module FirefoxScript
[hide private]
[frames] | no frames]

Source Code for Module FirefoxScript

   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   
44 -class FirefoxScriptState(AEScript.ScriptState):
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 '''
58 - def init(self):
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
73 - def getGroups(self):
74 ''' 75 Gets configurable settings for this L{AEScript <AEScript.AEScript>}. 76 77 @return: Group of all configurable settings 78 @rtype: L{AEState.Setting.Group} 79 ''' 80 root = self.newGroup() 81 root.append('BoundReview') 82 root.append('AutoMode') 83 root.append('SearchDepth') 84 return root
85
86 -class FirefoxScript(AEScript.EventScript):
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
141 - def init(self):
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
302 - def getName(self):
303 return _('Firefox')
304
305 - def getDescription(self):
306 return _('Defines keyboard commands and settings to customize Firefox ' 307 'access.')
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