00001 __version__ = "$Revision: 2.4 $" 00002 00003 from qt import * 00004 00005 class userAppLeaf(QListViewItem): 00006 """\brief userApp Gui Leaf 00007 This is the class of a leaf in the userApp Gui Tree 00008 It contains both basic functionality as a leaf (mainly input selection functions) 00009 and functionality as a manager of application windows 00010 """ 00011 00012 whitebox_pix = None 00013 greybox_pix = None 00014 whitecheckedbox_pix = None 00015 00016 objects = {} 00017 def __init__(self, lat, node, parent): 00018 """ Init Function for the leaf 00019 \param lat_node pointer to the LAT structure 00020 \param self_node pointer to the "Gnode" device related to this leaf 00021 \param parent object to use as the QCheckListItem parent 00022 """ 00023 userAppLeaf.objects[id(self)] = 1 00024 self.node = node 00025 self.lat = lat 00026 self.inputNodes = [] 00027 00028 QListViewItem.__init__(self, parent,self.name()) 00029 self.setText(0, self.name()) 00030 self.setOn(0) 00031 00032 self.setEnabled(1) 00033 self.window = None 00034 self.subw_list = [] 00035 self.window_scroller = None 00036 self.warning = 0 00037 self.pwarning = 0 00038 # self.AppWindowFiles = [] 00039 self.guiClasses = [] 00040 self.__generateCheckBoxDrawing() 00041 self.setPixmap(0, self.whitebox_pix) 00042 00043 00044 00045 def __generateCheckBoxDrawing(self): 00046 if userAppLeaf.whitebox_pix is None: 00047 checkbox = QCheckBox(None,'') 00048 checkbox.setMaximumSize(checkbox.sizeHint()) 00049 checkbox.setTristate(1) 00050 checkbox.setState(QCheckBox.Off) 00051 userAppLeaf.whitebox_pix = QPixmap.grabWidget(checkbox) 00052 checkbox.setState(QCheckBox.NoChange) 00053 userAppLeaf.greybox_pix = QPixmap.grabWidget(checkbox) 00054 checkbox.setState(QCheckBox.On) 00055 userAppLeaf.whitecheckedbox_pix = QPixmap.grabWidget(checkbox) 00056 ## checkbox.hide() 00057 00058 def rect(self): 00059 tree = self.getTree() 00060 rect = tree.itemRect(self) 00061 a = tree.treeStepSize()*(self.depth()+tree.rootIsDecorated())+tree.itemMargin() + self.pixmap(0).width() 00062 rect.setLeft(a) 00063 return rect 00064 00065 def pressedEvent(self,pos, column): 00066 tree = self.getTree() 00067 pos = tree.mapFromGlobal(pos) 00068 a = tree.treeStepSize()*(self.depth()+tree.rootIsDecorated())+tree.itemMargin() 00069 ##b = a + 20 00070 b = a + self.pixmap(0).width() 00071 #~ print "%d, %d" %(a,b) 00072 if pos.x() > a and pos.x() < b: 00073 self.stateChangeClicked() 00074 00075 def setOn(self, value): 00076 self.On = value 00077 00078 def isOn(self): 00079 return self.On 00080 00081 def __del__(self): 00082 del userAppLeaf.objects[id(self)] 00083 00084 ## Leaf functionality 00085 def getTree(self): 00086 return self.listView() 00087 00088 def stateChangeClicked(self): 00089 self.setOn(not self.isOn()) 00090 self.__propagateTriggerInputsUpdate() 00091 self.getTree().emit(PYSIGNAL("leafStateChanged (userAppLeaf * )"), (self, )) 00092 00093 def __propagateTriggerInputsUpdate(self,childrenToo = 0, parentToo = 1): 00094 if childrenToo: 00095 child = self.firstChild() 00096 while child is not None: 00097 child.__propagateTriggerInputsUpdate(childrenToo,0) 00098 child = child.nextSibling() 00099 self.triggerInputsUpdate() 00100 if parentToo and self.parent() is not None: 00101 self.parent().__propagateTriggerInputsUpdate(0, parentToo) 00102 00103 def name(self): 00104 """ Function which returns the name of the leaf 00105 A parent of this leaf should not possibly have two leaves with the same name 00106 The leaf could have cousins with the same name 00107 \return name of node/leaf 00108 """ 00109 name_with_id = "%s %2d" %(self.node.getName(), self.node.id()) 00110 return name_with_id 00111 00112 def module(self): 00113 """ Function which returns the name of the Gnode 00114 The parent might have more than one child with the same module name 00115 \return name of module type 00116 """ 00117 return str(self.node.getName()) 00118 00119 def getLeaf(self,leaf): 00120 """ Function that finds the leaf in the hierarchical structure of leaves starting at this leaf 00121 A match only occur if there exist a leaf at depth k under self with all of its parents name up to self matching with the reference leaf kth first parents. 00122 Ex: ref_leaf = a->b->self->d->e->ref_leaf will match with self->d->e->ref_leaf 00123 This function is mostly use to port information between leaves of different implementation of the same ELX Tree 00124 \param leaf leaf object to find in the structure 00125 \return the leaf that matches with the searched leaf, None with no match 00126 """ 00127 #Is it self? 00128 if leaf.name() == self.name(): 00129 return self 00130 00131 #Is self a parent? 00132 leaf_parent = leaf 00133 leaf_parent_parent = leaf.parent() 00134 while 1: 00135 if leaf_parent_parent.name() == self.name(): 00136 break 00137 elif leaf_parent_parent == leaf.getTree(): 00138 return None 00139 leaf_parent = leaf_parent_parent 00140 leaf_parent_parent = leaf_parent_parent.parent() 00141 00142 # Can we get it from any of our child? 00143 us_child = self.firstChild() 00144 while us_child is not None: 00145 if us_child.name() == leaf_parent.name(): 00146 return us_child.getLeaf(leaf) 00147 us_child = us_child.nextSibling() 00148 return None 00149 00150 def __copyCheckedNodes(self, from_leaf): 00151 """ Function which copies all the checked information from the from_leaf structure to the self leaf structure 00152 The functions does not do anything if from_leaf and self do not match 00153 \from_leaf leaf to use as a reference to set the checked structure of this leaf 00154 """ 00155 if self.name() == from_leaf.name(): 00156 self.setOn(from_leaf.isOn()) 00157 #~ self.setOnNoSignal(from_leaf.isOn()) 00158 from_child = from_leaf.firstChild() 00159 00160 ##assuming the same ordering of children 00161 to_child = self.firstChild() 00162 while from_child is not None: 00163 while to_child is not None: 00164 if to_child.name() == from_child.name(): 00165 to_child.__copyCheckedNodes(from_child) 00166 to_child = to_child.nextSibling() 00167 break 00168 to_child = to_child.nextSibling() 00169 from_child = from_child.nextSibling() 00170 00171 ## No prior assumption 00172 #~ while from_child is not None: 00173 #~ to_child = self.firstChild() 00174 #~ while to_child is not None: 00175 #~ to_child.copyCheckedNodes(from_child) 00176 #~ to_child = to_child.nextSibling() 00177 #~ from_child = from_child.nextSibling() 00178 00179 def copyCheckedNodes(self, from_leaf): 00180 self.__copyCheckedNodes(from_leaf) 00181 self.__propagateTriggerInputsUpdate(True, True) 00182 self.__emitLeavesStateChanged() 00183 00184 def select_family(self, value = 1): 00185 """ Function that checks/unchecks this leaf and all its children leaves and all their children... 00186 \value checks all leaves if 1, unchecks all if 0 00187 """ 00188 self.setOn(value) 00189 child = self.firstChild() 00190 while child is not None: 00191 child.select_family(value) 00192 child = child.nextSibling() 00193 00194 def unselect_family(self): 00195 """ Function that unchecks this leaf and all its children leaves and all their children... 00196 """ 00197 self.select_family(0) 00198 00199 def expand_family(self, value = 1): 00200 """ Function that expands/collapse the leaf node in the tree and all its children and their children... 00201 \value expands all leaves if 1, collapse if 0 00202 """ 00203 self.setOpen(value) 00204 child = self.firstChild() 00205 while child is not None: 00206 child.expand_family(value) 00207 child = child.nextSibling() 00208 00209 def collapse_family(self): 00210 """ Function that expands/collapse the leaf node in the tree and all its children and their children... 00211 """ 00212 self.expand_family(0) 00213 00214 def selectFamilyClicked(self, value = 1): 00215 self.select_family(value) 00216 self.__propagateTriggerInputsUpdate(1,1) 00217 self.__emitLeavesStateChanged() 00218 00219 def __emitLeavesStateChanged(self): 00220 self.getTree().emit(PYSIGNAL("leavesStateChanged ( QListViewItem * )"), (self, )) 00221 00222 def unselectFamilyClicked(self): 00223 self.selectFamilyClicked(0) 00224 00225 def leafActionsTuples(self): 00226 """ Function which returns the possible actions that can be included in this leafs menu 00227 \return a list of tuples (name,method) where name is the name of the action and method is the method implements the action 00228 """ 00229 actions = [('Select All',self.selectFamilyClicked), 00230 ('Unselect All',self.unselectFamilyClicked), 00231 ('Expand',self.expand_family), 00232 ('Collapse',self.collapse_family)] 00233 return actions 00234 00235 ## Application manager 00236 00237 def loadAppWindows(self,leaf_window_list): 00238 """ Function which loads the list of application windows related to the leaf 00239 \param appfiles_list list of module names to use as application window (these module need to contain a class 'MainWindow') 00240 """ 00241 if self.window is not None: 00242 self.window.close() 00243 self.window = None 00244 del(self.subw_list) 00245 del(self.app_list) 00246 self.subw_list = [] 00247 self.guiClasses = leaf_window_list 00248 00249 def createWindow(self,parent): 00250 """ Function that creates the window containing the applications managed by the leaf 00251 If the window exists already, the function returns the pointer to this window 00252 \parent pointer to the parent to use to create the window 00253 \return pointer to the window 00254 """ 00255 if self.window is None: 00256 self.window = QVBox(parent) 00257 for guiclass in self.guiClasses: 00258 #look for gui, userId, debug 00259 subw = guiclass(self.lat, self.node, self.window, self) 00260 self.subw_list.append(subw) 00261 return self.window 00262 00263 00264 def getInputNodes(self, of_class_type = None): 00265 """ Function which extracts from all its child leaves the ones that are checked 00266 Builds a list of Gnodes for the application to use as inputs 00267 \return list of Gnodes 00268 """ 00269 if of_class_type is None: 00270 return self.inputNodes 00271 00272 inputs = [] 00273 for node in self.inputNodes: 00274 if isinstance(node, of_class_type): 00275 inputs.append(node) 00276 return inputs 00277 00278 def getLogDir(self): 00279 """ Function which returns the current log directory for the application 00280 \return a string containing the name of the directory to log in 00281 """ 00282 return self.getTree().sys_comm.getLogDir() 00283 00284 def getRC(self): 00285 return self.getTree().sys_comm.getRC() 00286 00287 def setStatus(self, status_descr): 00288 if status_descr[0] == 'warning': 00289 self.setWarning(1) 00290 else: 00291 self.setWarning(0) 00292 self.getTree().setStatus(self, status_descr) 00293 00294 def triggerPolling(self): 00295 if self.window is not None: 00296 for subw in self.subw_list: 00297 subw.triggerPolling() 00298 00299 def triggerCmdCliUpdate(self): 00300 if self.window is not None: 00301 for subw in self.subw_list: 00302 subw.triggerCmdCliUpdate() 00303 00304 def triggerInputsUpdate(self): 00305 ##This method assumes that all children of this leaf have been previously triggered 00306 in_nodes = [] 00307 if self.isOn(): 00308 in_nodes = [self.node] 00309 child = self.firstChild() 00310 while child is not None: 00311 in_nodes = in_nodes + child.getInputNodes() 00312 child = child.nextSibling() 00313 self.inputNodes = in_nodes 00314 if not self.isOn(): 00315 if in_nodes != []: 00316 self.setPixmap(0,self.greybox_pix) 00317 else: 00318 self.setPixmap(0,self.whitebox_pix) 00319 else: 00320 self.setPixmap(0,self.whitecheckedbox_pix) 00321 00322 if self.window is not None: 00323 for subw in self.subw_list: 00324 subw.triggerInputsUpdate() 00325 00326 def close(self): 00327 if self.window is not None: 00328 for subw in self.subw_list: 00329 subw.close() 00330 self.window.close() 00331 00332 00333 ## Triggering Alerts section 00334 00335 def paintCell(self, p, cg, column, width, align): 00336 """ Function that reimplements QCheckListItem.paintCell to show that warning is active 00337 """ 00338 new_cg = QColorGroup(cg) 00339 if self.pwarning == 1: 00340 new_cg.setColor(QColorGroup.Text , QColor(200,0,0)) 00341 QListViewItem.paintCell(self, p, new_cg, column, width, align) 00342 00343 def paintFocus(self, p, cg, r): 00344 ## Removes the misaligned flashy rectangle around the selected item 00345 pass 00346 00347 def paintWarning(self, value): 00348 """ Function that sets the Paint warning value for the leaf 00349 A paint warning means either the leaf or one of the leaf's child is in warning mode 00350 \param value warning is painted if 1, not painted if 0 00351 """ 00352 self.pwarning = value 00353 self.repaint() 00354 00355 def updatePWarning(self): 00356 """ Function which updates the paint warning for this leaf and triggers an update for this leaf's parent 00357 """ 00358 warning = self.warning 00359 child = self.firstChild() 00360 while child is not None: 00361 warning |= child.pwarning 00362 child = child.nextSibling() 00363 if warning != self.pwarning: 00364 self.paintWarning(warning) 00365 if self.parent() is not None: 00366 self.parent().updatePWarning() 00367 00368 def setWarning(self,value): 00369 """ Function that sets/clear the leaf in warning mode 00370 It also updates the paint warning information 00371 \param value sets if 1, clears if 0 00372 """ 00373 if self.warning != value: 00374 self.warning = value 00375 self.paintWarning(value) 00376 self.updatePWarning() 00377 00378