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 __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)
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
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()
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
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)
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)