Changeset 70

Show
Ignore:
Timestamp:
11/16/07 17:04:57
Author:
slee
Message:

can run standalone and made modules

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • action_groups/trunk/action_tree.py

    r69 r70  
    33import pyatspi 
    44import gtk 
    5 from accerciser.plugin import ViewportPlugin 
    6 from accerciser.node import Node 
    7 import pyatspi 
    85import gobject 
    96from time import time 
    107 
    118_ = lambda x: x 
    12  
    13 class ActionsBrowser(ViewportPlugin): 
    14   plugin_name = 'Actions tree' 
    15   def init(self): 
    16     ''' 
    17     Initialize the API browser plugin. 
    18     ''' 
    19     self._buildUI() 
    20     self.is_scanning = False 
    21  
    22   def _buildUI(self): 
    23     ''' 
    24     Manually build the plugin's UI. 
    25     ''' 
    26     vbox = gtk.VBox() 
    27     self.plugin_area.add(vbox) 
    28     top_hbox = gtk.HBox() 
    29     bottom_hbox = gtk.HButtonBox() 
    30     bottom_hbox.set_layout(gtk.BUTTONBOX_SPREAD) 
    31     vbox.pack_start(top_hbox) 
    32     vbox.pack_start(bottom_hbox, False) 
    33     self.groups_tree = ProgressiveTree() 
    34      
    35     self.groups_tree.connect('row-activated', self._onRowActivated) 
    36  
    37     selection = self.groups_tree.get_selection() 
    38     selection.connect("changed", self._onSelectionChanged) 
    39  
    40     scrolled_window = gtk.ScrolledWindow() 
    41     scrolled_window.add(self.groups_tree) 
    42     top_hbox.pack_start(scrolled_window) 
    43  
    44     generate_button = gtk.Button('_Generate', use_underline=True) 
    45     generate_button.connect('clicked', self._onGenerate) 
    46     bottom_hbox.pack_start(generate_button, False) 
    47  
    48     examine_button = gtk.Button('E_xamine', use_underline=True) 
    49     examine_button.connect('clicked', self._onExamine) 
    50     bottom_hbox.pack_start(examine_button, False) 
    51  
    52     scan_button = gtk.Button('Start _Scan', use_underline=True) 
    53     scan_button.connect('clicked', self._onScan) 
    54     bottom_hbox.pack_start(scan_button, False) 
    55  
    56     action_button = gtk.Button('_Action',  
    57                                use_underline=True) 
    58     action_button.connect('clicked', self._onAction) 
    59     bottom_hbox.pack_start(action_button, False) 
    60  
    61     self.show_all() 
    62  
    63   def _onGenerate(self, button): 
    64     self.groups_tree.set_top_acc(self.acc) 
    65     self.groups_tree.next() 
    66      
    67   def _onExamine(self, button): 
    68     acc = self.groups_tree.get_selected_acc() 
    69     if acc: 
    70       self.node.update(acc) 
    71      
    72   def _onScan(self, button): 
    73     if not self.is_scanning: 
    74       gobject.timeout_add(1000, self._onScanStep) 
    75     self.is_scanning = not self.is_scanning 
    76     label = ('Stop _Scan' if self.is_scanning else 'Start _Scan') 
    77     button.set_label(label) 
    78      
    79   def _onScanStep(self): 
    80     if self.is_scanning: 
    81       self.groups_tree.next() 
    82     return self.is_scanning 
    83  
    84   def _onAction(self, button): 
    85     self.groups_tree.do_action() 
    86  
    87   def _onRowActivated(self, treeview, path, column): 
    88     acc = self.groups_tree.get_acc_from_path(path) 
    89     self.node.update(acc) 
    90      
    91   def _onSelectionChanged(self, selection): 
    92     acc = self.groups_tree.get_selected_acc(selection) 
    93     if acc: 
    94       Blinker(acc) 
    959 
    9610# can't derive from pyatspi.Accessibility.Accessible due to various issues 
     
    304218    self[iter][self.COL_FILLED] = False 
    305219 
    306 class ProgressiveTree(gtk.TreeView): 
    307   def __init__(self): 
    308     gtk.TreeView.__init__(self) 
    309     self.connect('row-expanded', self._onExpanded) 
    310     self.connect('row-collapsed', self._onCollapsed) 
    311  
    312     crt = gtk.CellRendererText() 
    313     tvc = gtk.TreeViewColumn(_('Role')) 
    314     tvc.pack_start(crt, True) 
    315     tvc.set_attributes(crt, text=ProgressiveTreeModel.COL_ROLE) 
    316     self.append_column(tvc) 
    317     crt = gtk.CellRendererText() 
    318     tvc = gtk.TreeViewColumn(_('Name')) 
    319     tvc.pack_start(crt, True) 
    320     tvc.set_attributes(crt, text=ProgressiveTreeModel.COL_NAME) 
    321     self.append_column(tvc) 
    322  
    323     self.next_children = False; 
    324     #self.set_property('fixed-height-mode', True) # speed display 
    325  
    326   def _onCollapsed(self, treeview, iter, path): 
    327     model = self.get_model() 
    328     model.dePopLevel(iter) 
    329  
    330   def _onExpanded(self, treeview, iter, path): 
    331     # don't repopulate if it has been filled before 
    332     if self.get_model()[iter][ProgressiveTreeModel.COL_FILLED]: 
    333       return 
    334     # populate this level 
    335     model = self.get_model() 
    336     model.popLevel(iter) 
    337     self.next_children = True; 
    338    
    339   def _getSelection(self, selection=None): 
    340     selection = selection or self.get_selection() 
    341 #    if selection is None: 
    342 #      return (self.get_model(), None, None) 
    343     model, iter = selection.get_selected() 
    344     if iter: 
    345       acc = model[iter][ProgressiveTreeModel.COL_ACC] 
    346     else: 
    347       acc = None 
    348     return (model, iter, acc) 
    349    
    350   def get_selected_acc(self, selection=None): 
    351     model, iter, acc = self._getSelection(selection) 
    352     return acc 
    353    
    354   def get_acc_from_path(self, path): 
    355     if not self.get_model(): 
    356       return None 
    357     return self.get_model()[path][ProgressiveTreeModel.COL_ACC] 
    358  
    359   def set_top_acc(self, acc): 
    360     model = ProgressiveTreeModel(acc) 
    361     model.popLevel(None) # top 
    362     self.set_model(model) 
    363     pyatspi.Registry.registerEventListener(self._onAccEventState, 'object:state-changed') 
    364  
    365   def __del__(self): 
    366     self.deRegisterEventListener(self._onAccEventState, 'object:state-changed') 
    367      
    368   def select(self, iter): 
    369     selection = self.get_selection() 
    370     selection.select_iter(iter) 
    371  
    372   def next(self): 
    373     selection = self.get_selection() 
    374     model, iter = selection.get_selected() 
    375     if iter is None:  
    376       nextiter = model.get_iter_root() 
    377     elif self.row_expanded(model.get_path(iter)): 
    378       nextiter = model.iter_children(iter) 
    379     else: 
    380       nextiter = model.iter_next(iter) 
    381       if nextiter is None: 
    382         nextiter = model.iter_parent(iter) 
    383         if nextiter is None: 
    384           nextiter = model.get_iter_root() 
    385         else: 
    386           self.next_children = True; 
    387     self.select(nextiter) 
    388       
    389   def _onAccEventState(self, event): 
    390     ''' 
    391     Callback for accessible state changes. Repopulates the states model. 
    392      
    393     @param event: Event that triggered this callback. 
    394     @type event: Accessibility.Event 
    395     ''' 
    396     if not self.get_model(): 
    397       return 
    398     if event.source.getApplication() <> self.get_acc_from_path(0).getApplication(): 
    399       return 
    400     model, iter, acc = self._getSelection() 
    401     if acc is None:  
    402       return 
    403     print event.type, event.detail1, event.detail2, event.source, acc,  event.source.parent 
    404     if acc.getRole() == pyatspi.ROLE_MENU : 
    405       print 'menu' 
    406       if event.source.parent == acc._acc : 
    407         print 'parent' 
    408         if event.type in ('object:state-changed:showing'): 
    409           showing = event.detail1 
    410           path = model.get_path(iter) 
    411           if showing == 1 \ 
    412              and not model.iter_has_child(iter): 
    413             model.makeExpandable(iter) 
    414             model.popLevel(iter) 
    415             self.expand_row(path, False) 
    416           elif showing == 0 \ 
    417                and self.row_expanded(path): 
    418               self.collapse_row(path) 
    419               model.dePopLevel(iter, all=True) 
    420      
    421   def do_action(self): 
    422     model, iter, acc = self._getSelection() 
    423     if acc is None: return 
    424     path = model.get_path(iter) 
    425     is_interactive = acc.isInteractive() 
    426     if is_interactive: 
    427       try: 
    428         action_if = acc.queryAction() 
    429         action_if.doAction(0) 
    430       except: 
    431         pass 
    432        
    433     else:   
    434       if self.row_expanded(path): 
    435         self.collapse_row(path) 
    436       elif model.iter_has_child(iter): 
    437         self.expand_row(path, False) 
    438  
    439 class Blinker(object): 
    440   max_blinks = 6 
    441   def __init__(self, acc): 
    442     display = gtk.gdk.display_get_default() 
    443     screen = display.get_default_screen() 
    444     self.root = screen.get_root_window() 
    445     self.gc = self.root.new_gc() 
    446     self.gc.set_subwindow(gtk.gdk.INCLUDE_INFERIORS) 
    447     self.gc.set_function(gtk.gdk.INVERT) 
    448     self.gc.set_line_attributes(3, gtk.gdk.LINE_DOUBLE_DASH, gtk.gdk.CAP_BUTT,  
    449                                 gtk.gdk.JOIN_MITER) 
    450     self.inv = gtk.Invisible() 
    451     self.inv.set_screen(screen) 
    452      
    453     try: 
    454       ci = acc.queryComponent() 
    455     except: 
    456       return 
    457  
    458     self.extents = ci.getExtents(pyatspi.DESKTOP_COORDS) 
    459     self.blinks = 0 
    460     gobject.timeout_add(30, self._drawRectangle) 
    461  
    462   def _drawRectangle(self): 
    463     ''' 
    464     Draw a rectangle on the screen using L{extents} for position and size. 
    465     ''' 
    466     # draw a blinking rectangle  
    467     if self.blinks == 0: 
    468       self.inv.show() 
    469       self.inv.grab_add() 
    470     self.root.draw_rectangle(self.gc, False,  
    471                              self.extents.x, 
    472                              self.extents.y, 
    473                              self.extents.width, 
    474                              self.extents.height) 
    475     self.blinks += 1 
    476     if self.blinks >= self.max_blinks: 
    477       self.inv.grab_remove() 
    478       self.inv.destroy() 
    479       return False 
    480     return True