Changeset 80

Show
Ignore:
Timestamp:
12/07/07 14:20:34
Author:
slee
Message:

menus now working in GAIL

Files:

Legend:

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

    r76 r80  
    169169  def isHyperlink(self): 
    170170    return self.getHyperlinkObject() is not None 
     171 
     172  def dumpAccTree(self, acc=None, level=0): 
     173    if level == 0 or acc == None: 
     174      try: 
     175        acc = self._acc 
     176        parent = acc.parent 
     177      except LookupError: 
     178        print '[DEAD]' 
     179        return 
     180      print 'Dumping' 
     181    print '  ' * level + str(acc) 
     182    level += 1 
     183    for child_acc in acc: 
     184      if child_acc is None: continue 
     185      self.dumpAccTree(child_acc, level) 
  • action_groups/trunk/ActionBrowser.py

    r79 r80  
    1414import gobject 
    1515 
    16 from ActionModel import ActionModel, ActionGroup 
     16from ActionTree import ActionTree 
    1717 
    1818_ = lambda x: x 
     
    151151      self.groups_tree.do_action() 
    152152 
    153 class ActionTree(gtk.TreeView): 
    154   EVENTS = ('object', 'window', 'focus') 
    155    
    156   def __init__(self): 
    157     gtk.TreeView.__init__(self) 
    158     self.connect('row-expanded', self._onExpanded) 
    159     self.connect('row-collapsed', self._onCollapsed) 
    160     self.connect('destroy', self._onDestroy) 
    161  
    162     crt = gtk.CellRendererText() 
    163     tvc = gtk.TreeViewColumn(_('Role')) 
    164     tvc.pack_start(crt, True) 
    165     tvc.set_attributes(crt, text=ActionModel.COL_ROLE) 
    166     self.append_column(tvc) 
    167     crt = gtk.CellRendererText() 
    168     tvc = gtk.TreeViewColumn(_('Name')) 
    169     tvc.pack_start(crt, True) 
    170     tvc.set_attributes(crt, text=ActionModel.COL_NAME) 
    171     self.append_column(tvc) 
    172  
    173     self.app = None 
    174     #self.set_property('fixed-height-mode', True) # speed display 
    175  
    176   def _onCollapsed(self, treeview, iter, path): 
    177     model = self.get_model() 
    178     model.dePopLevel(iter) 
    179  
    180   def _onExpanded(self, treeview, iter, path): 
    181     # don't repopulate if it has been filled before 
    182     if self.get_model()[iter][ActionModel.COL_FILLED]: 
    183       return 
    184     # populate this level 
    185     model = self.get_model() 
    186     model.popLevel(iter) 
    187     self.next_children = True; 
    188  
    189   def _getSelection(self, selection=None): 
    190     selection = selection or self.get_selection() 
    191     model, iter = selection.get_selected() 
    192     if iter is not None: 
    193       acc = model[iter][ActionModel.COL_ACC] 
    194     else: 
    195       acc = None 
    196     return (model, iter, acc) 
    197  
    198   def get_selected_acc(self, selection=None): 
    199     model, iter, acc = self._getSelection(selection) 
    200     return acc 
    201  
    202   def get_acc_from_path(self, path): 
    203     try: 
    204       acc = self.get_model()[path][ActionModel.COL_ACC] 
    205     except: 
    206       return None 
    207     return acc 
    208  
    209   def set_top_acc(self, app, acc): 
    210     if self.app is not None: 
    211       pyatspi.Registry.deregisterEventListener(self._onATSPIEvent, *ActionTree.EVENTS) 
    212     self.app = app 
    213     model = ActionModel(acc) 
    214     model.popLevel(None) # top 
    215     self.set_model(model) 
    216     pyatspi.Registry.registerEventListener(self._onATSPIEvent, *ActionTree.EVENTS) 
    217  
    218   def _onDestroy(self, object): 
    219     pyatspi.Registry.deregisterEventListener(self._onATSPIEvent, *ActionTree.EVENTS) 
    220  
    221   def select(self, iter): 
    222     selection = self.get_selection() 
    223     selection.select_iter(iter) 
    224  
    225   def next(self): 
    226     selection = self.get_selection() 
    227     model, iter = selection.get_selected() 
    228     if iter is None:  
    229       nextiter = model.get_iter_root() 
    230     elif self.row_expanded(model.get_path(iter)): 
    231       nextiter = model.iter_children(iter) 
    232     else: 
    233       nextiter = model.iter_next(iter) 
    234       if nextiter is None: 
    235         nextiter = model.iter_parent(iter) 
    236         if nextiter is None: 
    237           nextiter = model.get_iter_root() 
    238         else: 
    239           self.next_children = True; 
    240     self.select(nextiter) 
    241  
    242   def _onATSPIEvent(self, event): 
    243     if event.source.getApplication() == self.app: 
    244       s = formatEvent(event) 
    245       gobject.idle_add(self._processEventOnIdle, event, s) 
    246  
    247   def _processEventOnIdle(self, event, ev_string): 
    248     print ev_string 
    249      
    250     try: 
    251       parent = event.source.parent 
    252     except LookupError: 
    253       return False  # its dead now 
    254     
    255     from AccDecorator import AccDecorator 
    256     ev_acc = AccDecorator(event.source) 
    257      
    258     if not self.get_model(): 
    259       return 
    260     model, iter, acc = self._getSelection() 
    261     if acc is None:  
    262       return 
    263      
    264     if event.source.getRole() == pyatspi.ROLE_WINDOW \ 
    265        and event.type in ('object:state-changed:showing'): 
    266       showing = bool(event.detail1) 
    267       path = model.get_path(iter) 
    268  
    269       if showing: 
    270         if acc.hasRoleIn(pyatspi.ROLE_MENU): 
    271           model.makeExpandable(iter) 
    272           model.popLevel(iter) 
    273           self.expand_row(path, False) 
    274           acc.is_group = True 
    275           self.next() 
    276           #dumpAcc(event.source) 
    277          
    278       elif not showing: 
    279         menu_iter = model.iter_parent_with_role(iter, pyatspi.ROLE_MENU) 
    280         if menu_iter: 
    281           menu_path = model.get_path(menu_iter) 
    282           if self.row_expanded(menu_path): 
    283               self.collapse_row(menu_path) 
    284               model.dePopLevel(menu_iter, all=True) 
    285               acc.is_group = False 
    286               self.get_selection().select_iter(menu_iter) 
    287  
    288     return False  # remove this from idle processing 
    289      
    290   def do_action(self): 
    291     model, iter, acc = self._getSelection() 
    292     if acc is None: return 
    293     path = model.get_path(iter) 
    294     acc.grabFocus() 
    295   
    296     if acc.isEditable(): 
    297       try: 
    298         MessageBox(None, 'You are now editing the text:\r\n%s' % acc.getText()) 
    299       except: 
    300         raise 
    301        
    302     # TODO: use template DP for toolkit and application 
    303     elif acc.isActionable(): 
    304       if not (acc.getRole() == pyatspi.ROLE_MENU and self.row_expanded(path)): 
    305         if acc.hasRoleIn(pyatspi.ROLE_MENU, pyatspi.ROLE_MENU_ITEM) and acc.hasToolkitIn('Gecko'): 
    306           acc.generateClick() 
    307         else: 
    308           #acc.generateClick() 
    309           acc.doAction() 
    310  
    311       if acc.isHyperlink(): 
    312         # need to refresh - this is heavy handed 
    313         iter = model.iter_parent_with_role(iter, pyatspi.ROLE_DOCUMENT_FRAME) 
    314         acc = model.getRootAcc() 
    315         path = model.get_path(iter) # assume nothing changes before 
    316         self.set_top_acc(acc) 
    317         selection = self.get_selection() 
    318         print 'zzz' + str(path) 
    319         model.popToPath(path) 
    320         goToPath(path) 
    321         return 
    322            
    323     elif acc.isSelectable(): 
    324       print 'selectable' 
    325       acc.toggleSectable() 
    326               
    327 #    if getattr(acc, 'is_group', False) and acc.is_group: 
    328     if acc.is_group: 
    329       if self.row_expanded(path): 
    330         if acc.getRole() == pyatspi.ROLE_MENU: 
    331           from KeyGenerator import sendKeyCombination 
    332           sendKeyCombination('Escape', '')          
    333         else: 
    334           self.collapse_row(path) 
    335       elif model.iter_has_child(iter): 
    336         self.expand_row(path, False) 
    337         self.next() 
    338  
    339   def goToPath(self, path): 
    340     if len(path) > 1: 
    341       self.expand_to_path(path[:-1]) 
    342     self.scroll_to_cell(path) 
    343     selection = self.get_selection() 
    344     selection.select_path(path) 
    345   
    346 class MessageBox(): 
    347   def __init__(self, parent, message): 
    348     mb = gtk.MessageDialog(parent, 
    349                            gtk.DIALOG_MODAL, 
    350                            gtk.MESSAGE_INFO, 
    351                            buttons=gtk.BUTTONS_OK, 
    352                            message_format=message 
    353                          ) 
    354     mb.run() 
    355     mb.destroy() 
    356  
    357  
    358153class Blinker(object): 
    359154  max_blinks = 6 
     
    393188      return False 
    394189    return True 
    395  
    396 def formatEvent(event): 
    397   from os import times 
    398   try: 
    399     parent = str(event.source.parent) 
    400   except LookupError: 
    401     parent = '[DEAD]' 
    402      
    403   t = int(os.times()[-1] % 10000) 
    404   ad = event.any_data 
    405   if isinstance(ad, pyatspi.Accessibility.BoundingBox): 
    406     sad = '\n\t%s,%s,%s,%s' % (ad.x, ad.y, ad.width, ad.height) 
    407   elif ad: 
    408     sad = str(ad) 
    409   else: 
    410     sad = '' 
    411   s = '%s: %30s %1s %1s %s %s %s' % (t, event.type, event.detail1, event.detail2, 
    412                                    event.source, parent, sad)  
    413   return s 
    414  
    415 def dumpAcc(acc, level=0): 
    416   if level == 0: 
    417     print 'Dumping' 
    418   print ' ' * level + str(acc) 
    419   level += 1 
    420   for child_acc in acc: 
    421     if child_acc is None: continue 
    422     dumpAcc(child_acc, level) 
  • action_groups/trunk/ActionModel.py

    r77 r80  
    6262    # needs interactive (grand)children  
    6363    for child in acc: 
     64      if child is None: continue 
    6465      child = AccDecorator(child) 
    6566      if not child.hasStates(pyatspi.STATE_SHOWING, pyatspi.STATE_VISIBLE):