def get_n_nodes(self,withfilters=[],include_transparent=True): """ returns quantity of displayed nodes in this tree if the withfilters is set, returns the quantity of nodes that will be displayed if we apply those filters to the current tree. It means that the currently applied filters are also taken into account. If include_transparent = False, we only take into account the applied filters that doesn't have the transparent parameters. """ if not self.__ft: print "you cannot get_n_nodes for a static tree" self.__ft = FilteredTree(self.__maintree, self.__fbank, refresh = True) return self.__ft.get_n_nodes(withfilters=withfilters,\ include_transparent=include_transparent)
def __init__(self, maininterface, maintree, filters_bank,\ refresh = True, static = False): '''A ViewTree is the interface that should be used to display Tree(s). @param maintree: a Tree object, cointaining all the nodes @param filters_bank: a FiltersBank object. Filters can be added dinamically to that. @param refresh: if True, this ViewTree is automatically refreshed after applying a filter. @param static: if True, this is the view of the complete maintree. Filters cannot be added to such a view. ''' gobject.GObject.__init__(self) self.maininterface = maininterface self.__maintree = maintree self.static = static self.__cllbcks = {} self.thread = None #If we are static, we directly ask the tree. No need of an #FilteredTree layer self.__ft = None self.__fbank = filters_bank if static: #Needed for the get_n_nodes with filters # self.__ft = FilteredTree(maintree, filters_bank, refresh = refresh) self.__maintree.register_callback('node-added', \ functools.partial(self.__emit, 'node-added')) self.__maintree.register_callback('node-deleted', \ functools.partial(self.__emit, 'node-deleted')) self.__maintree.register_callback('node-modified', \ functools.partial(self.__emit, 'node-modified')) else: self.__ft = FilteredTree(maintree, filters_bank, refresh = refresh) self.__ft.set_callback('added', \ functools.partial(self.__emit, 'node-added-inview')) self.__ft.set_callback('deleted', \ functools.partial(self.__emit, 'node-deleted-inview')) self.__ft.set_callback('modified', \ functools.partial(self.__emit, 'node-modified-inview')) self.__ft.set_callback('reordered', \ functools.partial(self.__emit, 'node-children-reordered'))
class ViewTree(gobject.GObject): #Those are the three signals you want to catch if displaying #a filteredtree. The argument of all signals is the nid of the node __gsignal_str = (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (str, )) __gsignal_str2 = (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, \ (str,gobject.TYPE_PYOBJECT, )) __gsignal_str3 = (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, \ (str,gobject.TYPE_PYOBJECT,\ gobject.TYPE_PYOBJECT, )) #FIXME: should we unify those signals ? They are conceptually different __gsignals__ = {'node-added-inview' : __gsignal_str2, 'node-deleted-inview' : __gsignal_str2, 'node-modified-inview': __gsignal_str2, 'node-children-reordered': __gsignal_str3, 'node-added' : __gsignal_str, 'node-deleted' : __gsignal_str, 'node-modified': __gsignal_str,} def __init__(self, maininterface, maintree, filters_bank,\ refresh = True, static = False): '''A ViewTree is the interface that should be used to display Tree(s). @param maintree: a Tree object, cointaining all the nodes @param filters_bank: a FiltersBank object. Filters can be added dinamically to that. @param refresh: if True, this ViewTree is automatically refreshed after applying a filter. @param static: if True, this is the view of the complete maintree. Filters cannot be added to such a view. ''' gobject.GObject.__init__(self) self.maininterface = maininterface self.__maintree = maintree self.static = static self.__cllbcks = {} self.thread = None #If we are static, we directly ask the tree. No need of an #FilteredTree layer self.__ft = None self.__fbank = filters_bank if static: #Needed for the get_n_nodes with filters # self.__ft = FilteredTree(maintree, filters_bank, refresh = refresh) self.__maintree.register_callback('node-added', \ functools.partial(self.__emit, 'node-added')) self.__maintree.register_callback('node-deleted', \ functools.partial(self.__emit, 'node-deleted')) self.__maintree.register_callback('node-modified', \ functools.partial(self.__emit, 'node-modified')) else: self.__ft = FilteredTree(maintree, filters_bank, refresh = refresh) self.__ft.set_callback('added', \ functools.partial(self.__emit, 'node-added-inview')) self.__ft.set_callback('deleted', \ functools.partial(self.__emit, 'node-deleted-inview')) self.__ft.set_callback('modified', \ functools.partial(self.__emit, 'node-modified-inview')) self.__ft.set_callback('reordered', \ functools.partial(self.__emit, 'node-children-reordered')) def set_thread(self,thread): self.thread = thread def get_basetree(self): return self.maininterface def get_state_id(self): return self.__ft.get_state_id() def __emit(self, signal_name, tid,path=None,state_id=None,neworder=None,): for k in self.__cllbcks.get(signal_name, {}).copy(): f = self.__cllbcks[signal_name][k] if neworder: f(tid,path,neworder,state_id) elif state_id: f(tid,path,state_id) else: f(tid,path) if signal_name.endswith('-inview'): self.emit(signal_name, tid,path) elif signal_name.endswith('-reordered'): self.emit(signal_name,tid,path,neworder) else: self.emit(signal_name, tid) def register_cllbck(self,event,func): if THREAD_PROTECTION: t = threading.current_thread() if t != self.thread: raise Exception('! could not register_cllbck from thread %s' %t) if not self.__cllbcks.has_key(event): self.__cllbcks[event] = {} dic = self.__cllbcks[event] #finding a free key k = 0 while dic.has_key(k): k += 1 #registering dic[k] = func #returning the key so we can later unregister a callback return k def deregister_cllbck(self,event,func): try: del self.__cllbcks[event][func] except KeyError: pass #only by commodities def get_node(self,nid): return self.__maintree.get_node(nid) def __get_static_node(self,nid): toreturn = None if self.static: if not nid or nid == 'root': toreturn = self.__maintree.get_root() else: toreturn = self.__maintree.get_node(nid) else: raise Exception("You should not get a static node"+\ " in a viewtree") return toreturn def get_root(self): return self.__maintree.get_root() def print_tree(self,string=None,state_id=None): if self.static: return self.__maintree.print_tree(string=string) else: return self.__ft.print_tree(string=string,state_id=state_id) #return a list of nid of displayed nodes def get_all_nodes(self,state_id=None): if self.static: return self.__maintree.get_all_nodes() else: return self.__ft.get_all_nodes(state_id=state_id) def refresh_all(self): if THREAD_PROTECTION: t = threading.current_thread() if t != self.thread: raise Exception('! could not refresh_all from thread %s' %t) self.__maintree.refresh_all() def get_n_nodes(self,withfilters=[],include_transparent=True): """ returns quantity of displayed nodes in this tree if the withfilters is set, returns the quantity of nodes that will be displayed if we apply those filters to the current tree. It means that the currently applied filters are also taken into account. If include_transparent = False, we only take into account the applied filters that doesn't have the transparent parameters. """ if not self.__ft: print "you cannot get_n_nodes for a static tree" self.__ft = FilteredTree(self.__maintree, self.__fbank, refresh = True) return self.__ft.get_n_nodes(withfilters=withfilters,\ include_transparent=include_transparent) def get_node_for_path(self, path,state_id=None): if THREAD_PROTECTION: t = threading.current_thread() if t != self.thread: raise Exception('! could not get_node_for_path from thread %s' %t) if self.static: return self.__maintree.get_node_for_path(path) else: return self.__ft.get_node_for_path(path,state_id=state_id) #If nid is none, return root path def get_paths_for_node(self, nid=None,state_id=None): if THREAD_PROTECTION: t = threading.current_thread() if t != self.thread: raise Exception('! could not get_paths_for_node from thread %s' %t) if self.static: return self.__maintree._paths_for_node(nid) else: return self.__ft.get_paths_for_node(nid,state_id=state_id) #pid is used only if nid has multiple parents. #if pid is none, a random parent is used. def next_node(self, nid,pid=None,state_id=None): if THREAD_PROTECTION: t = threading.current_thread() if t != self.thread: raise Exception('! could not next_node from thread %s' %t) if self.static: return self.__maintree.next_node(nid,pid=pid) else: return self.__ft.next_node(nid,pid,state_id=state_id) def node_has_child(self, nid,state_id=None): if THREAD_PROTECTION: t = threading.current_thread() if t != self.thread: raise Exception('! could not has_child from thread %s' %t) if self.static: toreturn = self.__maintree.get_node(nid).has_child() else: toreturn = self.__ft.node_has_child(nid,state_id=state_id) return toreturn #if nid is None, return the number of nodes at the root def node_n_children(self, nid=None,state_id=None): if THREAD_PROTECTION: t = threading.current_thread() if t != self.thread: raise Exception('! could not node_n_children from thread %s' %t) return len(self.node_all_children(nid,state_id=state_id)) def node_all_children(self, nid=None,state_id=None): if THREAD_PROTECTION: t = threading.current_thread() if t != self.thread: raise Exception('! could not node_all_children from thread %s' %t) if self.static: if not nid or self.__maintree.has_node(nid): toreturn = self.__maintree.get_node(nid).get_children() else: toreturn = [] else: toreturn = self.__ft.node_all_children(nid,state_id=state_id) return toreturn def node_nth_child(self, nid, n,state_id=None): if THREAD_PROTECTION: t = threading.current_thread() if t != self.thread: raise Exception('! could not node_nth_child from thread %s' %t) toreturn = None if self.static: node = self.__get_static_node(nid) if node and node.get_n_children() > n: toreturn = node.get_nth_child(n) else: raise ValueError("node %s has less than %s nodes" %(nid,n)) else: realn = self.__ft.node_n_children(nid,state_id=state_id) if realn <= n: raise ValueError("viewtree has %s nodes, no node %s" %(realn,n)) toreturn = self.__ft.node_nth_child(nid,n,state_id=state_id) return toreturn def node_has_parent(self,nid,state_id=None): if THREAD_PROTECTION: t = threading.current_thread() if t != self.thread: raise Exception('! could not node_has_parent from thread %s' %t) return len(self.node_parents(nid,state_id=state_id)) > 0 def node_parents(self, nid,state_id=None): """ Returns displayed parents of the given node, or [] if there is no parent (such as if the node is a child of the virtual root), or if the parent is not displayable. Doesn't check wheter node nid is displayed or not. (we only care about parents) """ if THREAD_PROTECTION: t = threading.current_thread() if t != self.thread: raise Exception('! could not node_parents from thread %s' %t) if self.static: toreturn = self.__maintree.get_node(nid).get_parents() else: toreturn = self.__ft.node_parents(nid,state_id=state_id) return toreturn def is_displayed(self,nid,state_id=None): if THREAD_PROTECTION: t = threading.current_thread() if t != self.thread: raise Exception('! could not is_displayed from thread %s' %t) if self.static: return self.__maintree.has_node(nid) else: return self.__ft.is_displayed(nid,state_id=state_id) ####### Change filters ################# def list_applied_filters(self): return self.__ft.list_applied_filters() def apply_filter(self,filter_name,parameters=None,\ reset=False,refresh=True): """ Applies a new filter to the tree. @param filter_name: The name of an already registered filter to apply @param parameters: Optional parameters to pass to the filter @param reset : optional boolean. Should we remove other filters? @param refresh : should we refresh after applying this filter ? """ if THREAD_PROTECTION: t = threading.current_thread() if t != self.thread: raise Exception('! could not apply_filter from thread %s' %t) if self.static: raise Exception("WARNING: filters cannot be applied" +\ "to a static tree\n") else: self.__ft.apply_filter(filter_name,parameters=parameters,\ reset=reset,refresh=refresh) return def unapply_filter(self,filter_name,refresh=True): """ Removes a filter from the tree. @param filter_name: The name of an already added filter to remove """ if THREAD_PROTECTION: t = threading.current_thread() if t != self.thread: raise Exception('! could not unapply_filter from thread %s' %t) if self.static: raise Exception("WARNING: filters cannot be unapplied" +\ "from a static tree\n") else: self.__ft.unapply_filter(filter_name, refresh=refresh) return def reset_filters(self,refresh=True,transparent_only=False): """ Clears all filters currently set on the tree. """ if THREAD_PROTECTION: t = threading.current_thread() if t != self.thread: raise Exception('! could not reset_filters from thread %s' %t) if self.static: raise Exception("WARNING: filters cannot be reset" +\ "on a static tree\n") else: self.__ft.reset_filters(refresh=refresh,\ transparent_only=transparent_only) return