Ejemplo n.º 1
0
    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()
Ejemplo n.º 2
0
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()