Package conduit :: Package gtkui :: Module Tree
[hide private]

Source Code for Module conduit.gtkui.Tree

  1  """ 
  2  Cotains treeview and treemodel classes for displaying the  
  3  dataproviders 
  4   
  5  Copyright: John Stowers, 2006 
  6  License: GPLv2 
  7  """ 
  8   
  9  import gtk 
 10  import logging 
 11  log = logging.getLogger("gtkui.Tree") 
 12   
 13  import conduit 
 14  from conduit.ModuleWrapper import ModuleWrapper 
 15   
 16  from gettext import gettext as _ 
 17   
18 -class CategoryWrapper(ModuleWrapper):
19 """ 20 Represents a category stored in the treemodel. Not generally intended 21 to be used outside of C{conduit.Tree.DataProviderTreeModel} 22 """
23 - def __init__(self, category):
24 ModuleWrapper.__init__( 25 self, 26 klass=None, 27 initargs=(), 28 category=category 29 ) 30 self.name=category.name 31 self.classname=category.name 32 self.icon_name=category.icon 33 self.module_type="category"
34
35 - def get_UID(self):
36 return self.name
37 38 IDX_ICON = 0 39 IDX_NAME = 1 40 IDX_DESCRIPTION = 2 41 IDX_DND_KEY = 3 42 COLUMN_TYPES = (gtk.gdk.Pixbuf, str, str, str) 43
44 -class DataProviderTreeModel(gtk.GenericTreeModel):
45 """ 46 A treemodel for managing dynamically loaded modules. Manages an internal 47 list of L{conduit.ModuleManager.ModuleWrapper} 48 49 @ivar modules: The array of modules under this treeviews control. 50 @type modules: L{conduit.ModuleManager.ModuleWrapper}[] 51 """
52 - def __init__(self):
53 """ 54 TreeModel constructor 55 56 Ignores modules which are not enabled 57 """ 58 gtk.GenericTreeModel.__init__(self) 59 #A dictionary mapping wrappers to paths 60 self.pathMappings = {} 61 #2D array of wrappers at their path indexes 62 self.dataproviders = [] 63 #Array of wrappers at their path indexes 64 self.cats = [] 65 66 #Add dataproviders 67 self.add_dataproviders( 68 conduit.GLOBALS.moduleManager.get_modules_by_type("source","sink","twoway") 69 ) 70 conduit.GLOBALS.moduleManager.connect("dataprovider-available",self._on_dataprovider_available) 71 conduit.GLOBALS.moduleManager.connect("dataprovider-unavailable", self._on_dataprovider_unavailable)
72
73 - def _is_category_heading(self, rowref):
74 return rowref.module_type == "category"
75
76 - def _get_category_index_by_name(self, category_name):
77 i = 0 78 for j in self.cats: 79 if j.category == category_name: 80 return i 81 i += 1 82 return None
83
84 - def _get_category_by_name(self, category_name):
85 idx = self._get_category_index_by_name(category_name) 86 return self.cats[idx]
87
88 - def _rebuild_path_mappings(self):
89 self.pathMappings = {} 90 for i, cat in enumerate(self.cats): 91 self.pathMappings[cat] = (i, ) 92 for j, dp in enumerate(self.dataproviders[i]): 93 self.pathMappings[dp] = (i, j)
94
95 - def _on_dataprovider_available(self, loader, dataprovider):
96 if dataprovider.enabled == True: 97 self.add_dataprovider(dataprovider)
98
99 - def _on_dataprovider_unavailable(self, unloader, dataprovider):
100 self.remove_dataprovider(dataprovider)
101
102 - def add_dataproviders(self, dpw=[]):
103 """ 104 Adds all enabled dataproviders to the model 105 """ 106 #Only display enabled modules 107 module_wrapper_list = [m for m in dpw if m.enabled] 108 109 #Add them to the module 110 for mod in module_wrapper_list: 111 #dont signal the GUI to update, providing this model 112 #is added to a view after it has finished being constructed 113 self.add_dataprovider(mod, False)
114
115 - def add_dataprovider(self, dpw, signal=True):
116 """ 117 Adds a dataprovider to the model. Creating a category for it if 118 it does not exist 119 120 @param dpw: The dataproviderwrapper to add 121 @param signal: Whether the associated treeview should be signaled to 122 update the GUI. Set to False for the first time the model is 123 built (in the constructor) 124 @type signal: C{bool} 125 """ 126 #Do we need to create a category first? 127 i = self._get_category_index_by_name(dpw.category) 128 if i == None: 129 new_cat = CategoryWrapper(dpw.category) 130 self.cats.append(new_cat) 131 i = self.cats.index(new_cat) 132 self.pathMappings[new_cat] = (i,) 133 #Signal the treeview to redraw 134 if signal: 135 path=self.on_get_path(new_cat) 136 self.row_inserted(path, self.get_iter(path)) 137 138 #Now add the dataprovider to the categories children 139 try: 140 self.dataproviders[i].append(dpw) 141 except IndexError: 142 #Doesnt have any kids... yet! 143 self.dataproviders.insert(i, [dpw]) 144 145 #Store the index 146 j = self.dataproviders[i].index(dpw) 147 self.pathMappings[dpw] = (i,j) 148 149 #Signal the treeview to redraw 150 if signal: 151 path=self.on_get_path(dpw) 152 self.row_inserted(path, self.get_iter(path))
153
154 - def remove_dataprovider(self, dpw, signal=True):
155 """ 156 Removes the dataprovider from the treemodel. Also removes the 157 category that it was in if there is no remaining dataproviders in 158 that category 159 """ 160 path = self.on_get_path(dpw) 161 self.row_deleted(path) 162 del self.dataproviders[path[0]][path[1]] 163 164 #del (self.childrencache[parent]) 165 166 i = self._get_category_index_by_name(dpw.category) 167 if len(self.dataproviders[i]) == 0: 168 log.info("Category %s empty - removing." % dpw.category) 169 self.row_deleted((i, )) 170 del self.dataproviders[i] 171 del self.cats[i] 172 173 self._rebuild_path_mappings()
174
175 - def on_get_flags(self):
176 """ 177 on_get_flags( 178 """ 179 return gtk.TREE_MODEL_ITERS_PERSIST
180
181 - def on_get_n_columns(self):
182 """ 183 on_get_n_columns( 184 """ 185 return len(COLUMN_TYPES)
186
187 - def on_get_column_type(self, n):
188 """ 189 on_get_column_type( 190 """ 191 return COLUMN_TYPES[n]
192
193 - def on_get_iter(self, path, debug=False):
194 """ 195 on_get_iter( 196 """ 197 if len(self.cats) == 0: 198 return None 199 #Check if this is a toplevel row 200 if len(path) == 1: 201 if path[0] > len(self.cats): 202 return None 203 if debug: 204 print "on_get_iter: path = %s cat = %s" % (path, self.cats[path[0]]) 205 return self.cats[path[0]] 206 else: 207 try: 208 if debug: 209 print "on_get_iter: path = %s dataprovider = %s" % (path, self.dataproviders[path[0]][path[1]]) 210 return self.dataproviders[path[0]][path[1]] 211 except IndexError: 212 #no modules loaded 213 if debug: 214 print "on_get_iter: No modules loaded path = ", path 215 return None
216
217 - def on_get_path(self, rowref):
218 """ 219 on_get_path( 220 """ 221 #print "on_get_path: rowref = ", rowref 222 path = self.pathMappings[rowref] 223 #print "PATH = ", path 224 return path
225
226 - def on_get_value(self, rowref, column):
227 """ 228 on_get_value( 229 """ 230 #print "on_get_value: rowref = %s column = %s" % (rowref, column) 231 if column is IDX_ICON: 232 return rowref.get_descriptive_icon() 233 elif column is IDX_NAME: 234 if self._is_category_heading(rowref): 235 return "<b>"+rowref.name+"</b>" 236 else: 237 return rowref.name 238 elif column is IDX_DESCRIPTION: 239 return rowref.description 240 #Used internally from the TreeView to get the key used by the canvas to 241 #reinstantiate new dataproviders 242 elif column is IDX_DND_KEY: 243 if self._is_category_heading(rowref): 244 return "" 245 else: 246 return rowref.get_dnd_key() 247 #Used internally from the TreeView to see if this is a category heading 248 #and subsequently cancel the drag and drop 249 elif column is IDX_IS_CATEGORY: 250 return self._is_category_heading(rowref)
251
252 - def on_iter_next(self, rowref)