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

Source Code for Module GaimScript

  1  ''' 
  2  Defines a user interface for gaim. 
  3   
  4  Keys registered 
  5   
  6  CapsLock-W: Reports status of all open conversations 
  7  CapsLock-S: Cycle focus between message history and compose area 
  8   
  9  Event announcements 
 10   
 11  (X) means optional announcement X based on type of widget 
 12  [X] means X always announced 
 13  <X> indicates continue announcements in X 
 14   
 15  on activate: ["chat with" username] 
 16  on focus: ["compose" or "history"] <active descendant change> 
 17  on message received: [text of message] 
 18     
 19  @var CONTAINER_PATH: path from frame to container with accessible elements 
 20  @type CONTAINER_PATH: integer 
 21  @var NUM_CHILDREN_IN_CHAT_WINDOW: to identify a chat window: assume that only 
 22    this acc will have 2 kids, and further assume that accessibles with similar 
 23    hierarchical placement will not. 
 24  @type NUM_CHILDREN_IN_CHAT_WINDOW: integer 
 25  @var MENU_BAR_PATH: path: from container to menu bar 
 26  @type MENU_BAR_PATH: integer 
 27  @var TAB_PATH: path from container to page tab list (contains conversations) 
 28  @type TAB_PATH: integer 
 29  @var HISTORY_PATH: path from a conversation tab to its history text panel 
 30  @type HISTORY_PATH: integer 
 31  @var COMPOSE_PATH: path from a conversation tab to its compose text panel 
 32  @type COMPOSE_PATH: integer 
 33  @var UNREAD_STATUS: Constant representing a conversation has an unread  
 34    message 
 35  @type UNREAD_STATUS: integer 
 36  @var TYPING_STATUS: Constant representing a chat partner is currently typing 
 37    in a conversation 
 38  @type TYPING_STATUS: integer 
 39  @var PAUSED_STATUS: Constant representing a chat partner is stoped typing 
 40    in a conversation 
 41  @type PAUSED_STATUS: integer 
 42  @var IDLE_STATUS: Constant representing a chat partner is idle in a  
 43    conversation 
 44  @type IDLE_STATUS: integer 
 45  @var OFFLINE_STATUS: Constant representing a chat partner is offline in a  
 46    conversation 
 47  @type OFFLINE_STATUS: integer 
 48  @var RED: Gtk color description of color red, as string 
 49  @type RED: string 
 50  @var GREEN: Gtk color description of color green, as string 
 51  @type GREEN: string 
 52  @var YELLOW: Gtk color description of color yellow, as string 
 53  @type YELLOW: string 
 54  @var LOGOUT_GREY: Gtk color description of grey, as string, used in logoff 
 55  @type LOGOUT_GREY: string 
 56  @var STATUS_MSG: List of strings describing the unread, typing, etc. status 
 57    of conversations sorted by their likely importance to the user 
 58  @type STATUS_MSG: list of string 
 59   
 60  @author: Brett Clippingdale 
 61  @author: Peter Parente 
 62  @organization: IBM Corporation 
 63  @copyright: Copyright (c) 2005, 2007 IBM Corporation 
 64  @license: The BSD License 
 65   
 66  All rights reserved. This program and the accompanying materials are made  
 67  available under the terms of the BSD license which accompanies 
 68  this distribution, and is available at 
 69  U{http://www.opensource.org/licenses/bsd-license.php} 
 70  ''' 
 71  from AccessEngine import AEConstants 
 72  from AccessEngine import AEState, AEScript, AccessEngineAPI 
 73  from AccessEngine.AEPor import AEPor 
 74  from Tools.i18n import _ 
 75   
 76  # change tier='gaim' to tier='pidgin' if you use pidgin instead of gaim 
 77  __uie__ = dict(kind='script', tier='gaim') 
 78   
 79  # actual paths, derived using at-poke, assumed to be static.  YMMV. 
 80  # path: from frame to container with accessible elements    
 81  CONTAINER_PATH = 0 
 82  # to identify a chat window: assume that only this acc will have 2 kids, and 
 83  # further assume that accessibles with similar hierarchical placement will 
 84  # not.  Again, YMMV, so analyze carefully with AT-Poke and then verify. 
 85  NUM_CHILDREN_IN_CHAT_WINDOW = 2 
 86  # path: from container to page tab list (contains all conversations) 
 87  TAB_PATH = 1   
 88   
 89  # actual paths in Gaim 1.5, derived using at-poke, assumed to be static 
 90  # if Gaim 2, these will get different values in setGaimEnviron() 
 91  HISTORY_PATH = (0,0,0,0,0) # path: tab (a conversation) to history text panel 
 92  COMPOSE_PATH = (0,0,1,1,0,0,0) # path: tab to chat compose text panel 
 93   
 94  # gaim colors, (eg. convo tab text color depends on typing/login status) 
 95  RED = "57311,16962,7710" # unread msg 
 96  GREEN = "18247,41120,17990" # active typing 
 97  YELLOW = "53713,38036,3084" # paused typing 
 98  GREY = "34438,33410,29298" # off-line 
 99  LOGOUT_GREY = "32639, 32639, 32639" # used in buddy list on logoff 
100  # constants for status of conversations 
101  UNREAD_STATUS = 0 
102  TYPING_STATUS = 1 
103  PAUSED_STATUS = 2 
104  IDLE_STATUS = 3 
105  OFFLINE_STATUS = 4 
106  LOGIN_STATUS = 5 
107  LOGOUT_STATUS = 6 
108  STATUS_MSG = [_('unseen'), _('typing'), _('paused'), _('idle'), _('offline'), 
109                _('logged in'), _('logged out')]  
110   
111 -class GaimScriptState(AEScript.ScriptState):
112 ''' 113 Settings for Gaim. 114 115 ReadBackground (bool): Read incoming messages when gaim is in the background? 116 '''
117 - def init(self):
118 self.newBool('ReadBackground', False, _('Read background messages?'), 119 _('When checked, incoming messages will be read even when ' 120 'Gaim is in the background.')) 121 self.newBool('BrailleBackground', False, _('Braille background messages?'), 122 _('When checked, incoming messages will be output to Braille ' 123 'device even when Gaim is in the background.'))
124
125 - def getGroups(self):
126 g = self.newGroup() 127 g.append('ReadBackground') 128 g.append('BrailleBackground') 129 return g
130
131 -class GaimScript(AEScript.AEScript):
132 ''' 133 Provides hotkeys for switching between the message history and message 134 compose areas. Announces incoming messages and allows for review by entire 135 message. 136 137 Has initial support for announcing when buddies sign in and out and when the 138 status of a conversation changes. Written to work with both gaim 1.5 and 2.0. 139 140 @ivar chat_compose_por: Reference to chat msg compose panel 141 @type chat_compose_por: L{AEPor} 142 @ivar chat_history_por: Reference to chat history panel 143 @type chat_history_por: L{AEPor} 144 @ivar last_convo: Reference to the last selected conversation tab 145 @type last_convo: L{AEPor} 146 @ivar initialized: have gaim environment variables been initialized? 147 @type initialized: boolean 148 @ivar is_gaim2: is user client Gaim2 ? 149 @type is_gaim2: boolean 150 @ivar is_history_focused: does chat history panel currently have focus? 151 @type is_history_focused: boolean 152 @ivar last_history_caret: track caret in history panel, read when on new line 153 @type last_history_caret: L{AEPor} 154 ''' 155 STATE = GaimScriptState 156
157 - def init(self):
158 ''' 159 Registers keyboard bindings that give status of conversation tabs (unread 160 message, active typing, paused typing) and drive focus back and forth 161 between chat composition text area and history text area. 162 ''' 163 164 # set an audio device as the default output 165 AccessEngineAPI.setScriptIdealOutput('audio')
166 167 ## register event handlers 168 ## events here are app-level, other Scripts will handle gnome-level events, 169 ## so only register events of interest here. 170 #AccessEngineAPI.registerTask(ActivateGaimWindow('gaim read window')) 171 #AccessEngineAPI.registerTask(HandleFocusChange('gaim read focus')) 172 #AccessEngineAPI.registerTask(HandleSelectorChange('gaim read selector')) 173 #AccessEngineAPI.registerTask(HandleCaretChange('game read caret')) 174 #AccessEngineAPI.registerTask(ReadIncoming('gaim read incoming', all=True)) 175 ## not working for background events ??? 176 ##self.registerEventTask(HandlePropertyChange(focus=True, tier=True, 177 ## background=True)) 178 ## @note: not handling TableChange until certain Gaim bugs fixed 179 ## if re-enabled, may want to uncomment debug code: last_por_inserted (global 180 ## variable) and code in handleCaretChange 181 ##self.registerEventTask(BuddySignOnOff(focus=True, tier=True, 182 ##background=True)) 183 184 ## register named tasks. Specify the task class name (see below) and a 185 ## description. These descriptions are dictionary keys and therefore 186 ## must be unique. Here, Gaim is a prefix to help ensure uniqueness. 187 #AccessEngineAPI.registerTask(ToggleChatPanel('gaim chat panel toggle')) 188 #AccessEngineAPI.registerTask(ConversationStatus('gaim conversation status')) 189 190 ## get the Keyboard device and register modifiers. 191 #kbd = AccessEngineAPI.getInputDevice(None, 'keyboard') 192 #AccessEngineAPI.addInputModifiers(self, kbd, kbd.AEK_CAPS_LOCK) 193 194 ## register the keys and their associated commands, binding them using the 195 ## unique dictionary key we registered above. 196 ## Pass 3 element tuple. Need to capture keys as pressed though we only 197 ## handle them if all both modifiers pressed before the non-modifier. 198 #AccessEngineAPI.registerCommand(kbd, 'gaim chat panel toggle', False, 199 #[kbd.AEK_CAPS_LOCK, kbd.AEK_S]) 200 #AccessEngineAPI.registerCommand(kbd, 'gaim conversation status', False, 201 #[kbd.AEK_CAPS_LOCK, kbd.AEK_W]) 202 203 ## POR reference to chat composition text area 204 #self.chat_compose_por = AEPor() 205 ## POR reference to chat history text area 206 #self.chat_history_por = AEPor() 207 #self.last_convo = AEPor() 208 209 ## have gaim environment variables been initialized? This must happen first 210 ## time that gaim chat window is activated 211 #self.initialized = False 212 ## is user client Gaim 2.0 instead of 1.5? 213 #self.is_gaim2 = False 214 215 ## does chat history panel currently have focus 216 #self.is_history_focused = False 217 #self.last_history_caret = AEPor() 218 219 ## is there selection in the composition area? used to avoid announcing 220 ## deleted text when sending 221 #self.selection = False 222 223 ## may be used in case where, on sign-off, multiple inserts fire 224 ##debug, see handleRowInserted, handleCaretChange 225 ##last_row_inserted_por = None 226 227 #def getActivePageTabListPOR(self): 228 #''' 229 #Gets a Point of Regard to the page tab list in an active chat window. 230 231 #@return: Point of Regard to the page tab list in an active chat window, 232 #or None otherwise 233 #@rtype: L{AEPor} 234 #''' 235 #frame_por = AccessEngineAPI.getRootAcc() 236 #container_por = AccessEngineAPI.getAccFromPath(frame_por, CONTAINER_PATH) 237 ## is chat window active? 238 #if (AccessEngineAPI.hasAccState('active', frame_por) and 239 #AccessEngineAPI.getAccCount(container_por) == NUM_CHILDREN_IN_CHAT_WINDOW): 240 ## get 'page tab list' 241 #tab_list_por = AccessEngineAPI.getAccFromPath(container_por, TAB_PATH) 242 #if AccessEngineAPI.hasAccRole("page tab list", tab_list_por): 243 #return tab_list_por 244 ## in all other cases, return None 245 #return None 246 247 #def getTypingStatus(self, por): 248 #''' 249 #Gets current typing status on a given conversation L{AEPor}. 250 251 #@return: One of L{UNREAD_STATUS}, L{TYPING_STATUS}, L{PAUSED_STATUS}, 252 #L{IDLE_STATUS} that can be mapped to a message in L{STATUS_MSG} 253 #@rtype: integer 254 #''' 255 #value = AccessEngineAPI.getAccTextAttr("fg-color", por) 256 ## red: message typed, unread 257 #if value == RED: 258 #return UNREAD_STATUS 259 ## green: typing 260 #elif value == GREEN: 261 #return TYPING_STATUS 262 ## yellow: paused 263 #elif value == YELLOW: 264 #return PAUSED_STATUS 265 ## grey: offline 266 #elif value == GREY: 267 #return OFFLINE_STATUS 268 ## black: (no typing), and no fg-color value 269 #else: 270 #return IDLE_STATUS 271 272 #def setGaimVersion(self): 273 #''' 274 #Applies a heuristic to determine which Gaim version is running locally. 275 #This is important because the the representation of the UI varies by local 276 #client, and in the case of a local Gaim 2 it also varies by remote client. 277 #''' 278 #tab_list_por = self.getActivePageTabListPOR() 279 ## get selected conversation tab 280 #selected_tab_por = AccessEngineAPI.getFirstSelected(tab_list_por) 281 #self.chat_history_por = \ 282 #AccessEngineAPI.getAccFromPath(selected_tab_por, *HISTORY_PATH) 283 ## if this is a "filler" rather than a text area, must be Gaim2 284 #if AccessEngineAPI.getAccRoleName(self.chat_history_por) == "filler": 285 #self.is_gaim2 = True 286 #print "chat client is Gaim beta 2 or higher" 287 #else: 288 #print "chat client is Gaim 1.5 or lower" 289
290 - def getName(self):
291 ''' 292 @return: Human readable name of this L{AEScript <AEScript.AEScript>}. 293 @rtype: string 294 ''' 295 return _('Gaim')
296 297 ## 298 ## Tasks executed by keys 299 ## 300 301 #class ToggleChatPanel(Task.InputTask): 302 #''' 303 #Toggles focus between chat composition and chat history panels. 304 #''' 305 ## each task class must implement an execute method which is called when 306 ## the associated key bindings (registered in init method, above) are pressed 307 #def execute(self, **kwargs): 308 ## determine which chat panel currently has focus. Specify which 309 ## ATSPI-defined property of interest (here, 'focused') and the POR to check 310 ## for that property 311 #tab_list_por = self.script.getActivePageTabListPOR() 312 #if tab_list_por is not None: 313 #if not self.script.is_history_focused: 314 ##change focus to chat history panel 315 #self.setAccFocus(self.script.chat_history_por) 316 #else: 317 ##change focus to chat compose panel 318 #self.setAccFocus(self.script.chat_compose_por) 319 #return True # allow triggering keystrokes to propagate (default) 320 321 #class ConversationStatus(Task.InputTask): 322 #''' 323 #Announces the status of the current conversations. Status for conversations 324 #is grouped by status type except for the foreground conversation which is 325 #always reported first. 326 #''' 327 #def execute(self, **kwargs): 328 #brailleout=[] 329 #tab_list_por = self.script.getActivePageTabListPOR() 330 ## is chat window active? otherwise, don't switch 331 #if tab_list_por is None: 332 #return True 333 334 ## stop prior speech 335 #self.stopNow() 336 337 ## get selected conversation tab 338 #selected_tab_por = self.getFirstSelected(tab_list_por) 339 340 #por = self.getFirstPeerAcc(selected_tab_por) 341 #l = [] 342 #while por is not None: 343 ## get the tab name and status value 344 #name = self.getAccName(por) 345 ## if acc not an artifact, process 346 #if name != '': 347 #value = self.script.getTypingStatus(por) 348 #print selected_tab_por 349 #if selected_tab_por == por: 350 #self.sayState(text=(name, STATUS_MSG[value]), template='%s %s,') 351 #brailleout.append('%s: %s, ' % (name, STATUS_MSG[value])) 352 #else: 353 #l.append((value, name)) 354 #por = self.getNextPeerAcc(por) 355 356 ## sort the list of status values and names by priority, highest first) 357 #l.sort() 358 359 #last = -1 360 #for value, name in l: 361 #if last != value: 362 #last = value 363 #self.sayState(text=STATUS_MSG[value], template='%s,') 364 #brailleout.append('%s: ' % (STATUS_MSG[value])) 365 #self.sayState(text=name, template='%s,') 366 #brailleout.append('%s, ' % (name)) 367 ## output to Braille device 368 #self.doTask('braille text', text=''.join(brailleout)) 369 370 ## 371 ## Tasks executed by events 372 ## 373 374 #class ActivateGaimWindow(Task.ViewTask): 375 #''' 376 #Task that handles a L{AEEvent.ViewChange}. 377 #''' 378 #def executeGained(self, por, title, **kwargs): 379 #''' 380 #Prevents the window title from being announced if it is the chat window, 381 #since better information is given for the chat window on the subsequent 382 #focus change event. Accomplished by stopping propagation of the event. 383 384 #@param por: Point of regard to the root of the new view 385 #@type por: L{AEPor} 386 #@param title: Title of the newly activated window 387 #@type title: string 388 #''' 389 #self.script.last_convo = AEPor() 390 #tab_list_por = self.script.getActivePageTabListPOR() 391 #print 'GAIM:', tab_list_por 392 ## test to see if not a chat window 393 #if tab_list_por is None: 394 #return True # allow other Scripts to handle the view change 395 ## must be a chat window 396 #else: 397 #if not self.script.initialized: 398 #self.script.setGaimVersion() 399 #self.script.initialized = True 400 ## don't allow the view change event to propagate 401 #return False 402 403 #class HandleFocusChange(Task.FocusTask): 404 #''' 405 #Task that handles a L{AEEvent.FocusChange}. 406 #''' 407 #GAIM2_HISTORY_PATH = (0,0,0,0,0,0,0) #history text panel 408 #GAIM2_COMPOSE_PATH = (0,0,1,0,0,0,0,2,0) # compose text panel - gaim2 remote 409 #GAIM2_ALT_COMPOSE_PATH = (0,0,1,0,1,0,0,2,0) # compose text panel - gaim1.5 410 411 #def executeGained(self, por, **kwargs): 412 ## get 'page tab list' 413 #tab_list_por = self.script.getActivePageTabListPOR() 414 #if tab_list_por is None: 415 ## let the event propagate 416 #return True 417 418 ## possibly stop prior speech 419 #self.mayStop() 420 ## and prevent this speech from being interrupted 421 #self.inhibitMayStop() 422 423 ## get selected conversation tab 424 #selected_tab_por = self.getFirstSelected(tab_list_por) 425 426 ## check if we should announce the state of the current convo or not 427 #if selected_tab_por != self.script.last_convo: 428 #name = self.getAccName(selected_tab_por) 429 #self.saySection(text=name, template=_('chat with %s')) 430 #value = self.script.getTypingStatus(selected_tab_por) 431 #self.sayState(text=STATUS_MSG[value]) 432 #self.script.last_convo = selected_tab_por 433 434 ## locate message history/compose text box PORs 435 ## gaim 2 local client 436 #if self.script.is_gaim2: 437 #self.script.chat_history_por = \ 438 #self.getAccFromPath(selected_tab_por, *self.GAIM2_HISTORY_PATH) 439 #self.script.chat_compose_por = \ 440 #self.getAccFromPath(selected_tab_por, *self.GAIM2_COMPOSE_PATH) 441 #if (self.script.chat_compose_por is None or 442 #not AccessEngineAPI.hasAccRole('text', self.script.chat_compose_por)): 443 #self.script.chat_compose_por = \ 444 #self.getAccFromPath(selected_tab_por, *self.GAIM2_ALT_COMPOSE_PATH) 445 #print 'alt', self.script.chat_compose_por 446 ## gaim 1.5 local client 447 #else: 448 #self.script.chat_history_por = \ 449 #self.getAccFromPath(selected_tab_por, *HISTORY_PATH) 450 #self.script.chat_compose_por = \ 451 #self.getAccFromPath(selected_tab_por, *COMPOSE_PATH) 452 453 ## tell user which text area is focused 454 #self.script.is_history_focused = \ 455 #self.hasAccState('focused', self.script.chat_history_por) 456 #if self.script.is_history_focused: 457 ##if self.hasAccState('focused', self.script.chat_history_por): 458 #self.saySection(text=_('history,')) # this odd syntax supports i18n 459 #self.script.last_history_caret = AEPor() # reset 460 #return False 461 #elif self.hasAccState('focused', self.script.chat_compose_por): 462 ##elif self.hasAccState('focused', self.script.chat_compose_por): 463 #self.saySection(text=_('compose,')) # this odd syntax supports i18n 464 #return False 465 ##else: 466 ## return True # propagate handling of the event (default) 467 468 #class HandleSelectorChange(Task.SelectorTask): 469 #''' 470 #Task that tracks text selection changes. Used to updated the selection flag 471 #so the L{HandleCaretChange.executeDeleted} method can decide whether or not 472 #to allow reporting of deleted text. 473 #''' 474 #def executeText(self, por, text, **kwargs): 475 #''' 476 #Sets the selection flag to True if some text is selected else sets it to 477 #False. 478 479 #@param por: Point of regard to the text caret 480 #@type por: L{AEPor} 481 #@param text: Currently selected text 482 #@type text: string 483 #''' 484 #if text: 485 #self.script.selection = True 486 #else: 487 #self.script.selection = False 488 #return True 489 490 #class ReadIncoming(Task.CaretTask): 491 #''' 492 #Reads incoming messages. 493 #''' 494 #def executeInserted(self, por, text, text_offset, layer, **kwargs): 495 #''' 496 #Speaks text that starts with a new line character. This indicates a new 497 #line of text has been inserted into the message history. 498 499 #@param por: Point of regard where the caret event occurred 500 #@type por: L{AEPor} 501 #@param text: The text passed during the move 502 #@type text: string 503 #@param text_offset: The offset of the new caret position 504 #@type text_offset: integer 505 #@param layer: Layer of the event, focus, tier, or background 506 #@type layer: integer 507 #''' 508 ## convoluted logic is necessary in order to minimize expensive 509 ## compareAncestorRoles calls. 510 #if (not self.script_state.ReadBackground and 511 #not self.script_state.BrailleBackground and 512 #layer == AEConstants.LAYER_BACKGROUND): 513 ## don't output background messages if the user has it disabled. 514 #return 515 516 #rv = self.compareAncestorRoles(por, 'scroll pane', 'filler', 'panel', 517 #'filler', 'split pane', 'filler', 518 #'page tab') 519 520 #if rv and (layer != AEConstants.LAYER_BACKGROUND or 521 #(layer == AEConstants.LAYER_BACKGROUND and 522 #self.script_state.ReadBackground)): 523 ## queue up text to speak 524 #self.sayItem(text=text) 525 526 #if rv and (layer != AEConstants.LAYER_BACKGROUND or 527 #(layer == AEConstants.LAYER_BACKGROUND and 528 #self.script_state.BrailleBackground)): 529 ## output to braille device 530 #self.doTask('braille text', text=text) 531 532 533 #class HandleCaretChange(Task.CaretTask): 534 #''' 535 #Task that handles a L{AEEvent.CaretChange}. Used to read an entire message in 536 #chat history, rather than simply the current line. The L{executeMoved} method 537 #finds the beginning and end of the current message, truncates the timestamp 538 #and user name when redundant, then reads the message. 539 #''' 540 #def executeMoved(self, por, text, text_offset, **kwargs): 541 #''' 542 #Announces an entire message from a remote user by looking for hard line 543 #breaks (\\n) when the caret moves to a position just after or just before 544 #the break character. If the caret is anywhere else, lets other L{AEScript <AEScript.AEScript>}s do 545 #their default caret processing. 546 547 #@param por: Point of regard where the caret event occurred 548 #@type por: L{AEPor} 549 #@param text: The text passed during the move 550 #@type text: string 551 #@param text_offset: The offset of the new caret position 552 #@type text_offset: integer 553 #''' 554 ## debugging code for handleTableChange, since we may or may not get 555 ## multiple events when a remote buddy logs off, announce when caret changes 556 ## just as a test, not for final code. 557 ##if self.script.last_row_inserted_por is not None: 558 ## print "last_row_inserted_por" , self.script.last_row_inserted_por 559 ## self.script.last_row_inserted_por = None 560 ## could eliminate by setting is_history_focused = False when appropriate 561 #tab_list_por = self.script.getActivePageTabListPOR() 562 ## if chat window and chat history have focus 563 #if tab_list_por is not None and self.script.is_history_focused: 564 ## say line when item_offset changes 565 #if (not por.isSameItem(self.script.last_history_caret)): 566 ## get the start of the line (character after a \n) 567 #start = self.getStartOfHardLine(por) 568 ## get the end of the line (next encountered \n) 569 #end = self.getEndOfHardLine(por) 570 571 ## store the current POR 572 #self.script.last_history_caret = por 573 ## if we're not at the start or end of a true message line, let 574 ## other Scripts handle the caret event unless at start/end of msg 575 #if por != end and por != start: 576 #return True 577 578 ## get all the text between the start and end PORs 579 #msg = self.getAccTextBetween(start, end) 580 581 #self.mayStop() 582 #self.sayItem(text=msg) 583 ##self.inhibitMayStop() 584 #return False 585 586 ## respond to caret movement on same line 587 ## just let other Scripts handle this case 588 #else: 589 #self.script.last_history_caret = por 590 #return True 591 592 ## not in chat history 593 #else: 594 #return True 595 596 #def executeInserted(self, **kwargs): 597 #'''Resets the selection flag.''' 598 #self.script.selection = False 599 #return True 600 601 #def executeDeleted(self, text, **kwargs): 602 #''' 603 #Consumes the deletion event if the selection flag is False and more than 604 #one character of text was deleted (i.e. a message was sent). Avoids 605 #announcing the sent text as "Backspace <text>" as well as the text that 606 #appears in the message history. If the selection flag is True, resets it. 607 608 #@param text: The text deleted 609 #@type text: string 610 #''' 611 #if not self.script.selection and len(text) > 1: 612 #return False 613 #self.script.selection = False 614 #return True 615 616 #class HandlePropertyChange(Task.PropertyTask): 617 #''' 618 #Task that handles a L{AEEvent.PropertyChange}. 619 #''' 620 #def execute(self, por, name, value, **kwargs): 621 #''' 622 #If in a chat window, check to see if the text color properties of a 623 #conversation tab have changed. Announce change if to anything other than 624 #'idle' (ie. active typing, paused typing, away, away idle, logged out). 625 #''' 626 #is_chat_window = self.script.getActivePageTabListPOR() 627 ## test to see if a chat window and if a conversation page tab 628 #if is_chat_window is not None and self.hasAccRoleName('page tab', por): 629 #user = self.getAccName(por) 630 #status = self.script.getTypingStatus(por) 631 ##print "%s: %s: %s" %(name, STATUS_MSG[status], por) 632 ## don't report idle status, we already report paused and new message 633 #if status != IDLE_STATUS: 634 ##print "GaimScript::Property change:", por, name, value 635 ##print "%s: %s: %s" %(user, STATUS_MSG[status], por) 636 #self.sayState(text=(user, STATUS_MSG[status]), template='%s %s,') 637 #return True 638 639 640 #class BuddySignOnOff(Task.TableTask): 641 #''' 642 #Task that handles a L{AEEvent.TableChange}. 643 644 #These events will be used to know when a remote buddy logs in/out, however 645 #current information makes the "in/out" determination unreliable. Bugs are 646 #being filed against Gaim. Therefore, this script does not currently register 647 #to handle TableChange events. 648 #''' 649 650 #def executeTableRowInserted(self, por, first_child_por, last_child_por, 651 #layer, **kwargs): 652 #''' 653 #Executes this task in response to a row-inserted table change event. 654 #Called by L{Task.TableTask.execute}. 655 656 #@param por: The L{AEPor} for the related accessible 657 #@type por: L{AEPor} 658 #@param first_child_por: The L{AEPor} of first inserted row 659 #@type first_child_por: L{AEPor} 660 #@param last_child_por: The L{AEPor} of last inserted row 661 #@type last_child_por: L{AEPor} 662 #@param layer: Layer on which the event occurred 663 #@type layer: integer 664 #''' 665 ##print "GaimScript::executeTableRowInserted()", por, first_child_por, \ 666 ## last_child_por, layer 667 #frame_name = self.getWindowTitle(por) 668 ## only handle table change events from buddy list (don't announce when 669 ## conversation tab order changes, assume only a sighted user would do that). 670 #if frame_name == "Buddy List": 671 ##print "1" , self.getItemText(first_child_por) 672 ##print "2" , self.getItemText(last_child_por) 673 ## may be used in case where, on sign-off, multiple inserts fire 674 ## self.script.last_row_inserted_por = first_child_por 675 ## name = self.getItemText(self.script.last_row_inserted_por) 676 ##print "%s logged in" %name 677 #status = STATUS_MSG[LOGIN_STATUS] 678 #self.sayState(text=(name, status), template='%s: %s,') 679 #return True 680 681 #def executeTableRowDeleted(self, por, first_child_por, last_child_por, 682 #layer, **kwargs): 683 #''' 684 #Executes this task in response to a row-deleted table change event. 685 #Called by L{execute}. 686 687 #@param por: The L{AEPor} for the related accessible 688 #@type por: L{AEPor} 689 #@param first_child_por: The L{AEPor} of first deleted row 690 #@type first_child_por: L{AEPor} 691 #@param last_child_por: The L{AEPor} of last deleted row 692 #@type last_child_por: L{AEPor} 693 #@param layer: Layer on which the event occurred 694 #@type layer: integer 695 #''' 696 ##print "GaimScript::executeTableRowDeleted()" , por, first_child_por, \ 697 ## last_child_por, layer 698 #frame_name = self.getWindowTitle(por) 699 #if frame_name == "Buddy List": 700 ##print "1" , self.getItemText(first_child_por) 701 ##print "2" , self.getItemText(last_child_por) 702 #name = self.getItemText(first_child_por) 703 ##print "%s logged out" %name 704 #status = (name, STATUS_MSG[LOGOUT_STATUS]) 705 #self.sayState(text=status, template='%s: %s,') 706 #return True 707