def __init__(self): # Create a component checker self.componentChecker = {} self.configFile = os.path.expanduser('~/rcmanager.xml') # Gui config global dict QtGui.QDialog.__init__(self) self.root = '/opt/robocomp/' self.ui = Ui_Form() self.ui.setupUi(self) self.canvas = GraphView(self.ui.graphTab) self.canvas.setGeometry(0, 0, 531, 581) self.canvas.show() self.canvasTimer = QtCore.QTimer() self.canvasFastTimer = QtCore.QTimer() self.connect(self.canvas, QtCore.SIGNAL("nodeReleased()"), self.setFastState) self.setFastState(True) self.connect(self.canvasTimer, QtCore.SIGNAL("timeout()"), self.graphUpdate) self.connect(self.canvasFastTimer, QtCore.SIGNAL("timeout()"), self.graphFastEnds) if dict['dock'] == 'true': self.changeDock() # Variables needed to switch the state of components when double-clicking over them. self.clickTimes = 0 self.lastClickTime = QtCore.QTime() self.clickNumber = -1 # Component config containter self.compConfig = [] # Init component sets self.back_comps = set() self.requests = set() # Icon and system's tray stuff self.iconOK = QtGui.QIcon( QtGui.QPixmap('/opt/robocomp/share/rcmanager/drawing_red.png')) self.iconFULL = QtGui.QIcon( QtGui.QPixmap('/opt/robocomp/share/rcmanager/drawing_green.png')) self.iconChange1 = QtGui.QIcon( QtGui.QPixmap('/opt/robocomp/share/rcmanager/drawing_right.png')) self.iconChange2 = QtGui.QIcon( QtGui.QPixmap('/opt/robocomp/share/rcmanager/drawing_left.png')) self.setWindowIcon(self.iconOK) self.state = 0 self.doExit = False self.systray = None self.blinkTimer = QtCore.QTimer() self.doDock = False # Set the fixed timeout for component checking self.timer = QtCore.QTimer() self.timer.start(dict['fixed']) self.menu = QtGui.QMenuBar(None) self.ui.verticalLayout_3.insertWidget(0, self.menu) self.menuFile = self.menu.addMenu('File') self.menuSim = self.menu.addMenu('Simulation') self.menuActions = self.menu.addMenu('Actions') self.actionKillAll = self.menuActions.addAction('kill all') self.connect(self.actionKillAll, QtCore.SIGNAL("triggered(bool)"), self.killall) #self.actionRunAll = self.menuActions.addAction('run all') #self.connect(self.actionRunAll, QtCore.SIGNAL("triggered(bool)"), self.runall) self.actionOpen = self.menuFile.addAction('Open') self.connect(self.actionOpen, QtCore.SIGNAL("triggered(bool)"), self.openFile) self.actionSave = self.menuFile.addAction('Save') self.connect(self.actionSave, QtCore.SIGNAL("triggered(bool)"), self.saveFile) self.actionEdit = self.menuFile.addAction('Edit') self.connect(self.actionEdit, QtCore.SIGNAL("triggered(bool)"), self.runEditor) self.actionDock = self.menuFile.addAction('Dock') self.connect(self.actionDock, QtCore.SIGNAL("triggered(bool)"), self.changeDock) self.actionExit = self.menuFile.addAction('Exit') self.connect(self.actionExit, QtCore.SIGNAL("triggered(bool)"), self.forceExit) # Do we want the eye-candy graph simulation? if (dict['active'] == "true"): self.doSimulation = True else: self.doSimulation = False if self.doSimulation == True: self.actionSS = self.menuSim.addAction('Stop') else: self.actionSS = self.menuSim.addAction('Start') # Set connections self.connect(self.ui.checkList, QtCore.SIGNAL("itemClicked(QListWidgetItem *)"), self.selectCheck) self.connect(self.ui.upButton, QtCore.SIGNAL("clicked()"), self.up) self.connect(self.ui.downButton, QtCore.SIGNAL("clicked()"), self.down) self.connect(self.ui.tabWidget, QtCore.SIGNAL("currentChanged(int)"), self.tabChanged) self.connect(self.timer, QtCore.SIGNAL("timeout()"), self.checkAll) self.connect(self.canvas, QtCore.SIGNAL('upRequest()'), self.manageGraphUp) self.connect(self.canvas, QtCore.SIGNAL('downRequest()'), self.manageGraphDown) self.connect(self.canvas, QtCore.SIGNAL('configRequest()'), self.manageGraphConfig) self.connect(self.actionSS, QtCore.SIGNAL("triggered(bool)"), self.sSimulation) # Draw the graph self.canvas.update() # Get settings settings = QtCore.QSettings("RoboComp", "rcmanager") value = settings.value("geometry").toByteArray() if value != None: self.restoreGeometry(value) value = settings.value("page").toInt() if value != None: if value[1] == True: self.ui.tabWidget.setCurrentIndex(value[0]) value = settings.value("docking").toBool() if value != None: if value == True: self.changeDock()
class TheThing(QtGui.QDialog): def __init__(self): # Create a component checker self.componentChecker = {} self.configFile = os.path.expanduser('~/rcmanager.xml') # Gui config global dict QtGui.QDialog.__init__(self) self.root = '/opt/robocomp/' self.ui = Ui_Form() self.ui.setupUi(self) self.canvas = GraphView(self.ui.graphTab) self.canvas.setGeometry(0, 0, 531, 581) self.canvas.show() self.canvasTimer = QtCore.QTimer() self.canvasFastTimer = QtCore.QTimer() self.connect(self.canvas, QtCore.SIGNAL("nodeReleased()"), self.setFastState) self.setFastState(True) self.connect(self.canvasTimer, QtCore.SIGNAL("timeout()"), self.graphUpdate) self.connect(self.canvasFastTimer, QtCore.SIGNAL("timeout()"), self.graphFastEnds) if dict['dock'] == 'true': self.changeDock() # Variables needed to switch the state of components when double-clicking over them. self.clickTimes = 0 self.lastClickTime = QtCore.QTime() self.clickNumber = -1 # Component config containter self.compConfig = [] # Init component sets self.back_comps = set() self.requests = set() # Icon and system's tray stuff self.iconOK = QtGui.QIcon( QtGui.QPixmap('/opt/robocomp/share/rcmanager/drawing_red.png')) self.iconFULL = QtGui.QIcon( QtGui.QPixmap('/opt/robocomp/share/rcmanager/drawing_green.png')) self.iconChange1 = QtGui.QIcon( QtGui.QPixmap('/opt/robocomp/share/rcmanager/drawing_right.png')) self.iconChange2 = QtGui.QIcon( QtGui.QPixmap('/opt/robocomp/share/rcmanager/drawing_left.png')) self.setWindowIcon(self.iconOK) self.state = 0 self.doExit = False self.systray = None self.blinkTimer = QtCore.QTimer() self.doDock = False # Set the fixed timeout for component checking self.timer = QtCore.QTimer() self.timer.start(dict['fixed']) self.menu = QtGui.QMenuBar(None) self.ui.verticalLayout_3.insertWidget(0, self.menu) self.menuFile = self.menu.addMenu('File') self.menuSim = self.menu.addMenu('Simulation') self.menuActions = self.menu.addMenu('Actions') self.actionKillAll = self.menuActions.addAction('kill all') self.connect(self.actionKillAll, QtCore.SIGNAL("triggered(bool)"), self.killall) #self.actionRunAll = self.menuActions.addAction('run all') #self.connect(self.actionRunAll, QtCore.SIGNAL("triggered(bool)"), self.runall) self.actionOpen = self.menuFile.addAction('Open') self.connect(self.actionOpen, QtCore.SIGNAL("triggered(bool)"), self.openFile) self.actionSave = self.menuFile.addAction('Save') self.connect(self.actionSave, QtCore.SIGNAL("triggered(bool)"), self.saveFile) self.actionEdit = self.menuFile.addAction('Edit') self.connect(self.actionEdit, QtCore.SIGNAL("triggered(bool)"), self.runEditor) self.actionDock = self.menuFile.addAction('Dock') self.connect(self.actionDock, QtCore.SIGNAL("triggered(bool)"), self.changeDock) self.actionExit = self.menuFile.addAction('Exit') self.connect(self.actionExit, QtCore.SIGNAL("triggered(bool)"), self.forceExit) # Do we want the eye-candy graph simulation? if (dict['active'] == "true"): self.doSimulation = True else: self.doSimulation = False if self.doSimulation == True: self.actionSS = self.menuSim.addAction('Stop') else: self.actionSS = self.menuSim.addAction('Start') # Set connections self.connect(self.ui.checkList, QtCore.SIGNAL("itemClicked(QListWidgetItem *)"), self.selectCheck) self.connect(self.ui.upButton, QtCore.SIGNAL("clicked()"), self.up) self.connect(self.ui.downButton, QtCore.SIGNAL("clicked()"), self.down) self.connect(self.ui.tabWidget, QtCore.SIGNAL("currentChanged(int)"), self.tabChanged) self.connect(self.timer, QtCore.SIGNAL("timeout()"), self.checkAll) self.connect(self.canvas, QtCore.SIGNAL('upRequest()'), self.manageGraphUp) self.connect(self.canvas, QtCore.SIGNAL('downRequest()'), self.manageGraphDown) self.connect(self.canvas, QtCore.SIGNAL('configRequest()'), self.manageGraphConfig) self.connect(self.actionSS, QtCore.SIGNAL("triggered(bool)"), self.sSimulation) # Draw the graph self.canvas.update() # Get settings settings = QtCore.QSettings("RoboComp", "rcmanager") value = settings.value("geometry").toByteArray() if value != None: self.restoreGeometry(value) value = settings.value("page").toInt() if value != None: if value[1] == True: self.ui.tabWidget.setCurrentIndex(value[0]) value = settings.value("docking").toBool() if value != None: if value == True: self.changeDock() # Select a new rcmanager configuration file def openFile(self, p=None): if p == None: self.configFile = QtGui.QFileDialog.getOpenFileName( self, "Select file", initDir, "*.xml") else: self.configFile = p if len(self.configFile) > 0: if self.canvas.ui != None: self.canvas.ui.close() self.readConfig() else: print 'len(cfgFile) == 0' # Save the current configuration to a new file def saveFile(self): global dict if self.canvas.ui != None: self.canvas.ui.close() s = QtGui.QFileDialog.getSaveFileName(self, "Select output file", os.environ['HOME'], "*.xml") if len(s) > 0: for c1 in self.compConfig: for c2 in self.canvas.compList: if c1.alias == c2.name: c1.x = c2.x c1.y = c2.y c1.r = c2.r rcmanagerConfigSimple.writeConfigToFile(dict, self.compConfig, s) # Dock icon blinking method. def changeDock(self): global dict if self.canvas.ui != None: self.canvas.ui.close() if self.doDock == False: self.systray = QtGui.QSystemTrayIcon(self) self.systray.setIcon(self.iconOK) self.systray.setVisible(True) self.connect( self.systray, QtCore.SIGNAL("activated (QSystemTrayIcon::ActivationReason)"), self.toggle) self.connect(self.blinkTimer, QtCore.SIGNAL("timeout()"), self.changeIcon) self.iconNumber = 0 self.doDock = True dict['dock'] = 'true' self.actionDock.setText('Undock') else: self.systray.deleteLater() self.disconnect(self.blinkTimer, QtCore.SIGNAL("timeout()"), self.changeIcon) self.iconNumber = 0 self.doDock = False dict['dock'] = 'false' self.actionDock.setText('Dock') # Stop graph simulation if its running or vice versa. def sSimulation(self): global dict self.doSimulation = not self.doSimulation if self.doSimulation == False: self.actionSS.setText('Start') if self.fastState == False: self.canvasTimer.start(dict['focustime']) dict['active'] = 'false' else: self.actionSS.setText('Stop') self.setFastState() if self.fastState == False: self.canvasTimer.start(dict['idletime']) dict['active'] = 'true' # When doing simulation calling this method will make the simulation go fast def setFastState(self, fast=True): global dict self.fastState = fast if fast: self.canvasTimer.start(dict['fasttime']) self.canvasFastTimer.start(dict['fastperiod']) else: self.canvasFastTimer.stop() if self.ui.tabWidget.currentIndex( ) == 1 and self.doSimulation == True: self.canvasTimer.start(dict['focustime']) else: self.canvasTimer.start(dict['idletime']) # Opposite of the previous method def graphFastEnds(self): self.setFastState(False) # Run component simulator def runEditor(self): if self.canvas.ui != None: self.canvas.ui.close() self.editor = rcmanagerEditor.rcmanagerEditorWidget() self.editor.setModal(True) self.editor.show() self.editor.readConfig(self.configFile) self.connect(self.editor, QtCore.SIGNAL('finished()'), self.readConfig) # Add the ui-selected component to the requests set by calling the 'up()' method. def manageGraphUp(self): for idx in range(self.ui.checkList.count()): if self.ui.checkList.item(idx).text() == self.canvas.request: self.ui.checkList.setCurrentRow(idx) self.selectCheck() self.up() break # Add the ui-selected component to the down set by calling the 'down()' method. def manageGraphDown(self): for idx in range(self.ui.checkList.count()): if self.ui.checkList.item(idx).text() == self.canvas.request: self.ui.checkList.setCurrentRow(idx) self.selectCheck() self.down() break # Edit a component's configuration def manageGraphConfig(self): for idx in range(self.ui.checkList.count()): if self.ui.checkList.item(idx).text() == self.canvas.request: self.ui.checkList.setCurrentRow(idx) self.selectCheck() self.config() break # Update the UI graph def graphUpdate(self): global dict self.canvas.checkForNewComponents(self) self.canvas.center() if self.doSimulation: self.canvas.step(self) self.canvas.update() # Current tab changed @QtCore.pyqtSignature("int") def tabChanged(self, num): if self.fastState == False: if num == 0: self.canvasTimer.start(dict['idletime']) elif num == 1 and self.doSimulation == True: self.canvasTimer.start(dict['focustime']) # Retuns True if the specified component is up, otherwise returns False def itsUp(self, compNumber): if self.compConfig[compNumber].alias in self.componentChecker: return self.componentChecker[self.compConfig[compNumber]].isalive() return False # Queues the user's request to change the state of a given component, turning it off if it's on and viceversa. def switchComponent(self, compNumber): if self.itsUp(compNumber) == True: self.down() else: self.up() # Queues the user request to turn on a component def up(self): itsconfig = self.compConfig[self.ui.checkList.currentRow()] self.requests = self.requests | set([itsconfig.alias]) self.clearFocus() # Queues the user request to turn off a component def down(self): self.bg_exec(str(self.ui.downEdit.text()), self.ui.wdEdit.text()) self.clearFocus() def killall(self): for info in self.compConfig: self.bg_exec(str(info.compdown), str(info.workingdir)) # Run the configured file editor def config(self): global dict self.bg_exec( self.compConfig[self.ui.checkList.currentRow()].configFile, self.ui.wdEdit.text()) self.clearFocus() # Reads new configuration from file def readConfig(self): self.canvas.initialize() self.ui.checkList.clear() self.compConfig = [] self.back_comps = set() self.requests = set() newList, newDict = rcmanagerConfigSimple.getConfigFromFile( self.configFile) for k, v in newDict.iteritems(): dict[k] = v self.componentChecker.clear() for listItem in newList: item = QtGui.QListWidgetItem() item.setText(listItem.alias) self.ui.checkList.insertItem(0, item) self.compConfig.insert(0, listItem) self.componentChecker[listItem.alias] = ComponentChecker( listItem.endpoint) self.componentChecker[listItem.alias].runrun() self.log('Configuration loaded') n = rcmanagerConfigSimple.unconnectedGroups(newList) if n > 1: msg = 'WARNING: ' + str(n) + ' unconnected component groups' self.log(msg) QtGui.QMessageBox.warning(self, 'Warning', msg) self.setFastState() # Call-back when # def selectCheck(self): # Check if it's a consecutive click notTheLastOneAtTime = 0 if self.clickNumber != self.ui.checkList.currentRow(): notTheLastOneAtTime = 1 if self.lastClickTime.elapsed() > dict['interval']: notTheLastOneAtTime = 1 if notTheLastOneAtTime == 0: # It's not self.clickTimes = self.clickTimes + 1 else: # It is self.clickTimes = 1 self.clickNumber = self.ui.checkList.currentRow() self.lastClickTime = self.lastClickTime.currentTime() # If it's a N-ary click: swap its state if self.clickTimes >= dict['switch']: self.switchComponent(self.clickNumber) # Show information of the last clicked component info = self.compConfig[self.ui.checkList.currentRow()] self.ui.checkEdit.setText(info.endpoint) self.ui.wdEdit.setText(info.workingdir) self.ui.upEdit.setText(info.compup) self.ui.downEdit.setText(info.compdown) self.ui.cfgEdit.setText(info.configFile) def checkAll(self, initial=False): allOk = True workingComponents = set() for numItem in range(0, len(self.compConfig)): ok = True itemConfig = self.compConfig[numItem] item = self.ui.checkList.item(numItem) if (itemConfig.alias in self.componentChecker) and ( self.componentChecker[itemConfig.alias].isalive()): item.setTextColor(QtGui.QColor(0, 255, 0)) workingComponents.add(itemConfig.alias) else: item.setTextColor(QtGui.QColor(255, 0, 0)) allOk = False if workingComponents != self.back_comps: if allOk == False: self.blinkTimer.stop() self.blinkTimer.start(dict['blink']) for comp in workingComponents.difference(self.back_comps): self.log('Now \"' + comp + '\" is up.') for comp in self.back_comps.difference(workingComponents): self.log('Now \"' + comp + '\" is down.') if self.wantsDocking(): if allOk and len(self.compConfig) > 0: self.systray.setIcon(self.iconFULL) elif workingComponents != self.back_comps: self.systray.setIcon(self.iconOK) self.back_comps = workingComponents.copy() self.upRequests() def upRequests(self): future_requests = self.requests for alias in self.requests: itsconfig = self.getConfigByAlias(alias) unavailableDependences = [] for dep in itsconfig.dependences: if (not dep in self.componentChecker) or ( not self.componentChecker[dep].isalive()): unavailableDependences.append(dep) if len(unavailableDependences) == 0: print 'rcmanager:', alias, 'is now ready to run.' self.upConfig(itsconfig) future_requests = future_requests - set([alias]) else: print 'rcmanager:', alias, 'has unavailable dependences:', unavailableDependences future_requests = future_requests | set(unavailableDependences) self.requests = future_requests # Tries to execute a component def upConfig(self, conf): self.bg_exec(conf.compup, conf.workingdir) # Executes a command in the background def bg_exec(self, command, workDir): # Get command argument list argument_list = command.split(' ') # Set program as argument_list[0] program = argument_list[0] # Set args as argument_list[1, -1] args = argument_list[1:] currentWorkDir = os.getcwd() os.chdir(workDir) proc = QtCore.QProcess() print '\nQProcess::startDetached( ' + program + ' , ' + str( args) + ' ) @ ' + os.getcwd() + '\n' proc.startDetached(program, args) os.chdir(currentWorkDir) # # Changes the icon of the program properly, skipping if docking is not active def changeIcon(self): if self.isActiveWindow() == True: self.blinkTimer.stop() self.systray.setIcon(self.iconOK) else: if self.iconNumber == 0: self.systray.setIcon(self.iconChange1) self.iconNumber = 1 elif self.iconNumber == 1: self.systray.setIcon(self.iconChange2) self.iconNumber = 2 else: self.systray.setIcon(self.iconChange1) self.iconNumber = 1 # # (Un)hide the main window def toggle(self): if self.isVisible(): self.hide() else: self.show() # # Manages close events def closeEvent(self, closeevent): settings = QtCore.QSettings("RoboComp", "rcmanager") g = self.saveGeometry() settings.setValue("geometry", QtCore.QVariant(g)) settings.setValue("page", QtCore.QVariant(self.ui.tabWidget.currentIndex())) settings.setValue("docking", QtCore.QVariant(self.wantsDocking())) if self.doExit != 1 and self.doDock == True: closeevent.ignore() self.hide() elif self.wantsDocking(): closeevent.accept() for key, checker in self.componentChecker.iteritems(): checker.stop() # else: # closeevent.accept() # self.forceExit() # sys.exit(0) # # Forces the program to exit def forceExit(self): self.doExit = 1 self.close() # # Clears the interface selection when the user presses 'Esc' def keyPressEvent(self, keyevent): if keyevent.key() == 16777216: #0x01000000 self.ui.checkList.clearSelection() if self.canvas.ui != None: self.canvas.ui.close() # # Interface stuff: def uiChange(self): self.ui.checkList.setCurrentRow(0) self.selectCheck() self.clearFocus() def clearFocus(self): self.ui.checkList.clearSelection() def log(self, text): self.ui.outputText.append(' * ' + QtCore.QTime.currentTime().toString() + ': ' + text) def getConfigByAlias(self, alias): for config in self.compConfig: if config.alias == alias: return config return None # # Return 1 if docking is selected, 0 otherwise. def wantsDocking(self): if self.doDock == True: return 1 else: return 0 def resizeEvent(self, e): old = e.oldSize() new = e.size() inc = new - old if (inc.width != 0 or inc.height != 0): self.canvas.resize(self.canvas.size() + inc) e.accept()