コード例 #1
0
ファイル: visualstates.py プロジェクト: reysam93/JdeRobot
    def createTreeView(self):
        dockWidget = QDockWidget()
        dockWidget.setAllowedAreas(Qt.LeftDockWidgetArea)
        dockWidget.setFeatures(QDockWidget.NoDockWidgetFeatures)
        dockWidget.setTitleBarWidget(QWidget())
        self.treeView = QTreeView()
        self.treeView.clicked.connect(self.treeItemClicked)
        self.treeModel = TreeModel()
        self.treeView.setModel(self.treeModel)

        self.logo = QLabel()
        logoPixmap = QPixmap(CMAKE_INSTALL_PREFIX + '/share/jderobot/resources/jderobot.png')
        self.logo.setPixmap(logoPixmap)

        self.upButton = QPushButton()
        self.upButton.setText('Up')
        self.upButton.clicked.connect(self.upButtonClicked)

        leftContainer = QWidget()
        leftLayout = QVBoxLayout()
        leftLayout.addWidget(self.treeView)
        leftLayout.addWidget(self.upButton)
        leftLayout.addWidget(self.logo)
        leftContainer.setLayout(leftLayout)

        dockWidget.setWidget(leftContainer)
        self.addDockWidget(Qt.LeftDockWidgetArea, dockWidget)
コード例 #2
0
    def __init__(self, parent=None):
        super().__init__(parent)

        # initialize class attributes
        self._INPUTS_FIXED_WIDTH = 180
        self._BUTTON_MIN_WIDTH = 80
        self._OXYGEN_PATH_32 = os.path.join("resources", "icons", "oxygen", "32")

        # locale and language settings
        self.language = self.locale().name()[:2]
        self.qtTl = QTranslator()
        self.appTl = QTranslator()
        self.switchTranslator(self.qtTl, "qtbase", self.language)
        self.switchTranslator(self.appTl, "wuchshuellenrechner", self.language)

        # TODO(th)
        self.model = TreeModel()

        # setup gui
        self.setMinimumSize(1200, 760)

        self.createActions()
        self.createMainMenu()

        # plot widget
        self.plotWidget = VariantPlotView()
        self.plotWidget.setModel(self.model)

        # create vertical splitter
        splitter = QSplitter(Qt.Vertical)
        splitter.setContentsMargins(11, 11, 11, 11)
        splitter.addWidget(self.createEditBox())
        splitter.addWidget(self.plotWidget)

        self.setCentralWidget(splitter)

        self.dataWidget.setModel(self.model)

        selectionModel = QItemSelectionModel(self.model)
        self.dataWidget.setSelectionModel(selectionModel)
        self.plotWidget.setSelectionModel(selectionModel)

        self.retranslateUi()


        self.model.dataChanged.connect(self.updateInputs)
        self.model.itemsInserted.connect(self.taxInput.setDisabled)
        self.model.allItemsRemoved.connect(self.taxInput.setEnabled)
        self.operationInput.textChanged.connect(self.updateOperation)
        self.districtInput.textChanged.connect(self.updateDistrict)
        self.managerInput.textChanged.connect(self.updateManager)
        self.locationInput.textChanged.connect(self.updateLocation)
        self.taxInput.stateChanged.connect(self.updateTax)
コード例 #3
0
ファイル: runtimegui.py プロジェクト: reysam93/JdeRobot
class RunTimeGui(QMainWindow):

    activeStateChanged = pyqtSignal(int)
    runningStateChanged = pyqtSignal(int)
    loadFromRoot = pyqtSignal(int)

    def __init__(self, parent=None):
        super(QMainWindow, self).__init__()

        self.setWindowTitle("VisualStates RunTime GUI")

        self.rootState = None

        # create status bar
        self.statusBar()

        self.createTreeView()
        self.createStateCanvas()

        self.setGeometry(0, 0, 800, 600)
        self.show()

        self.states = {}
        self.transitions = {}

        self.activeState = None

        self.activeStateChanged.connect(self.activeStateChangedHandle)
        self.runningStateChanged.connect(self.runningStateChangedHandle)
        self.loadFromRoot.connect(self.loadFromRootHandle)

        self.memory = None
        self.ipcThread = None

    def createTreeView(self):
        dockWidget = QDockWidget()
        dockWidget.setAllowedAreas(Qt.LeftDockWidgetArea)
        dockWidget.setFeatures(QDockWidget.NoDockWidgetFeatures)
        dockWidget.setTitleBarWidget(QWidget())
        self.treeView = QTreeView()
        self.treeView.clicked.connect(self.treeItemClicked)
        self.treeModel = TreeModel()
        self.treeView.setModel(self.treeModel)

        self.logo = QLabel()
        logoPixmap = QPixmap(CMAKE_INSTALL_PREFIX + '/share/jderobot/resources/jderobot.png')
        self.logo.setPixmap(logoPixmap)

        self.upButton = QPushButton()
        self.upButton.setText('Up')
        self.upButton.clicked.connect(self.upButtonClicked)

        leftContainer = QWidget()
        leftLayout = QVBoxLayout()
        leftLayout.addWidget(self.treeView)
        leftLayout.addWidget(self.upButton)
        leftLayout.addWidget(self.logo)
        leftContainer.setLayout(leftLayout)

        dockWidget.setWidget(leftContainer)
        self.addDockWidget(Qt.LeftDockWidgetArea, dockWidget)

    def createStateCanvas(self):
        self.stateCanvas = QGraphicsView()
        self.scene = QGraphicsScene()
        self.scene.setSceneRect(0, 0, 2000, 2000)

        self.setCentralWidget(self.stateCanvas)
        self.stateCanvas.setScene(self.scene)
        self.stateCanvas.setRenderHint(QPainter.Antialiasing)


    def addState(self, id, name, initial, x, y, parentId):
        if parentId is not None:
            self.states[id] = State(id, name, initial, self.states[parentId])
            self.states[parentId].addChild(self.states[id])
            parentItem = self.treeModel.getByDataId(parentId)
            # print('parent:' + str(parentItem))
        else:
            self.states[id] = State(id, name, initial, None)
        if id == 0:
            self.rootState = self.states[id]

        self.states[id].setPos(x, y)

    def addTransition(self, id, name, originId, destinationId, x, y):
        self.transitions[id] = Transition(id, name, self.states[originId], self.states[destinationId])
        self.transitions[id].setPos(x, y)

    def emitRunningStateById(self, id):
        # print('emit running state:' + str(id))
        self.runningStateChanged.emit(id)

    def runningStateChangedHandle(self, id):
        # print('running state:' + str(id))
        if id not in self.states:
            return

        runningState = self.states[id]

        parentId = None
        if runningState.parent is not None:
            for child in runningState.parent.getChildren():
                child.setRunning(False)

            runningState.setRunning(True)
            parentId = runningState.parent.id

        self.treeModel.setAllBackgroundByParentId(Qt.white, parentId)
        self.treeModel.setBackgroundById(runningState.id, Qt.green)

    def emitActiveStateById(self, id):
        self.activeStateChanged.emit(id)

    def activeStateChangedHandle(self, id):
        if self.activeState is not None:
            for child in self.activeState.getChildren():
                child.resetGraphicsItem()
                for tran in child.getOriginTransitions():
                    tran.resetGraphicsItem()

        self.activeState = self.states[id]
        # print('set active state:' + str(id))
        self.scene.clear()
        for childState in self.activeState.getChildren():
            # print('add child to scene:' + str(childState.id))
            qitem = childState.getGraphicsItem()
            qitem.setAcceptHoverEvents(False)
            qitem.setFlag(QGraphicsItem.ItemIsMovable, False)
            qitem.doubleClicked.connect(self.stateDoubleClicked)
            self.setAcceptDrops(False)
            self.scene.addItem(qitem)
            for tran in childState.getOriginTransitions():
                # print('add transition:' + str(tran.id))
                qitem = tran.getGraphicsItem()
                qitem.disableInteraction()
                self.scene.addItem(qitem)

    def emitLoadFromRoot(self):
        self.loadFromRoot.emit(0)

    def loadFromRootHandle(self, id):
        self.treeModel.loadFromRoot(self.states[id])

    def stateDoubleClicked(self, stateItem):
        if len(stateItem.stateData.getChildren()) > 0:
            self.emitActiveStateById(stateItem.stateData.id)

    def upButtonClicked(self):
        if self.activeState is not None:
            if self.activeState.parent is not None:
                self.emitActiveStateById(self.activeState.parent.id)

    def getStateById(self,state, id):
        if state.id == id:
            return state
        else:
            result = None
            for child in state.getChildren():
                result = self.getStateById(child, id)
                if result is not None:
                    return result
            return result

    def treeItemClicked(self, index):
        # print('clicked item.id:' + str(index.internalPointer().id))
        pass

    def getStateList(self, state, stateList):
        if len(state.getChildren()) > 0:
            stateList.append(state)

        for s in state.getChildren():
            self.getStateList(s, stateList)

    def loopIPC(self):
        while True:
            msg = self.getIPCMessage()
            if msg is not None:
                # print('msg received:' + msg)
                methodName = msg.split(' ')[0]
                id = int(msg.split(' ')[1])
                if methodName == 'emitRunningStateById':
                    self.emitRunningStateById(id)
                else:
                    print('unknown method name')

            time.sleep(1.0/1000)

    def activateIPC(self):
        try:
            self.memory = sysv_ipc.SharedMemory(123456, sysv_ipc.IPC_CREX)
        except:
            # if memory exists just open shared memory
            self.memory = sysv_ipc.SharedMemory(123456)

        self.ipcThread = Thread(target=self.loopIPC)
        self.ipcThread.start()

    def getIPCMessage(self):
        if self.memory is not None:
            data = self.memory.read().decode()
            if data[0] != '0':
                self.memory.write('0'.encode())
                i = data.find('\0')
                if i != -1:
                    data = data[:i]
                return data

        return None
コード例 #4
0
class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)

        # initialize class attributes
        self._INPUTS_FIXED_WIDTH = 180
        self._BUTTON_MIN_WIDTH = 80
        self._OXYGEN_PATH_32 = os.path.join("resources", "icons", "oxygen", "32")

        # locale and language settings
        self.language = self.locale().name()[:2]
        self.qtTl = QTranslator()
        self.appTl = QTranslator()
        self.switchTranslator(self.qtTl, "qtbase", self.language)
        self.switchTranslator(self.appTl, "wuchshuellenrechner", self.language)

        # TODO(th)
        self.model = TreeModel()

        # setup gui
        self.setMinimumSize(1200, 760)

        self.createActions()
        self.createMainMenu()

        # plot widget
        self.plotWidget = VariantPlotView()
        self.plotWidget.setModel(self.model)

        # create vertical splitter
        splitter = QSplitter(Qt.Vertical)
        splitter.setContentsMargins(11, 11, 11, 11)
        splitter.addWidget(self.createEditBox())
        splitter.addWidget(self.plotWidget)

        self.setCentralWidget(splitter)

        self.dataWidget.setModel(self.model)

        selectionModel = QItemSelectionModel(self.model)
        self.dataWidget.setSelectionModel(selectionModel)
        self.plotWidget.setSelectionModel(selectionModel)

        self.retranslateUi()


        self.model.dataChanged.connect(self.updateInputs)
        self.model.itemsInserted.connect(self.taxInput.setDisabled)
        self.model.allItemsRemoved.connect(self.taxInput.setEnabled)
        self.operationInput.textChanged.connect(self.updateOperation)
        self.districtInput.textChanged.connect(self.updateDistrict)
        self.managerInput.textChanged.connect(self.updateManager)
        self.locationInput.textChanged.connect(self.updateLocation)
        self.taxInput.stateChanged.connect(self.updateTax)

    def updateOperation(self, value):
        self.model.setProjectData("operation", value)

    def updateDistrict(self, value):
        self.model.setProjectData("district", value)

    def updateManager(self, value):
        self.model.setProjectData("manager", value)

    def updateLocation(self, value):
        self.model.setProjectData("location", value)

    def updateTax(self):
        self.model.setProjectData("tax", self.taxInput.isChecked())
        self.dataWidget.tax = self.taxInput.isChecked()

    def updateInputs(self):
        self.operationInput.setText(self.model.projectData("operation"))
        self.districtInput.setText(self.model.projectData("district"))
        self.managerInput.setText(self.model.projectData("manager"))
        self.locationInput.setText(self.model.projectData("location"))

        self.taxInput.setChecked(self.model.projectData("tax"))

    def loadLanguage(self, language):
        if not self.language == language:
            self.language = language

            locale = QLocale(language)
            QLocale.setDefault(locale)

            self.switchTranslator(self.qtTl, "qtbase", language)
            self.switchTranslator(self.appTl, "wuchshuellenrechner", language)

            # update gui
            self.retranslateUi()
            self.dataWidget.retranslateUi()

    def switchTranslator(self, translator, filename, language):
        app = QApplication.instance()

        # remove the old translator and
        # try to load a new language file
        app.removeTranslator(translator)
        if translator.load(QLocale(), filename, "_", "language"):
            app.installTranslator(translator)

    def setTaxEnabled(self, enable):
        # enable buttons and the view element
        self.removeButton.setEnabled(enable)
        self.modifyButton.setEnabled(enable)
        self.view.setEnabled(enable)

    def setDisabled(self, disable):
        # internaly call the setEnabled function
        # therefore negate the boolean value
        self.setEnabled(not disable)

    def aboutAction(self):
        aboutDialog = AboutDialog()
        aboutDialog.exec()

    def clear(self):
        # first clear the model
        self.model.clear()

        # update fields with model's default values
        self.operationInput.setText(self.model.projectData("operation"))
        self.districtInput.setText(self.model.projectData("district"))
        self.managerInput.setText(self.model.projectData("manager"))
        self.locationInput.setText(self.model.projectData("location"))

        self.taxInput.setEnabled(True)
        self.taxInput.setChecked(self.model.projectData("tax"))

        # reset the tree view
        self.dataWidget.clear()

        # reset the chart and result view
        # actually this is necassary
        self.plotWidget.clear()

    def closeAction(self):
        if self.model.changed:
            question = QMessageBox()
            question.setIcon(QMessageBox.Question)
            question.setWindowTitle("Berechnung speichern? - Wuchshüllenrechner")
            question.setText("Möchten Sie die Änderungen an dieser Berechnung speichern?")
            question.setInformativeText("Die Änderungen gehen verloren, wenn Sie nicht speichern.")
            question.setStandardButtons(QMessageBox.Save|QMessageBox.Discard|QMessageBox.Cancel)
            question.setDefaultButton(QMessageBox.Save)
            reply = question.exec()

            if not reply == QMessageBox.Cancel:
                if reply == QMessageBox.Save:
                    if self.saveAction():
                        self.close()
                else:
                    self.close()
        else:
            self.close()

    def newAction(self):
        if self.model.changed:
            question = QMessageBox()
            question.setIcon(QMessageBox.Question)
            question.setWindowTitle("Berechnung speichern? - Wuchshüllenrechner")
            question.setText("Möchten Sie die Änderungen an dieser Berechnung speichern?")
            question.setInformativeText("Die Änderungen gehen verloren, wenn Sie nicht speichern.")
            question.setStandardButtons(QMessageBox.Save|QMessageBox.Discard|QMessageBox.Cancel)
            question.setDefaultButton(QMessageBox.Save)
            reply = question.exec()

            if not reply == QMessageBox.Cancel:
                if reply == QMessageBox.Save:
                    if self.saveAction():
                        # clear all
                        self.clear()
                else:
                    # clear all
                    self.clear()

    def checkSaveState(self):
        if self.model.changed:
            question = QMessageBox(self)
            question.setWindowModality(Qt.WindowModal)  # check for mac only
            question.setIcon(QMessageBox.Warning)
            question.setStandardButtons(QMessageBox.Save|QMessageBox.Discard|QMessageBox.Cancel)
            question.setDefaultButton(QMessageBox.Save)
            question.setWindowTitle(QApplication.translate("MainWindow", "Wuchshüllenrechner"))
            question.setText("<b>" + QApplication.translate("MainWindow",
                    "Do you want to save the changes you made<br>"
                    "to the current calculation?") + "</b>")
            question.setInformativeText(QApplication.translate("MainWindow",
                    "Your changes will be lost if you don't save them."))

            reply = question.exec()
            if reply == QMessageBox.Save:
                if self.saveAction():
                    #self.model.clear()
                    self.clear()
                    return True
                else:
                    return False
            elif reply == QMessageBox.Discard:
                #self.model.clear()
                self.clear()
                return True
            else:
                return False

        # always clear
        self.clear()

        return True

    def loadExample(self, example=""):
        # create the path
        exampleFile = os.path.join("examples", example.strip() + ".xml")

         # if all is save, open the example file
        if self.checkSaveState():
            self.model.readFile(exampleFile)

    def mapleAction(self):
        self.loadExample("great_maple")

    def douglasAction(self):
        self.loadExample("douglas_fir")

    def openAction(self):
        # first check save state of the current calculation
        if self.checkSaveState():
            dialog = QFileDialog(self)
            dialog.setWindowModality(Qt.WindowModal)    # check for mac only
            dialog.setWindowTitle(QApplication.translate("MainWindow", "Open Calculation"))
            dialog.setDirectory(os.path.expanduser("~"))
            dialog.setNameFilter(QApplication.translate("MainWindow",
                    "XML files (*.xml);;All Files (*)"))

            dialog.exec()
            filename = dialog.selectedFiles()
            if filename:
                self.model.readFile(filename.pop())

    def saveAction(self):
        if self.model.file:
            return self.model.saveFile()
        else:
            return self.saveAsAction()

    def saveAsAction(self):
        dialog = QFileDialog(self)
        dialog.setWindowModality(Qt.WindowModal)    # check for mac only
        dialog.setAcceptMode(QFileDialog.AcceptSave)
        dialog.setWindowTitle(QApplication.translate("MainWindow", "Save Calculation"))
        dialog.setDirectory(os.path.expanduser("~"))
        dialog.setNameFilter(QApplication.translate("MainWindow",
                "XML files (*.xml);;All Files (*)"))

        dialog.exec()
        filename = dialog.selectedFiles()
        if filename:
            self.model.saveFile(filename.pop())
            return True
        else:
            return False

    def exportAction(self):
        dialog = QFileDialog(self)
        dialog.setWindowModality(Qt.WindowModal)    # check for mac only
        dialog.setAcceptMode(QFileDialog.AcceptSave)
        dialog.setWindowTitle(QApplication.translate("MainWindow", "Export Calculation"))
        dialog.setDirectory(os.path.expanduser("~"))
        dialog.setNameFilter(QApplication.translate("MainWindow",
                "PNG files (*.png);;JPG files (*.jpg);;TIFF files (*.tif)"))

        if dialog.exec():
            filename = dialog.selectedFiles()
            self.plotWidget.plotWidget.plotWidget.export(filename.pop())

    def helpAction(self):
        # create the documentation path with
        # the current locale settings
        docFile = os.path.join("doc", "documentation_" + self.language + ".pdf")

        # on every platfrom a different
        # start operation is needed
        if sys.platform == "win32":
            os.startfile(docFile)
        elif sys.platform == "darwin":
            subprocess.call(("open", docFile))
        elif sys.platform.startswith("linux"):
            subprocess.call(("xdg-open", docFile))

    def scientificAction(self):
        scientificDialog = ScientificBasisDialog()
        scientificDialog.exec()

    def germanAction(self):
        # update language menu
        self.languageEnglish.setChecked(False)
        self.languageGerman.setChecked(True)

        # update gui
        self.loadLanguage("de")

    def englishAction(self):
        # update language menu
        self.languageGerman.setChecked(False)
        self.languageEnglish.setChecked(True)

        # update gui
        self.loadLanguage("en")

    def createActions(self):
        # all actions for the calculation menu
        # create the new calculation action
        self.calculationNew = QAction(self, icon=QIcon(os.path.join(self._OXYGEN_PATH_32, "document-new.png")),
                shortcut=QKeySequence.New, triggered=self.newAction)

        # create the open calculation action
        self.calculationOpen = QAction(self, icon=QIcon(os.path.join(self._OXYGEN_PATH_32, "document-open.png")),
                shortcut=QKeySequence.Open, triggered=self.openAction)

        # create the open calculation example actions
        # for great maple and douglas fir
        self.examplesMaple = QAction(self, triggered=self.mapleAction)
        self.examplesDouglas = QAction(self, triggered=self.douglasAction)

        # create the save calculation action
        self.calculationSave = QAction(self, icon=QIcon(os.path.join(self._OXYGEN_PATH_32, "document-save.png")),
                shortcut=QKeySequence.Save, triggered=self.saveAction)

        # create the save as action
        self.calculationSaveAs = QAction(self, icon=QIcon(os.path.join(self._OXYGEN_PATH_32, "document-save-as.png")),
                shortcut=QKeySequence.SaveAs, triggered=self.saveAsAction)

        # create the print calculation action
        #self.calculationPrint = QAction(self, icon=QIcon(os.path.join(self._OXYGEN_PATH_32, "document-print.png")),
        #        shortcut=QKeySequence.Print, triggered=self.printAction)

        # create the export calculation action
        self.calculationExport = QAction(self, icon=QIcon(os.path.join(self._OXYGEN_PATH_32, "document-export.png")),
                shortcut=QKeySequence(Qt.CTRL + Qt.Key_E), triggered=self.exportAction)

        # create the quit calculation action
        self.calculationQuit = QAction(self, icon=QIcon(os.path.join(self._OXYGEN_PATH_32, "application-exit.png")),
                shortcut=QKeySequence.Quit, triggered=self.closeAction)

        # all actions for the language menu
        # create the german and the english language actions
        self.languageGerman = QAction(self, checkable=True, triggered=self.germanAction)
        self.languageEnglish = QAction(self, checkable=True, triggered=self.englishAction)

        # update the language menu
        if self.language == "de":
            self.languageGerman.setChecked(True)
        elif self.language == "en":
            self.languageEnglish.setChecked(True)

        # create the help contents action
        self.helpContents = QAction(self, icon=QIcon(os.path.join(self._OXYGEN_PATH_32, "help-contents.png")),
                triggered=self.helpAction)

        # create the scientific basis action
        self.scientificBasis = QAction(self, icon=QIcon(os.path.join(self._OXYGEN_PATH_32, "applications-science.png")),
                triggered=self.scientificAction)

        # create the help about action
        self.helpAbout = QAction(self, icon=QIcon(os.path.join(self._OXYGEN_PATH_32, "dialog-information.png")),
                triggered=self.aboutAction)

    def createMainMenu(self):
        # create main menu bar
        self.menu = self.menuBar()

        # create file menu
        self.calculationMenu = QMenu(self)
        self.calculationMenu.addAction(self.calculationNew)
        self.calculationMenu.addAction(self.calculationOpen)

        self.examplesMenu = QMenu(self, icon=QIcon(os.path.join(self._OXYGEN_PATH_32, "folder-documents.png")))
        self.examplesMenu.addAction(self.examplesMaple)
        self.examplesMenu.addAction(self.examplesDouglas)
        self.calculationMenu.addMenu(self.examplesMenu)
        self.calculationMenu.addSeparator()

        self.calculationMenu.addAction(self.calculationSave)
        self.calculationMenu.addAction(self.calculationSaveAs)
        self.calculationMenu.addAction(self.calculationExport)
        self.calculationMenu.addSeparator()

        #self.calculationMenu.addAction(self.calculationPrint)
        #self.calculationMenu.addSeparator()

        self.calculationMenu.addAction(self.calculationQuit)

        self.menu.addMenu(self.calculationMenu)

        # create language menu
        self.languageMenu = QMenu(self)
        self.languageMenu.addAction(self.languageGerman)
        self.languageMenu.addAction(self.languageEnglish)
        self.menu.addMenu(self.languageMenu)

        # create help menu
        self.helpMenu = QMenu(self)
        self.helpMenu.addAction(self.helpContents)
        self.helpMenu.addAction(self.scientificBasis)
        self.helpMenu.addSeparator()
        self.helpMenu.addAction(self.helpAbout)
        self.menu.addMenu(self.helpMenu)

    def createEditBox(self):
        # create group box
        self.editBox = QGroupBox()
        self.editBox.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum)
        gridLayout = QGridLayout(self.editBox)

        # create input fields
        self.operationInput = QLineEdit(self.model.projectData("operation"))
        self.operationInput.setFixedWidth(self._INPUTS_FIXED_WIDTH)
        self.operationInput.setClearButtonEnabled(True)
        self.operationLabel = QLabel()
        self.operationLabel.setBuddy(self.operationInput)
        gridLayout.addWidget(self.operationLabel, 0, 0)
        gridLayout.addWidget(self.operationInput, 0, 1)

        self.districtInput = QLineEdit(self.model.projectData("district"))
        self.districtInput.setFixedWidth(self._INPUTS_FIXED_WIDTH)
        self.districtInput.setClearButtonEnabled(True)
        self.districtLabel = QLabel()
        self.districtLabel.setBuddy(self.districtInput)
        gridLayout.addWidget(self.districtLabel, 0, 2)
        gridLayout.addWidget(self.districtInput, 0, 3)

        self.managerInput = QLineEdit(self.model.projectData("manager"))
        self.managerInput.setFixedWidth(self._INPUTS_FIXED_WIDTH)
        self.managerInput.setClearButtonEnabled(True)
        self.managerLabel = QLabel()
        self.managerLabel.setBuddy(self.managerInput)
        gridLayout.addWidget(self.managerLabel, 1, 0)
        gridLayout.addWidget(self.managerInput, 1, 1)

        self.locationInput = QLineEdit(self.model.projectData("location"))
        self.locationInput.setFixedWidth(self._INPUTS_FIXED_WIDTH)
        self.locationInput.setClearButtonEnabled(True)
        self.locationLabel = QLabel()
        self.locationLabel.setBuddy(self.locationInput)
        gridLayout.addWidget(self.locationLabel, 1, 2)
        gridLayout.addWidget(self.locationInput, 1, 3)

        lineFrame = QFrame(frameShadow=QFrame.Sunken, frameShape=QFrame.VLine)
        gridLayout.addWidget(lineFrame, 0, 4, 2, 1)

        self.taxInput = QCheckBox()
        self.taxInput.setChecked(self.model.projectData("tax"))
        self.taxLabel = QLabel()
        self.taxLabel.setBuddy(self.taxInput)
        self.taxHint = ToolTipLabel()
        gridLayout.addWidget(self.taxLabel, 0, 5)
        gridLayout.addWidget(self.taxInput, 0, 6)
        gridLayout.addWidget(self.taxHint, 0, 7, Qt.AlignRight)
        gridLayout.setColumnMinimumWidth(7, 40)

        rightSpacer = QSpacerItem(20, 0, QSizePolicy.Expanding, QSizePolicy.Fixed)
        gridLayout.addItem(rightSpacer, 0, 8, 2, 1)

        self.dataWidget = EnhancedTreeWidget()
        gridLayout.addWidget(self.dataWidget, 2, 0, 1, 9)

        return self.editBox

    def retranslateUi(self):
        # main window title
        self.setWindowTitle(QApplication.translate("MainWindow", "Wuchshüllenrechner"))     # Wuchshüllenrechner

        # all menu actions
        # first the calculation menu
        self.calculationMenu.setTitle(QApplication.translate("MainWindow", "&Calculation"))     # Kalkulation
        self.calculationNew.setText(QApplication.translate("MainWindow", "&New"))               # &Neu
        self.calculationOpen.setText(QApplication.translate("MainWindow", "&Open"))             # Ö&ffnen
        self.calculationSave.setText(QApplication.translate("MainWindow", "&Save"))             # &Speichern
        self.calculationSaveAs.setText(QApplication.translate("MainWindow", "&Save as"))        # &Speichern unter
        #self.calculationPrint.setText(QApplication.translate("MainWindow", "&Print"))           # &Drucken
        self.calculationExport.setText(QApplication.translate("MainWindow", "&Export"))         # &Exportieren
        self.calculationQuit.setText(QApplication.translate("MainWindow", "E&xit"))             # &Beenden

        # now the examples menu
        self.examplesMenu.setTitle(QApplication.translate("MainWindow", "E&xamples"))           # &Beispiele
        self.examplesMaple.setText(QApplication.translate("MainWindow",
                "&Calculation example for great &maple"))                                       # Berechnungsbeispiel für Berg-&Ahorn
        self.examplesDouglas.setText(QApplication.translate("MainWindow",
                "&Calculation example for &douglas fir"))                                       # Berechnungsbeispiel für Küsten-Douglasie

        # the language menu
        self.languageMenu.setTitle(QApplication.translate("MainWindow", "&Language"))           # &Sprache
        self.languageGerman.setText(QApplication.translate("MainWindow", "&German"))            # &Deutsch
        self.languageEnglish.setText(QApplication.translate("MainWindow", "&English"))          # &Englisch

        # the help menu
        self.helpMenu.setTitle(QApplication.translate("MainWindow", "&Help"))                   # &Hilfe
        self.helpContents.setText(QApplication.translate("MainWindow", "Help &Contents"))       # &Hilfe anzeigen
        self.scientificBasis.setText(QApplication.translate("MainWindow", "Specialist &articles")) # &Fachbeiträge
        self.helpAbout.setText(QApplication.translate("MainWindow",
                "&About Wuchshüllenrechner"))                                                   # Über &Wuchshüllenrechner

        # the edit box for data collection
        self.editBox.setTitle(QApplication.translate("MainWindow", "Data collection"))          # Datenerfassung
        self.operationLabel.setText(QApplication.translate("MainWindow",
                "Forestry &operation") + ":")                                                   # Forst&betrieb
        self.districtLabel.setText(QApplication.translate("MainWindow",
                "Forest &district") + ":")                                                      # Forst&revier
        self.managerLabel.setText(QApplication.translate("MainWindow",
                "&District manager") + ":")                                                     # &Revierleiter
        self.locationLabel.setText(QApplication.translate("MainWindow",
                "&Location") + ":")                                                             # &Waldort
        self.taxLabel.setText(QApplication.translate("MainWindow",
                "&Sales tax") + ":")                                                            # Mehrwert&steuer
        self.taxHint.setToolTip(QApplication.translate("MainWindow",
                "Wirkt sich auf Vorgabewerte aus und kann nach\nAnlegen einer "
                "Variante nicht geändert werden."))

        # update the data widget
        self.dataWidget.retranslateUi()

        # update the chart and result view
        self.plotWidget.retranslateUi()
コード例 #5
0
ファイル: runtimegui.py プロジェクト: shamb0/RoboticsAcademy
class RunTimeGui(QMainWindow):

    activeStateChanged = pyqtSignal(int)
    runningStateChanged = pyqtSignal(int)
    loadFromRoot = pyqtSignal(int)

    def __init__(self, parent=None):
        super(QMainWindow, self).__init__()

        self.setWindowTitle("VisualStates RunTime GUI")

        self.rootState = None

        # create status bar
        self.statusBar()

        self.createTreeView()
        self.createStateCanvas()

        self.setGeometry(0, 0, 800, 600)
        self.show()

        self.states = {}
        self.transitions = {}

        self.activeState = None

        self.activeStateChanged.connect(self.activeStateChangedHandle)
        self.runningStateChanged.connect(self.runningStateChangedHandle)
        self.loadFromRoot.connect(self.loadFromRootHandle)

        self.memory = None
        self.ipcThread = None
        self.semaphore = None

    def createTreeView(self):
        dockWidget = QDockWidget()
        dockWidget.setAllowedAreas(Qt.LeftDockWidgetArea)
        dockWidget.setFeatures(QDockWidget.NoDockWidgetFeatures)
        dockWidget.setTitleBarWidget(QWidget())
        self.treeView = QTreeView()
        self.treeView.clicked.connect(self.treeItemClicked)
        self.treeModel = TreeModel()
        self.treeView.setModel(self.treeModel)

        self.logo = QLabel()
        logoPixmap = QPixmap(CMAKE_INSTALL_PREFIX +
                             '/share/jderobot/resources/jderobot.png')
        self.logo.setPixmap(logoPixmap)

        self.upButton = QPushButton()
        self.upButton.setText('Up')
        self.upButton.clicked.connect(self.upButtonClicked)

        leftContainer = QWidget()
        leftLayout = QVBoxLayout()
        leftLayout.addWidget(self.treeView)
        leftLayout.addWidget(self.upButton)
        leftLayout.addWidget(self.logo)
        leftContainer.setLayout(leftLayout)

        dockWidget.setWidget(leftContainer)
        self.addDockWidget(Qt.LeftDockWidgetArea, dockWidget)

    def createStateCanvas(self):
        self.stateCanvas = QGraphicsView()
        self.scene = QGraphicsScene()
        self.scene.setSceneRect(0, 0, 2000, 2000)

        self.setCentralWidget(self.stateCanvas)
        self.stateCanvas.setScene(self.scene)
        self.stateCanvas.setRenderHint(QPainter.Antialiasing)

    def addState(self, id, name, initial, x, y, parentId):
        if parentId is not None:
            self.states[id] = State(id, name, initial, self.states[parentId])
            self.states[parentId].addChild(self.states[id])
            parentItem = self.treeModel.getByDataId(parentId)
            # print('parent:' + str(parentItem))
        else:
            self.states[id] = State(id, name, initial, None)
        if id == 0:
            self.rootState = self.states[id]

        self.states[id].setPos(x, y)

    def addTransition(self, id, name, originId, destinationId, x, y):
        self.transitions[id] = Transition(id, name, self.states[originId],
                                          self.states[destinationId])
        self.transitions[id].setPos(x, y)

    def emitRunningStateById(self, id):
        # print('emit running state:' + str(id))
        self.runningStateChanged.emit(id)

    def runningStateChangedHandle(self, id):
        # print('running state:' + str(id))
        if id not in self.states:
            return

        runningState = self.states[id]

        parentId = None
        if runningState.parent is not None:
            for child in runningState.parent.getChildren():
                child.setRunning(False)

            runningState.setRunning(True)
            parentId = runningState.parent.id

        self.treeModel.setAllBackgroundByParentId(Qt.white, parentId)
        self.treeModel.setBackgroundById(runningState.id, Qt.green)

    def emitActiveStateById(self, id):
        self.activeStateChanged.emit(id)

    def activeStateChangedHandle(self, id):
        if self.activeState is not None:
            for child in self.activeState.getChildren():
                child.resetGraphicsItem()
                for tran in child.getOriginTransitions():
                    tran.resetGraphicsItem()

        self.activeState = self.states[id]
        # print('set active state:' + str(id))
        self.scene.clear()
        for childState in self.activeState.getChildren():
            # print('add child to scene:' + str(childState.id))
            qitem = childState.getGraphicsItem()
            qitem.setAcceptHoverEvents(False)
            qitem.setFlag(QGraphicsItem.ItemIsMovable, False)
            qitem.doubleClicked.connect(self.stateDoubleClicked)
            self.setAcceptDrops(False)
            self.scene.addItem(qitem)
            for tran in childState.getOriginTransitions():
                # print('add transition:' + str(tran.id))
                qitem = tran.getGraphicsItem()
                qitem.disableInteraction()
                self.scene.addItem(qitem)

    def emitLoadFromRoot(self):
        self.loadFromRoot.emit(0)

    def loadFromRootHandle(self, id):
        self.treeModel.loadFromRoot(self.states[id])

    def stateDoubleClicked(self, stateItem):
        if len(stateItem.stateData.getChildren()) > 0:
            self.emitActiveStateById(stateItem.stateData.id)

    def upButtonClicked(self):
        if self.activeState is not None:
            if self.activeState.parent is not None:
                self.emitActiveStateById(self.activeState.parent.id)

    def getStateById(self, state, id):
        if state.id == id:
            return state
        else:
            result = None
            for child in state.getChildren():
                result = self.getStateById(child, id)
                if result is not None:
                    return result
            return result

    def treeItemClicked(self, index):
        # print('clicked item.id:' + str(index.internalPointer().id))
        pass

    def getStateList(self, state, stateList):
        if len(state.getChildren()) > 0:
            stateList.append(state)

        for s in state.getChildren():
            self.getStateList(s, stateList)

    def loopIPC(self):
        while True:
            msg = self.getIPCMessage()
            if msg is not None:
                if len(msg) > 0:
                    msg = msg.strip()
                    methodName = msg.split(' ')[0]
                    id = int(msg.split(' ')[1])
                    if methodName == 'emitRunningStateById':
                        self.emitRunningStateById(id)
                    else:
                        print('unknown method name')

            # time.sleep(1.0/1000)

    def activateIPC(self):
        try:
            self.memory = sysv_ipc.SharedMemory(123456,
                                                flags=sysv_ipc.IPC_CREAT,
                                                size=1024)
        except:
            print('cannot create or open share mem with id 123456')
            return

        # create sempahore
        try:
            self.semaphore = sysv_ipc.Semaphore(9,
                                                flags=sysv_ipc.IPC_CREAT,
                                                initial_value=0)
        except:
            print('cannot create or open semaphore with id 9')
            self.memory.remove()
            return

        self.ipcThread = Thread(target=self.loopIPC)
        self.ipcThread.start()

    def getIPCMessage(self):
        self.semaphore.acquire()
        data = self.memory.read().decode()
        return data
コード例 #6
0
class VisualStates(QMainWindow):
    def __init__(self, parent=None):
        super(QMainWindow, self).__init__()

        self.setWindowTitle("VisualStates")
        self.configDialog = None

        # root state
        self.rootState = State(0, "root", True)
        self.activeState = self.rootState

        # create status bar
        self.statusBar()

        self.createMenu()
        self.createTreeView()
        self.createStateCanvas()

        self.setGeometry(0, 0, 800, 600)
        self.show()

        self.fileManager = FileManager()

        self.libraries = []
        self.config = None
        self.interfaceHeaderMap = Interfaces.getInterfaces()

    def createMenu(self):
        # create actions
        newAction = QAction('&New', self)
        newAction.setShortcut('Ctrl+N')
        newAction.setStatusTip('Create New Visual States')
        newAction.triggered.connect(self.newAction)

        openAction = QAction('&Open', self)
        openAction.setShortcut('Ctrl+O')
        openAction.setStatusTip('Open Visual States')
        openAction.triggered.connect(self.openAction)

        saveAction = QAction('&Save', self)
        saveAction.setShortcut('Ctrl+S')
        saveAction.setStatusTip('Save Visual States')
        saveAction.triggered.connect(self.saveAction)

        saveAsAction = QAction('&Save As', self)
        saveAsAction.setShortcut('Ctrl+S')
        saveAsAction.setStatusTip('Save Visual States as New One')
        saveAsAction.triggered.connect(self.saveAsAction)

        quitAction = QAction('&Quit', self)
        quitAction.setShortcut('Ctrl+Q')
        quitAction.setStatusTip('Quit Visual States')
        quitAction.triggered.connect(self.quitAction)

        # figures menu
        stateAction = QAction('&State', self)
        stateAction.setStatusTip('Create a state')
        stateAction.triggered.connect(self.stateAction)

        transitionAction = QAction('&Transition', self)
        transitionAction.setStatusTip('Create a transition')
        transitionAction.triggered.connect(self.transitionAction)

        # data menu
        timerAction = QAction('&Timer', self)
        timerAction.setShortcut('Ctrl+M')
        timerAction.setStatusTip('Set timing of states')
        timerAction.triggered.connect(self.timerAction)

        variablesAction = QAction('&Variables', self)
        variablesAction.setShortcut('Ctrl+V')
        variablesAction.setStatusTip('Define state variables')
        variablesAction.triggered.connect(self.variablesAction)

        functionsAction = QAction('&Functions', self)
        functionsAction.setShortcut('Ctrl+F')
        functionsAction.setStatusTip('Define functions')
        functionsAction.triggered.connect(self.functionsAction)

        # actions menu
        librariesAction = QAction('&Libraries', self)
        librariesAction.setShortcut('Ctrl+L')
        librariesAction.setStatusTip('Add additional libraries')
        librariesAction.triggered.connect(self.librariesAction)

        configFileAction = QAction('&Config File', self)
        configFileAction.setShortcut('Ctrl+C')
        configFileAction.setStatusTip('Edit configuration file')
        configFileAction.triggered.connect(self.configFileAction)

        generateCppAction = QAction('&Generate C++', self)
        generateCppAction.setShortcut('Ctrl+G')
        generateCppAction.setStatusTip('Generate C++ code')
        generateCppAction.triggered.connect(self.generateCppAction)

        compileCppAction = QAction('&Compile C++', self)
        compileCppAction.setShortcut('Ctrl+P')
        compileCppAction.setStatusTip('Compile generated C++ code')
        compileCppAction.triggered.connect(self.compileCppAction)

        generatePythonAction = QAction('&Generate Python', self)
        generatePythonAction.setShortcut('Ctrl+Y')
        generatePythonAction.setStatusTip('Generate Python code')
        generatePythonAction.triggered.connect(self.generatePythonAction)

        # help menu
        aboutAction = QAction('&About', self)
        aboutAction.setShortcut('F1')
        aboutAction.setStatusTip('Information about VisualStates')
        aboutAction.triggered.connect(self.aboutAction)

        # create main menu
        menubar = self.menuBar()
        archieveMenu = menubar.addMenu('&File')
        archieveMenu.addAction(newAction)
        archieveMenu.addAction(openAction)
        archieveMenu.addAction(saveAction)
        archieveMenu.addAction(saveAsAction)
        archieveMenu.addAction(quitAction)

        figuresMenu = menubar.addMenu('&Figures')
        figuresMenu.addAction(stateAction)
        figuresMenu.addAction(transitionAction)

        dataMenu = menubar.addMenu('&Data')
        dataMenu.addAction(timerAction)
        dataMenu.addAction(variablesAction)
        dataMenu.addAction(functionsAction)

        actionsMenu = menubar.addMenu('&Actions')
        actionsMenu.addAction(librariesAction)
        actionsMenu.addAction(configFileAction)
        actionsMenu.addAction(generateCppAction)
        actionsMenu.addAction(compileCppAction)
        actionsMenu.addAction(generatePythonAction)

        helpMenu = menubar.addMenu('&Help')
        helpMenu.addAction(aboutAction)

    def newAction(self):
        self.automataScene.clearScene()
        self.treeModel.removeAll()

        # create new root state
        self.rootState = State(0, 'root', True)
        self.automataScene.setActiveState(self.rootState)
        self.automataScene.resetIndexes()

    def openAction(self):
        fileDialog = QFileDialog(self)
        fileDialog.setWindowTitle("Open VisualStates File")
        fileDialog.setViewMode(QFileDialog.Detail)
        fileDialog.setNameFilters(['VisualStates File (*.xml)'])
        fileDialog.setDefaultSuffix('.xml')
        fileDialog.setAcceptMode(QFileDialog.AcceptOpen)
        if fileDialog.exec_():
            (self.rootState, self.config,
             self.libraries) = self.fileManager.open(
                 fileDialog.selectedFiles()[0])
            self.treeModel.removeAll()
            self.treeModel.loadFromRoot(self.rootState)
            # set the active state as the loaded state
            self.automataScene.setActiveState(self.rootState)
            self.automataScene.setLastIndexes(self.rootState)
            # print(str(self.config))
        # else:
        #     print('open is canceled')

    def saveAction(self):
        if len(self.fileManager.getFileName()) == 0:
            self.saveAsAction()
        else:
            self.fileManager.save(self.rootState, self.config, self.libraries)

    def saveAsAction(self):
        fileDialog = QFileDialog(self)
        fileDialog.setWindowTitle("Save VisualStates Project")
        fileDialog.setViewMode(QFileDialog.Detail)
        fileDialog.setNameFilters(['VisualStates File (*.xml)'])
        fileDialog.setAcceptMode(QFileDialog.AcceptSave)
        if fileDialog.exec_():
            self.fileManager.setFullPath(fileDialog.selectedFiles()[0])
            self.fileManager.save(self.rootState, self.config, self.libraries)
        # else:
        #     print('file dialog canceled')

    def quitAction(self):
        # print('Quit')
        self.close()

    def stateAction(self):
        self.automataScene.setOperationType(OpType.ADDSTATE)

    def transitionAction(self):
        self.automataScene.setOperationType(OpType.ADDTRANSITION)

    def timerAction(self):
        if self.activeState is not None:
            timerDialog = TimerDialog('Time Step Duration',
                                      str(self.activeState.getTimeStep()))
            timerDialog.timeChanged.connect(self.timeStepDurationChanged)
            timerDialog.exec_()

    def variablesAction(self):
        if self.activeState is not None:
            variablesDialog = CodeDialog('Variables',
                                         self.activeState.getVariables())
            variablesDialog.codeChanged.connect(self.variablesChanged)
            variablesDialog.exec_()
        else:
            self.showWarning(
                'Choose a state',
                'You can create variables only for a selected state')

    def functionsAction(self):
        if self.activeState is not None:
            functionsDialog = CodeDialog('Functions',
                                         self.activeState.getFunctions())
            functionsDialog.codeChanged.connect(self.functionsChanged)
            functionsDialog.exec_()
        else:
            self.showWarning(
                'Choose a state',
                'You can create functions only for a selected state')

    def librariesAction(self):
        librariesDialog = LibrariesDialog('Libraries', self.libraries)
        librariesDialog.librariesChanged.connect(self.librariesChanged)
        librariesDialog.exec_()

    def configFileAction(self):
        self.configDialog = ConfigDialog('Config', self.config)
        self.configDialog.configChanged.connect(self.configChanged)
        self.configDialog.exec_()

    def showWarning(self, title, msg):
        QMessageBox.warning(self, title, msg)

    def showInfo(self, title, msg):
        QMessageBox.information(self, title, msg)

    def generateCppAction(self):
        stateList = []
        if self.fileManager.hasFile():
            self.getStateList(self.rootState, stateList)
            if self.config.type == ROS:
                generator = CppRosGenerator(self.libraries, self.config,
                                            self.interfaceHeaderMap, stateList)
            elif self.config.type == JDEROBOTCOMM:
                generator = CppGenerator(self.libraries, self.config,
                                         self.interfaceHeaderMap, stateList)

            generator.generate(self.fileManager.getPath(),
                               self.fileManager.getFileName())
            self.showInfo('C++ Code Generation',
                          'C++ code generation is successful.')
        else:
            self.showWarning(
                'C++ Generation',
                'Please save the project before code generation.')

    def compileCppAction(self):
        # print('compile cpp action')
        pass

    def generatePythonAction(self):
        stateList = []
        if self.fileManager.hasFile():
            self.getStateList(self.rootState, stateList)
            if self.config.type == ROS:
                generator = PythonRosGenerator(self.libraries, self.config,
                                               stateList)
            elif self.config.type == JDEROBOTCOMM:
                generator = PythonGenerator(self.libraries, self.config,
                                            self.interfaceHeaderMap, stateList)
            generator.generate(self.fileManager.getPath(),
                               self.fileManager.getFileName())
            self.showInfo('Python Code Generation',
                          'Python code generation is successful.')
        else:
            self.showWarning(
                'Python Generation',
                'Please save the project before code generation.')

    def aboutAction(self):
        pass
        # print('about action')

    def createTreeView(self):
        dockWidget = QDockWidget()
        dockWidget.setAllowedAreas(Qt.LeftDockWidgetArea)
        dockWidget.setFeatures(QDockWidget.NoDockWidgetFeatures)
        dockWidget.setTitleBarWidget(QWidget())
        self.treeView = QTreeView()
        self.treeView.clicked.connect(self.treeItemClicked)
        self.treeModel = TreeModel()
        self.treeView.setModel(self.treeModel)

        self.logo = QLabel()
        logoPixmap = QPixmap(CMAKE_INSTALL_PREFIX +
                             '/share/jderobot/resources/jderobot.png')
        self.logo.setPixmap(logoPixmap)

        self.upButton = QPushButton()
        self.upButton.setText('Up')
        self.upButton.clicked.connect(self.upButtonClicked)

        leftContainer = QWidget()
        leftLayout = QVBoxLayout()
        leftLayout.addWidget(self.treeView)
        leftLayout.addWidget(self.upButton)
        leftLayout.addWidget(self.logo)
        leftContainer.setLayout(leftLayout)

        dockWidget.setWidget(leftContainer)
        self.addDockWidget(Qt.LeftDockWidgetArea, dockWidget)

    def createStateCanvas(self):
        self.stateCanvas = QGraphicsView()
        self.automataScene = AutomataScene()
        self.automataScene.setSceneRect(0, 0, 2000, 2000)
        self.automataScene.activeStateChanged.connect(self.activeStateChanged)
        self.automataScene.stateInserted.connect(self.stateInserted)
        self.automataScene.stateRemoved.connect(self.stateRemoved)
        self.automataScene.transitionInserted.connect(self.transitionInserted)
        self.automataScene.stateNameChangedSignal.connect(
            self.stateNameChanged)
        self.automataScene.setActiveState(self.rootState)

        self.setCentralWidget(self.stateCanvas)
        self.stateCanvas.setScene(self.automataScene)
        self.stateCanvas.setRenderHint(QPainter.Antialiasing)
        self.stateCanvas.setAcceptDrops(True)

    def stateInserted(self, state):
        if self.activeState != self.rootState:
            parent = self.treeModel.getByDataId(self.activeState.id)
            self.treeModel.insertState(state, QColor(Qt.white), parent)
        else:
            self.treeModel.insertState(state, QColor(Qt.white))

    def stateRemoved(self, state):
        if self.activeState != self.rootState:
            self.treeModel.removeState(state.stateData, self.activeState)
        else:
            self.treeModel.removeState(state.stateData)

    def transitionInserted(self, tran):
        # print('transition inserted:' + tran.transitionData.name)
        pass

    def stateNameChanged(self, state):
        dataItem = self.treeModel.getByDataId(state.stateData.id)
        if dataItem != None:
            dataItem.name = state.stateData.name
            self.treeModel.layoutChanged.emit()

    def activeStateChanged(self):
        if self.automataScene.activeState != self.activeState:
            # print('visual states active state changed:' + self.automataScene.activeState.name)
            self.activeState = self.automataScene.activeState
            if self.activeState == self.rootState:
                self.treeView.selectionModel().clearSelection()
            else:
                self.treeView.setCurrentIndex(
                    self.treeModel.indexOf(
                        self.treeModel.getByDataId(self.activeState.id)))

    def upButtonClicked(self):
        if self.activeState != None:
            if self.activeState.parent != None:
                # print('parent name:' + self.activeState.parent.name)
                self.automataScene.setActiveState(self.activeState.parent)

    def getStateById(self, state, id):
        if state.id == id:
            return state
        else:
            result = None
            for child in state.getChildren():
                result = self.getStateById(child, id)
                if result is not None:
                    return result
            return result

    def treeItemClicked(self, index):
        # print('clicked item.id:' + str(index.internalPointer().id))
        state = self.getStateById(self.rootState, index.internalPointer().id)
        if state is not None:
            # set the active state as the loaded state
            self.automataScene.setActiveState(state)

    def timeStepDurationChanged(self, duration):
        if self.activeState is not None:
            self.activeState.setTimeStep(duration)

    def variablesChanged(self, variables):
        if self.activeState is not None:
            self.activeState.setVariables(variables)

    def functionsChanged(self, functions):
        if self.activeState is not None:
            self.activeState.setFunctions(functions)

    def librariesChanged(self, libraries):
        self.libraries = libraries

    def configChanged(self):
        if self.configDialog is not None:
            self.config = self.configDialog.getConfig()

    def getStateList(self, state, stateList):
        if len(state.getChildren()) > 0:
            stateList.append(state)

        for s in state.getChildren():
            self.getStateList(s, stateList)
コード例 #7
-1
ファイル: visualstates.py プロジェクト: reysam93/JdeRobot
class VisualStates(QMainWindow):
    def __init__(self, parent=None):
        super(QMainWindow, self).__init__()

        self.setWindowTitle("VisualStates")
        self.configDialog = None

        # root state
        self.rootState = State(0, "root", True)
        self.activeState = self.rootState

        # create status bar
        self.statusBar()

        self.createMenu()
        self.createTreeView()
        self.createStateCanvas()

        self.setGeometry(0, 0, 800, 600)
        self.show()

        self.fileManager = FileManager()

        self.libraries = []
        self.config = None
        self.interfaceHeaderMap = Interfaces.getInterfaces()

    def createMenu(self):
        # create actions
        newAction = QAction('&New', self)
        newAction.setShortcut('Ctrl+N')
        newAction.setStatusTip('Create New Visual States')
        newAction.triggered.connect(self.newAction)

        openAction = QAction('&Open', self)
        openAction.setShortcut('Ctrl+O')
        openAction.setStatusTip('Open Visual States')
        openAction.triggered.connect(self.openAction)

        saveAction = QAction('&Save', self)
        saveAction.setShortcut('Ctrl+S')
        saveAction.setStatusTip('Save Visual States')
        saveAction.triggered.connect(self.saveAction)

        saveAsAction = QAction('&Save As', self)
        saveAsAction.setShortcut('Ctrl+S')
        saveAsAction.setStatusTip('Save Visual States as New One')
        saveAsAction.triggered.connect(self.saveAsAction)

        quitAction = QAction('&Quit', self)
        quitAction.setShortcut('Ctrl+Q')
        quitAction.setStatusTip('Quit Visual States')
        quitAction.triggered.connect(self.quitAction)

        # figures menu
        stateAction = QAction('&State', self)
        stateAction.setStatusTip('Create a state')
        stateAction.triggered.connect(self.stateAction)

        transitionAction = QAction('&Transition', self)
        transitionAction.setStatusTip('Create a transition')
        transitionAction.triggered.connect(self.transitionAction)

        # data menu
        timerAction = QAction('&Timer', self)
        timerAction.setShortcut('Ctrl+M')
        timerAction.setStatusTip('Set timing of states')
        timerAction.triggered.connect(self.timerAction)

        variablesAction = QAction('&Variables', self)
        variablesAction.setShortcut('Ctrl+V')
        variablesAction.setStatusTip('Define state variables')
        variablesAction.triggered.connect(self.variablesAction)

        functionsAction = QAction('&Functions', self)
        functionsAction.setShortcut('Ctrl+F')
        functionsAction.setStatusTip('Define functions')
        functionsAction.triggered.connect(self.functionsAction)

        # actions menu
        librariesAction = QAction('&Libraries', self)
        librariesAction.setShortcut('Ctrl+L')
        librariesAction.setStatusTip('Add additional libraries')
        librariesAction.triggered.connect(self.librariesAction)

        configFileAction = QAction('&Config File', self)
        configFileAction.setShortcut('Ctrl+C')
        configFileAction.setStatusTip('Edit configuration file')
        configFileAction.triggered.connect(self.configFileAction)

        generateCppAction = QAction('&Generate C++', self)
        generateCppAction.setShortcut('Ctrl+G')
        generateCppAction.setStatusTip('Generate C++ code')
        generateCppAction.triggered.connect(self.generateCppAction)

        compileCppAction = QAction('&Compile C++', self)
        compileCppAction.setShortcut('Ctrl+P')
        compileCppAction.setStatusTip('Compile generated C++ code')
        compileCppAction.triggered.connect(self.compileCppAction)

        generatePythonAction = QAction('&Generate Python', self)
        generatePythonAction.setShortcut('Ctrl+Y')
        generatePythonAction.setStatusTip('Generate Python code')
        generatePythonAction.triggered.connect(self.generatePythonAction)

        # help menu
        aboutAction = QAction('&About', self)
        aboutAction.setShortcut('F1')
        aboutAction.setStatusTip('Information about VisualStates')
        aboutAction.triggered.connect(self.aboutAction)

        # create main menu
        menubar = self.menuBar()
        archieveMenu = menubar.addMenu('&File')
        archieveMenu.addAction(newAction)
        archieveMenu.addAction(openAction)
        archieveMenu.addAction(saveAction)
        archieveMenu.addAction(saveAsAction)
        archieveMenu.addAction(quitAction)

        figuresMenu = menubar.addMenu('&Figures')
        figuresMenu.addAction(stateAction)
        figuresMenu.addAction(transitionAction)

        dataMenu = menubar.addMenu('&Data')
        dataMenu.addAction(timerAction)
        dataMenu.addAction(variablesAction)
        dataMenu.addAction(functionsAction)

        actionsMenu = menubar.addMenu('&Actions')
        actionsMenu.addAction(librariesAction)
        actionsMenu.addAction(configFileAction)
        actionsMenu.addAction(generateCppAction)
        actionsMenu.addAction(compileCppAction)
        actionsMenu.addAction(generatePythonAction)

        helpMenu = menubar.addMenu('&Help')
        helpMenu.addAction(aboutAction)


    def newAction(self):
        self.automataScene.clearScene()
        # create new root state
        self.rootState = State(0, 'root', True)
        self.automataScene.setActiveState(self.rootState)
        self.automataScene.resetIndexes()

    def openAction(self):
        fileDialog = QFileDialog(self)
        fileDialog.setWindowTitle("Open VisualStates File")
        fileDialog.setViewMode(QFileDialog.Detail)
        fileDialog.setNameFilters(['VisualStates File (*.xml)'])
        fileDialog.setDefaultSuffix('.xml')
        fileDialog.setAcceptMode(QFileDialog.AcceptOpen)
        if fileDialog.exec_():
            (self.rootState, self.config, self.libraries) = self.fileManager.open(fileDialog.selectedFiles()[0])
            self.treeModel.removeAll()
            self.treeModel.loadFromRoot(self.rootState)
            # set the active state as the loaded state
            self.automataScene.setActiveState(self.rootState)
            self.automataScene.setLastIndexes(self.rootState)
            # print(str(self.config))
        # else:
        #     print('open is canceled')



    def saveAction(self):
        if len(self.fileManager.getFileName()) == 0:
            self.saveAsAction()
        else:
            self.fileManager.save(self.rootState, self.config, self.libraries)

    def saveAsAction(self):
        fileDialog = QFileDialog(self)
        fileDialog.setWindowTitle("Save VisualStates Project")
        fileDialog.setViewMode(QFileDialog.Detail)
        fileDialog.setNameFilters(['VisualStates File (*.xml)'])
        fileDialog.setAcceptMode(QFileDialog.AcceptSave)
        if fileDialog.exec_():
            self.fileManager.setFullPath(fileDialog.selectedFiles()[0])
            self.fileManager.save(self.rootState, self.config, self.libraries)
        # else:
        #     print('file dialog canceled')


    def quitAction(self):
        # print('Quit')
        self.close()

    def stateAction(self):
        self.automataScene.setOperationType(OpType.ADDSTATE)

    def transitionAction(self):
        self.automataScene.setOperationType(OpType.ADDTRANSITION)

    def timerAction(self):
        if self.activeState is not None:
            timerDialog = TimerDialog('Time Step Duration', str(self.activeState.getTimeStep()))
            timerDialog.timeChanged.connect(self.timeStepDurationChanged)
            timerDialog.exec_()

    def variablesAction(self):
        if self.activeState is not None:
            variablesDialog = CodeDialog('Variables', self.activeState.getVariables())
            variablesDialog.codeChanged.connect(self.variablesChanged)
            variablesDialog.exec_()
        else:
            self.showWarning('Choose a state', 'You can create variables only for a selected state')

    def functionsAction(self):
        if self.activeState is not None:
            functionsDialog = CodeDialog('Functions', self.activeState.getFunctions())
            functionsDialog.codeChanged.connect(self.functionsChanged)
            functionsDialog.exec_()
        else:
            self.showWarning('Choose a state', 'You can create functions only for a selected state')

    def librariesAction(self):
        librariesDialog = LibrariesDialog('Libraries', self.libraries)
        librariesDialog.librariesChanged.connect(self.librariesChanged)
        librariesDialog.exec_()

    def configFileAction(self):
        self.configDialog = ConfigDialog('Config', self.config)
        self.configDialog.configChanged.connect(self.configChanged)
        self.configDialog.exec_()


    def showWarning(self, title, msg):
        QMessageBox.warning(self, title, msg)

    def showInfo(self, title, msg):
        QMessageBox.information(self, title, msg)

    def generateCppAction(self):
        stateList = []
        if self.fileManager.hasFile():
            self.getStateList(self.rootState, stateList)
            if self.config.type == ROS:
                generator = CppRosGenerator(self.libraries, self.config, self.interfaceHeaderMap, stateList)
            elif self.config.type == JDEROBOTCOMM:
                generator = CppGenerator(self.libraries, self.config, self.interfaceHeaderMap, stateList)

            generator.generate(self.fileManager.getPath(), self.fileManager.getFileName())
            self.showInfo('C++ Code Generation', 'C++ code generation is successful.')
        else:
            self.showWarning('C++ Generation', 'Please save the project before code generation.')


    def compileCppAction(self):
        # print('compile cpp action')
        pass

    def generatePythonAction(self):
        stateList = []
        if self.fileManager.hasFile():
            self.getStateList(self.rootState, stateList)
            if self.config.type == ROS:
                generator = PythonRosGenerator(self.libraries, self.config, stateList)
            elif self.config.type == JDEROBOTCOMM:
                generator = PythonGenerator(self.libraries, self.config, self.interfaceHeaderMap, stateList)
            generator.generate(self.fileManager.getPath(), self.fileManager.getFileName())
            self.showInfo('Python Code Generation', 'Python code generation is successful.')
        else:
            self.showWarning('Python Generation', 'Please save the project before code generation.')

    def aboutAction(self):
        pass
        # print('about action')

    def createTreeView(self):
        dockWidget = QDockWidget()
        dockWidget.setAllowedAreas(Qt.LeftDockWidgetArea)
        dockWidget.setFeatures(QDockWidget.NoDockWidgetFeatures)
        dockWidget.setTitleBarWidget(QWidget())
        self.treeView = QTreeView()
        self.treeView.clicked.connect(self.treeItemClicked)
        self.treeModel = TreeModel()
        self.treeView.setModel(self.treeModel)

        self.logo = QLabel()
        logoPixmap = QPixmap(CMAKE_INSTALL_PREFIX + '/share/jderobot/resources/jderobot.png')
        self.logo.setPixmap(logoPixmap)

        self.upButton = QPushButton()
        self.upButton.setText('Up')
        self.upButton.clicked.connect(self.upButtonClicked)

        leftContainer = QWidget()
        leftLayout = QVBoxLayout()
        leftLayout.addWidget(self.treeView)
        leftLayout.addWidget(self.upButton)
        leftLayout.addWidget(self.logo)
        leftContainer.setLayout(leftLayout)

        dockWidget.setWidget(leftContainer)
        self.addDockWidget(Qt.LeftDockWidgetArea, dockWidget)

    def createStateCanvas(self):
        self.stateCanvas = QGraphicsView()
        self.automataScene = AutomataScene()
        self.automataScene.setSceneRect(0, 0, 2000, 2000)
        self.automataScene.activeStateChanged.connect(self.activeStateChanged)
        self.automataScene.stateInserted.connect(self.stateInserted)
        self.automataScene.stateRemoved.connect(self.stateRemoved)
        self.automataScene.transitionInserted.connect(self.transitionInserted)
        self.automataScene.stateNameChangedSignal.connect(self.stateNameChanged)
        self.automataScene.setActiveState(self.rootState)

        self.setCentralWidget(self.stateCanvas)
        self.stateCanvas.setScene(self.automataScene)
        self.stateCanvas.setRenderHint(QPainter.Antialiasing)
        self.stateCanvas.setAcceptDrops(True)

    def stateInserted(self, state):
        if self.activeState != self.rootState:
            parent = self.treeModel.getByDataId(self.activeState.id)
            self.treeModel.insertState(state, QColor(Qt.white), parent)
        else:
            self.treeModel.insertState(state, QColor(Qt.white))

    def stateRemoved(self, state):
        if self.activeState != self.rootState:
            self.treeModel.removeState(state.stateData, self.activeState)
        else:
            self.treeModel.removeState(state.stateData)

    def transitionInserted(self, tran):
        # print('transition inserted:' + tran.transitionData.name)
        pass

    def stateNameChanged(self, state):
        dataItem = self.treeModel.getByDataId(state.stateData.id)
        if dataItem != None:
            dataItem.name = state.stateData.name
            self.treeModel.layoutChanged.emit()

    def activeStateChanged(self):
        if self.automataScene.activeState != self.activeState:
            # print('visual states active state changed:' + self.automataScene.activeState.name)
            self.activeState = self.automataScene.activeState
            if self.activeState == self.rootState:
                self.treeView.selectionModel().clearSelection()
            else:
                self.treeView.setCurrentIndex(self.treeModel.indexOf(self.treeModel.getByDataId(self.activeState.id)))

    def upButtonClicked(self):
        if self.activeState != None:
            if self.activeState.parent != None:
                # print('parent name:' + self.activeState.parent.name)
                self.automataScene.setActiveState(self.activeState.parent)


    def getStateById(self,state, id):
        if state.id == id:
            return state
        else:
            result = None
            for child in state.getChildren():
                result = self.getStateById(child, id)
                if result is not None:
                    return result
            return result

    def treeItemClicked(self, index):
        # print('clicked item.id:' + str(index.internalPointer().id))
        state = self.getStateById(self.rootState, index.internalPointer().id)
        if state is not None:
            # set the active state as the loaded state
            self.automataScene.setActiveState(state)

    def timeStepDurationChanged(self, duration):
        if self.activeState is not None:
            self.activeState.setTimeStep(duration)

    def variablesChanged(self, variables):
        if self.activeState is not None:
            self.activeState.setVariables(variables)

    def functionsChanged(self, functions):
        if self.activeState is not None:
            self.activeState.setFunctions(functions)

    def librariesChanged(self, libraries):
        self.libraries = libraries

    def configChanged(self):
        if self.configDialog is not None:
            self.config = self.configDialog.getConfig()

    def getStateList(self, state, stateList):
        if len(state.getChildren()) > 0:
            stateList.append(state)

        for s in state.getChildren():
            self.getStateList(s, stateList)