class Editor(ApplicationBase, MainWindow): """ Editor sets up all subsystems and provides access to them """ editor = None def __init__(self, params, *args, **kwargs): Editor.editor = self self._filemanager = None self._open_files = [] self._params = params self._eventlistener = None self._pluginmanager = None self._inited = False self._mapview = None self._mapviewlist = [] self._mapgroup = None self._mapbar = None self._maparea = None self._mapeditor = None self._file_menu = None self._edit_menu = None self._view_menu = None self._tools_menu = None self._help_menu = None self._settings = None self._help_dialog = None ApplicationBase.__init__(self, *args, **kwargs) MainWindow.__init__(self, *args, **kwargs) pychan.init(self.engine, debug=False) def loadSettings(self): """ Load the settings from a python file and load them into the engine. Called in the ApplicationBase constructor. """ self._settings = Settings() TDS = self._settings glyphDft = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/():;%&`'*#=[]\\\"" engineSetting = self.engine.getSettings() engineSetting.setDefaultFontGlyphs(TDS.get("FIFE", "FontGlyphs", glyphDft)) engineSetting.setDefaultFontPath(TDS.get("FIFE", "Font", "fonts/FreeSans.ttf")) engineSetting.setDefaultFontSize(12) engineSetting.setBitsPerPixel(TDS.get("FIFE", "BitsPerPixel", 0)) engineSetting.setInitialVolume(TDS.get("FIFE", "InitialVolume", 5.0)) engineSetting.setSDLRemoveFakeAlpha(TDS.get("FIFE", "SDLRemoveFakeAlpha", 1)) engineSetting.setScreenWidth(TDS.get("FIFE", "ScreenWidth", 1024)) engineSetting.setScreenHeight(TDS.get("FIFE", "ScreenHeight", 768)) engineSetting.setRenderBackend(TDS.get("FIFE", "RenderBackend", "OpenGL")) engineSetting.setFullScreen(TDS.get("FIFE", "FullScreen", 0)) engineSetting.setWindowTitle(TDS.get("FIFE", "WindowTitle", "No window title set")) engineSetting.setWindowIcon(TDS.get("FIFE", "WindowIcon", "")) engineSetting.setImageChunkingSize(TDS.get("FIFE", "ImageChunkSize", 256)) def initLogging(self): """ Initialize the LogManager. """ import fifelog logModules = self._settings.get("FIFE", "LogModules") loglevel = self._settings.get("FIFE", "LogLevel", "Warn"); self.log = fifelog.LogManager(self.engine, self._settings.get("FIFE", "LogToPrompt"), self._settings.get("FIFE", "LogToFile")) if logModules: self.log.setVisibleModules(*logModules) if loglevel == "Debug": loglevel = fife.LogManager.LEVEL_DEBUG elif loglevel == "Log": loglevel = fife.LogManager.LEVEL_LOG elif loglevel == "Error": loglevel = fife.LogManager.LEVEL_ERROR else: loglevel = fife.LogManager.LEVEL_WARN self.log.lm.setLevelFilter(loglevel) def _initTools(self): """ Initializes tools """ self._pluginmanager = plugin.PluginManager(self.getSettings()) self._filemanager = FileManager() self._toolbar.adaptLayout() self._mapeditor = MapEditor() def _initGui(self): """ Sets up the GUI """ screen_width = self.engine.getSettings().getScreenWidth() screen_height = self.engine.getSettings().getScreenHeight() MainWindow.initGui(self, screen_width, screen_height) self._toolbox = ToolBar(title=u"", orientation=1) self._toolbox.position_technique = "explicit" self._toolbox.position = (150, 150) self._mapbar = ToolBar(name="MapBar", panel_size=20) self._mapbar.setDocked(True) self._maparea = pychan.widgets.VBox() self._maparea.opaque = False self._maparea.is_focusable = True # Capture mouse and key events for EventListener cw = self._maparea cw.capture(self.__sendMouseEvent, "mouseEntered") cw.capture(self.__sendMouseEvent, "mouseExited") cw.capture(self.__sendMouseEvent, "mousePressed") cw.capture(self.__sendMouseEvent, "mouseReleased") cw.capture(self.__sendMouseEvent, "mouseClicked") cw.capture(self.__sendMouseEvent, "mouseMoved") cw.capture(self.__sendMouseEvent, "mouseWheelMovedUp") cw.capture(self.__sendMouseEvent, "mouseWheelMovedDown") cw.capture(self.__sendMouseEvent, "mouseDragged") cw.capture(self.__sendKeyEvent, "keyPressed") cw.capture(self.__sendKeyEvent, "keyReleased") self._centralwidget.addChild(self._mapbar) self._centralwidget.addChild(self._maparea) self._initActions() self._toolbox.show() def _initActions(self): """ Initializes toolbar and menubar buttons """ exitAction = Action(u"Exit", "gui/icons/quit.png") exitAction.helptext = u"Exit program" action.activated.connect(self.quit, sender=exitAction) self._file_menu = Menu(name=u"File") self._file_menu.addAction(exitAction) self._edit_menu = Menu(name=u"Edit") self._view_menu = Menu(name=u"View") self._tools_menu = Menu(name=u"Tools") self._window_menu = Menu(name=u"Window") self._help_menu = Menu(name=u"Help") self._action_show_statusbar = Action(u"Statusbar") self._action_show_statusbar.helptext = u"Toggle statusbar" action.activated.connect(self.toggleStatusbar, sender=self._action_show_statusbar) self._action_show_toolbar = Action(u"Toolbar") self._action_show_toolbar.helptext = u"Toggle toolbar" action.activated.connect(self.toggleToolbar, sender=self._action_show_toolbar) self._action_show_toolbox = Action(u"Tool box") self._action_show_toolbox.helptext = u"Toggle tool box" action.activated.connect(self.toggleToolbox, sender=self._action_show_toolbox) self._view_menu.addAction(self._action_show_statusbar) self._view_menu.addAction(self._action_show_toolbar) self._view_menu.addAction(self._action_show_toolbox) self._view_menu.addSeparator() test_action1 = Action(u"Cycle buttonstyles", "gui/icons/cycle_styles.png") test_action1.helptext = u"Cycles button styles. There are currently four button styles." action.activated.connect(self._actionActivated, sender=test_action1) self._view_menu.addAction(test_action1) self._mapgroup = ActionGroup(exclusive=True, name="Mapgroup") self._mapbar.addAction(self._mapgroup) self._window_menu.addAction(self._mapgroup) help_action = Action(u"Help", "gui/icons/help.png") help_action.helptext = u"Displays a window with some simple instructions" action.activated.connect(self._showHelpDialog, sender=help_action) self._help_menu.addAction(help_action) self._menubar.addMenu(self._file_menu) self._menubar.addMenu(self._edit_menu) self._menubar.addMenu(self._view_menu) self._menubar.addMenu(self._tools_menu) self._menubar.addMenu(self._window_menu) self._menubar.addMenu(self._help_menu) def _actionActivated(self, sender): self._toolbar.button_style += 1 def _showHelpDialog(self, sender): """ Shows the help dialog """ if self._help_dialog is not None: self._help_dialog.show() return self._help_dialog = pychan.loadXML("gui/help.xml") self._help_dialog.findChild(name="closeButton").capture(self._help_dialog.hide) f = open('lang/infotext.txt', 'r') self._help_dialog.findChild(name="helpText").text = unicode(f.read()) f.close() self._help_dialog.show() def toggleStatusbar(self): """ Toggles status bar """ statusbar = self.getStatusBar() if statusbar.max_size[1] > 0: statusbar.min_size=(statusbar.min_size[0], 0) statusbar.max_size=(statusbar.max_size[0], 0) self._action_show_statusbar.setChecked(False) else: statusbar.min_size=(statusbar.min_size[0], statusbar.min_size[0]) statusbar.max_size=(statusbar.max_size[0], statusbar.max_size[0]) self._action_show_statusbar.setChecked(True) statusbar.adaptLayout() def toggleToolbar(self): """ Toggles toolbar """ toolbar = self.getToolBar() if toolbar.isVisible(): toolbar.setDocked(False) toolbar.hide() self._action_show_toolbar.setChecked(False) else: tx = toolbar.x ty = toolbar.y toolbar.show() toolbar.x = tx toolbar.y = ty self._action_show_toolbar.setChecked(True) def toggleToolbox(self): """ Toggles tool box """ toolbox = self.getToolbox() if toolbox.isVisible(): toolbox.setDocked(False) toolbox.hide() self._action_show_toolbox.setChecked(False) else: tx = toolbox.x ty = toolbox.y toolbox.show() toolbox.x = tx toolbox.y = ty self._action_show_toolbox.setChecked(True) toolbox.adaptLayout() def getToolbox(self): return self._toolbox def getPluginManager(self): return self._pluginmanager def getEngine(self): return self.engine def getMapViews(self): return self._mapviewlist def getActiveMapView(self): return self._mapview def getSettings(self): return self._settings; def showMapView(self, mapview): """ Switches to mapview. """ if mapview is None or mapview == self._mapview: return events.preMapShown.send(sender=self, mapview=mapview) self._mapview = mapview self._mapview.show() events.postMapShown.send(sender=self, mapview=mapview) def createListener(self): """ Creates the event listener. This is called by ApplicationBase """ if self._eventlistener is None: self._eventlistener = EventListener(self.engine) return self._eventlistener def getEventListener(self): """ Returns the event listener """ return self._eventlistener def newMapView(self, map): """ Creates a new map view """ mapview = MapView(map) self._mapviewlist.append(mapview) map_action = Action(unicode(map.getId())) action.activated.connect(cbwa(self.showMapView, mapview), sender=map_action, weak=False) self._mapgroup.addAction(map_action) self.showMapView(mapview) events.preMapClosed.connect(self._preMapRemoved) events.postMapClosed.connect(self._postMapRemoved) events.mapAdded.send(sender=self, map=map) return mapview def _preMapRemoved(self, sender, mapview): events.preMapClosed.disconnect(self._preMapRemoved) # Remove from open files list try: path = mapview.getMap().getResourceLocation().getFilename() try: self._open_files.remove(path) except ValueError: pass except RuntimeError: # Mapview is not saved return # Remove tab for map_action in self._mapgroup.getActions(): if map_action.text == unicode(mapview.getMap().getId()): self._mapgroup.removeAction(map_action) break def _postMapRemoved(self, mapview): events.postMapClosed.disconnect(self._postMapRemoved) # Remove from mapviewlist index = self._mapviewlist.index(mapview)-1 self._mapviewlist.remove(mapview) # Change mapview if index >= 0: self.showMapView(self._mapviewlist[index]) else: self._mapview = None self.getEngine().getView().clearCameras() def getMapviewByPath(self, path): mappath = "" for mv in self._mapviewlist: try: mappath = mv.getMap().getResourceLocation().getFilename() except RuntimeError: # Mapview is not saved yet continue if mappath == path: return mv def openFile(self, path): if path in self._open_files: # Map is already open, ask user if he wants to reload the map mapview = self.getMapviewByPath(path) YesNoDialog(u"Map is already open. Do you want to reload it?", cbwa(self.reloadMapview, mapview=mapview)) return """ Opens a file """ try: map = loaders.loadMapFile(path, self.engine) mapview = self.newMapView(map) self._open_files.append(path) return mapview except: traceback.print_exc(sys.exc_info()[1]) errormsg = u"Opening map failed:\n" errormsg += u"File: "+unicode(path, sys.getfilesystemencoding())+u"\n" errormsg += u"Error: "+unicode(sys.exc_info()[1]) ErrorDialog(errormsg) return None def reloadMapview(self, mapview=None): if mapview is None: mapview = self._mapview if mapview is None: print "Can't reload map: No maps are open." return path = mapview.getMap().getResourceLocation().getFilename() mapview.close() self.openFile(path) def saveAll(self): """ Saves all open maps """ tmpview = self._mapview for mapview in self._mapviewlist: self._mapview = mapview self._filemanager.save() self._mapview = tmpview def quit(self): """ Quits the editor. An onQuit signal is sent before the application closes """ events.onQuit.send(sender=self) self._settings.saveSettings() ApplicationBase.quit(self) def _pump(self): """ Called once per frame """ # ApplicationBase and Engine should be done initializing at this point if self._inited == False: self._initGui() self._initTools() if self._params: self.openFile(self._params) self._inited = True events.onPump.send(sender=self) def __sendMouseEvent(self, event, **kwargs): """ Function used to capture mouse events for EventListener """ ms_event = fife.MouseEvent type = event.getType() if type == ms_event.MOVED: mouseMoved.send(sender=self._maparea, event=event) elif type == ms_event.PRESSED: mousePressed.send(sender=self._maparea, event=event) elif type == ms_event.RELEASED: mouseReleased.send(sender=self._maparea, event=event) elif type == ms_event.WHEEL_MOVED_DOWN: mouseWheelMovedDown.send(sender=self._maparea, event=event) elif type == ms_event.WHEEL_MOVED_UP: mouseWheelMovedUp.send(sender=self._maparea, event=event) elif type == ms_event.CLICKED: mouseClicked.send(sender=self._maparea, event=event) elif type == ms_event.ENTERED: mouseEntered.send(sender=self._maparea, event=event) elif type == ms_event.EXITED: mouseExited.send(sender=self._maparea, event=event) elif type == ms_event.DRAGGED: mouseDragged.send(sender=self._maparea, event=event) def __sendKeyEvent(self, event, **kwargs): """ Function used to capture key events for EventListener """ type = event.getType() if type == fife.KeyEvent.PRESSED: keyPressed.send(sender=self._maparea, event=event) elif type == fife.KeyEvent.RELEASED: keyReleased.send(sender=self._maparea, event=event)
class Editor(ApplicationBase, MainWindow): """ Editor sets up all subsystems and provides access to them """ editor = None def __init__(self, options, mapfile, *args, **kwargs): Editor.editor = self self._filemanager = None self._options = options self._mapfile = mapfile self._eventlistener = None self._pluginmanager = None self._inited = False self._mapview = None self._mapviewlist = [] self._mapgroup = None self._mapbar = None self._maparea = None self._mapeditor = None self._file_menu = None self._edit_menu = None self._view_menu = None self._tools_menu = None self._help_menu = None self._change_map = -1 self._settings = TDS self._lighting_mode = int(TDS.get("FIFE", "Lighting")) self._help_dialog = None ApplicationBase.__init__(self, TDS, *args, **kwargs) MainWindow.__init__(self, *args, **kwargs) def _initTools(self): """ Initializes tools """ if self._options.plugin_dir is not None: sys.path.append(os.path.abspath(self._options.plugin_dir)) self._pluginmanager = plugin.PluginManager(self.getSettings(), self._options.plugin_dir) self._filemanager = FileManager() self._toolbar.adaptLayout() self._mapeditor = MapEditor() def _initGui(self): """ Sets up the GUI """ screen_width = self.engine.getSettings().getScreenWidth() screen_height = self.engine.getSettings().getScreenHeight() MainWindow.initGui(self, screen_width, screen_height) self._toolbox = ToolBar(title=u"", orientation=1) self._toolbox.position_technique = "explicit" self._toolbox.position = (150, 150) self._mapbar = ToolBar(name="MapBar", panel_size=20) self._mapbar.setDocked(True) self._maparea = pychan.widgets.VBox() self._maparea.opaque = False self._maparea.is_focusable = True # Capture mouse and key events for EventListener cw = self._maparea cw.capture(self.__sendMouseEvent, "mouseEntered") cw.capture(self.__sendMouseEvent, "mouseExited") cw.capture(self.__sendMouseEvent, "mousePressed") cw.capture(self.__sendMouseEvent, "mouseReleased") cw.capture(self.__sendMouseEvent, "mouseClicked") cw.capture(self.__sendMouseEvent, "mouseMoved") cw.capture(self.__sendMouseEvent, "mouseWheelMovedUp") cw.capture(self.__sendMouseEvent, "mouseWheelMovedDown") cw.capture(self.__sendMouseEvent, "mouseDragged") cw.capture(self.__sendKeyEvent, "keyPressed") cw.capture(self.__sendKeyEvent, "keyReleased") self._centralwidget.addChild(self._mapbar) self._centralwidget.addChild(self._maparea) self._initActions() self._toolbox.show() events.preMapClosed.connect(self._mapRemoved) def _initActions(self): """ Initializes toolbar and menubar buttons """ exitAction = Action(u"Exit", "gui/icons/quit.png") exitAction.helptext = u"Exit program" action.activated.connect(self.quit, sender=exitAction) self._file_menu = Menu(name=u"File") self._file_menu.addAction(exitAction) self._edit_menu = Menu(name=u"Edit") self._view_menu = Menu(name=u"View") self._tools_menu = Menu(name=u"Tools") self._window_menu = Menu(name=u"Window") self._help_menu = Menu(name=u"Help") self._action_show_statusbar = Action(u"Statusbar") self._action_show_statusbar.helptext = u"Toggle statusbar" action.activated.connect(self.toggleStatusbar, sender=self._action_show_statusbar) self._action_show_toolbar = Action(u"Toolbar") self._action_show_toolbar.helptext = u"Toggle toolbar" action.activated.connect(self.toggleToolbar, sender=self._action_show_toolbar) self._action_show_toolbox = Action(u"Tool box") self._action_show_toolbox.helptext = u"Toggle tool box" action.activated.connect(self.toggleToolbox, sender=self._action_show_toolbox) self._view_menu.addAction(self._action_show_statusbar) self._view_menu.addAction(self._action_show_toolbar) self._view_menu.addAction(self._action_show_toolbox) self._view_menu.addSeparator() test_action1 = Action(u"Cycle buttonstyles", "gui/icons/cycle_styles.png") test_action1.helptext = u"Cycles button styles. There are currently four button styles." action.activated.connect(self._actionActivated, sender=test_action1) self._view_menu.addAction(test_action1) test_action2 = Action(u"Toggle Blocking") test_action2.helptext = u"Toggles the blocking infos for the instances." action.activated.connect(self.toggleBlocking, sender=test_action2) self._view_menu.addAction(test_action2) test_action3 = Action(u"Toggle Grid") test_action3.helptext = u"Toggles the grids of the map." action.activated.connect(self.toggleGrid, sender=test_action3) self._view_menu.addAction(test_action3) test_action4 = Action(u"Toggle Coordinates") test_action4.helptext = u"Toggles the coordinates of the map." action.activated.connect(self.toggleCoordinates, sender=test_action4) self._view_menu.addAction(test_action4) self._mapgroup = ActionGroup(exclusive=True, name="Mapgroup") self._mapbar.addAction(self._mapgroup) self._window_menu.addAction(self._mapgroup) help_action = Action(u"Help", "gui/icons/help.png") help_action.helptext = u"Displays a window with some simple instructions" action.activated.connect(self._showHelpDialog, sender=help_action) self._help_menu.addAction(help_action) self._menubar.addMenu(self._file_menu) self._menubar.addMenu(self._edit_menu) self._menubar.addMenu(self._view_menu) self._menubar.addMenu(self._tools_menu) self._menubar.addMenu(self._window_menu) self._menubar.addMenu(self._help_menu) def _actionActivated(self, sender): self._toolbar.button_style += 1 def _showHelpDialog(self, sender): """ Shows the help dialog """ if self._help_dialog is not None: self._help_dialog.show() return self._help_dialog = pychan.loadXML("gui/help.xml") self._help_dialog.findChild(name="closeButton").capture(self._help_dialog.hide) f = open('lang/infotext.txt', 'r') self._help_dialog.findChild(name="helpText").text = unicode(f.read()) f.close() self._help_dialog.show() def toggleStatusbar(self): """ Toggles status bar """ statusbar = self.getStatusBar() if statusbar.max_size[1] > 0: statusbar.min_size=(statusbar.min_size[0], 0) statusbar.max_size=(statusbar.max_size[0], 0) self._action_show_statusbar.setChecked(False) else: statusbar.min_size=(statusbar.min_size[0], statusbar.min_size[0]) statusbar.max_size=(statusbar.max_size[0], statusbar.max_size[0]) self._action_show_statusbar.setChecked(True) statusbar.adaptLayout() def toggleToolbar(self): """ Toggles toolbar """ toolbar = self.getToolBar() if toolbar.isVisible(): toolbar.setDocked(False) toolbar.hide() self._action_show_toolbar.setChecked(False) else: tx = toolbar.x ty = toolbar.y toolbar.show() toolbar.x = tx toolbar.y = ty self._action_show_toolbar.setChecked(True) def toggleToolbox(self): """ Toggles tool box """ toolbox = self.getToolbox() if toolbox.isVisible(): toolbox.setDocked(False) toolbox.hide() self._action_show_toolbox.setChecked(False) else: tx = toolbox.x ty = toolbox.y toolbox.show() toolbox.x = tx toolbox.y = ty self._action_show_toolbox.setChecked(True) toolbox.adaptLayout() def toggleBlocking(self, sender): if self._mapview is not None: for cam in self._mapview.getMap().getCameras(): r = fife.BlockingInfoRenderer.getInstance(cam) r.setEnabled(not r.isEnabled()) def toggleGrid(self, sender): if self._mapview is not None: for cam in self._mapview.getMap().getCameras(): r = fife.GridRenderer.getInstance(cam) r.setEnabled(not r.isEnabled()) def toggleCoordinates(self, sender): if self._mapview is not None: for cam in self._mapview.getMap().getCameras(): r = fife.CoordinateRenderer.getInstance(cam) if not r.isEnabled(): r.clearActiveLayers() color = str(self._settings.get("Colors", "Coordinate", "255,255,255")) r.setColor(*[int(c) for c in color.split(',')]) for layer in self._mapview.getMap().getLayers(): if layer.areInstancesVisible(): r.addActiveLayer(layer) r.setEnabled(True) else: r.setEnabled(False) def getToolbox(self): return self._toolbox def getPluginManager(self): return self._pluginmanager def getEngine(self): return self.engine def getMapViews(self): return self._mapviewlist def getActiveMapView(self): return self._mapview def getSettings(self): return self._settings; def getObject(self): return self._mapeditor.getObject() def showMapView(self, mapview): """ Switches to mapview. """ if mapview is None or mapview == self._mapview: return if self._mapview != None and mapview != self._mapview: # need to disable the cameras from the previous map # if it exists before switching if self._mapview.getMap() != None: for cam in self._mapview.getMap().getCameras(): cam.setEnabled(False) # if light model is set then enable LightRenderer for all layers if self._lighting_mode is not 0: for cam in mapview.getMap().getCameras(): renderer = fife.LightRenderer.getInstance(cam) renderer.activateAllLayers(mapview.getMap()) renderer.setEnabled(not renderer.isEnabled()) events.preMapShown.send(sender=self, mapview=mapview) self._mapview = mapview self._mapview.show() events.postMapShown.send(sender=self, mapview=mapview) def createListener(self): """ Creates the event listener. This is called by ApplicationBase """ if self._eventlistener is None: self._eventlistener = EventListener(self.engine) return self._eventlistener def getEventListener(self): """ Returns the event listener """ return self._eventlistener def newMapView(self, map): """ Creates a new map view """ mapview = MapView(map) self._mapviewlist.append(mapview) map_action = Action(unicode(map.getId())) action.activated.connect(cbwa(self.showMapView, mapview), sender=map_action, weak=False) self._mapgroup.addAction(map_action) self.showMapView(mapview) events.mapAdded.send(sender=self, map=map) return mapview def _mapRemoved(self, mapview): index = self._mapviewlist.index(mapview)-1 for cam in mapview.getMap().getCameras(): cam.setEnabled(False) self._mapviewlist.remove(mapview) # Remove tab for map_action in self._mapgroup.getActions(): if map_action.text == unicode(mapview.getMap().getId()): self._mapgroup.removeAction(map_action) break # Change mapview if len(self._mapviewlist) > 0: if index < 0: index = 0 self._change_map = index else: self._mapview = None def openFile(self, path): """ Opens a file """ try: if self._lighting_mode == 0: map = loaders.loadMapFile(path, self.engine) else: map = loaders.loadMapFile(path, self.engine, extensions = {'lights': True}) return self.newMapView(map) except: traceback.print_exc(sys.exc_info()[1]) errormsg = u"Opening map failed:\n" errormsg += u"File: "+unicode(path, sys.getfilesystemencoding())+u"\n" errormsg += u"Error: "+unicode(sys.exc_info()[1]) ErrorDialog(errormsg) return None def saveAll(self): """ Saves all open maps """ tmpview = self._mapview for mapview in self._mapviewlist: self._mapview = mapview self._filemanager.save() self._mapview = tmpview def quit(self): """ Quits the editor. An onQuit signal is sent before the application closes """ events.onQuit.send(sender=self) self._settings.saveSettings() ApplicationBase.quit(self) def _pump(self): """ Called once per frame """ # ApplicationBase and Engine should be done initializing at this point if self._inited == False: self._initGui() self._initTools() if self._mapfile: self.openFile(self._mapfile) self._inited = True # FIXME: This isn't very nice, but it is needed to change the map # outside the callback. if self._change_map >= 0 and len(self._mapviewlist) > 0: if self._change_map >= len(self._mapviewlist): self._change_map = len(self._mapviewlist)-1 mapview = self._mapviewlist[self._change_map] self.showMapView(mapview) self._change_map = -1 events.onPump.send(sender=self) def __sendMouseEvent(self, event, **kwargs): """ Function used to capture mouse events for EventListener """ ms_event = fife.MouseEvent type = event.getType() if type == ms_event.MOVED: mouseMoved.send(sender=self._maparea, event=event) elif type == ms_event.PRESSED: mousePressed.send(sender=self._maparea, event=event) elif type == ms_event.RELEASED: mouseReleased.send(sender=self._maparea, event=event) elif type == ms_event.WHEEL_MOVED_DOWN: mouseWheelMovedDown.send(sender=self._maparea, event=event) elif type == ms_event.WHEEL_MOVED_UP: mouseWheelMovedUp.send(sender=self._maparea, event=event) elif type == ms_event.CLICKED: mouseClicked.send(sender=self._maparea, event=event) elif type == ms_event.ENTERED: mouseEntered.send(sender=self._maparea, event=event) elif type == ms_event.EXITED: mouseExited.send(sender=self._maparea, event=event) elif type == ms_event.DRAGGED: mouseDragged.send(sender=self._maparea, event=event) def __sendKeyEvent(self, event, **kwargs): """ Function used to capture key events for EventListener """ type = event.getType() if type == fife.KeyEvent.PRESSED: keyPressed.send(sender=self._maparea, event=event) elif type == fife.KeyEvent.RELEASED: keyReleased.send(sender=self._maparea, event=event)
class Editor(ApplicationBase, MainWindow): """ Editor sets up all subsystems and provides access to them """ editor = None def __init__(self, options, mapfile, *args, **kwargs): Editor.editor = self self._filemanager = None self._options = options self._mapfile = mapfile self._eventlistener = None self._pluginmanager = None self._inited = False self._mapview = None self._mapviewlist = [] self._mapgroup = None self._mapbar = None self._maparea = None self._mapeditor = None self._file_menu = None self._edit_menu = None self._view_menu = None self._tools_menu = None self._help_menu = None self._change_map = -1 self._settings = TDS self._lighting_mode = int(TDS.get("FIFE", "Lighting")) self._help_dialog = None self._toolbar_docked = False self._toolbar_dockname = "" self._toolbox_docked = False self._toolbox_dockname = "" ApplicationBase.__init__(self, TDS, *args, **kwargs) MainWindow.__init__(self, *args, **kwargs) def _initTools(self): """ Initializes tools """ if self._options.plugin_dir is not None: sys.path.append(os.path.abspath(self._options.plugin_dir)) self._pluginmanager = plugin.PluginManager(self.getSettings(), self._options.plugin_dir) self._filemanager = FileManager() self._toolbar.adaptLayout() self._mapeditor = MapEditor() def _initGui(self): """ Sets up the GUI """ screen_width = self.engine.getSettings().getScreenWidth() screen_height = self.engine.getSettings().getScreenHeight() MainWindow.initGui(self, screen_width, screen_height) self._toolbox = ToolBar(name="ToolBox", title=u"", orientation=1) self._toolbox.position_technique = "explicit" self._toolbox.position = (150, 150) self._mapbar = ToolBar(name="MapBar", panel_size=20) self._mapbar.setDocked(True) self._maparea = pychan.widgets.VBox() self._maparea.opaque = False self._maparea.is_focusable = True # Capture mouse and key events for EventListener cw = self._maparea cw.capture(self.__sendMouseEvent, "mouseEntered") cw.capture(self.__sendMouseEvent, "mouseExited") cw.capture(self.__sendMouseEvent, "mousePressed") cw.capture(self.__sendMouseEvent, "mouseReleased") cw.capture(self.__sendMouseEvent, "mouseClicked") cw.capture(self.__sendMouseEvent, "mouseMoved") cw.capture(self.__sendMouseEvent, "mouseWheelMovedUp") cw.capture(self.__sendMouseEvent, "mouseWheelMovedDown") cw.capture(self.__sendMouseEvent, "mouseDragged") cw.capture(self.__sendKeyEvent, "keyPressed") cw.capture(self.__sendKeyEvent, "keyReleased") self._centralwidget.addChild(self._mapbar) self._centralwidget.addChild(self._maparea) self._initActions() self._toolbox.show() events.preMapClosed.connect(self._mapRemoved) def _initActions(self): """ Initializes toolbar and menubar buttons """ exitAction = Action(u"Exit", "gui/icons/quit.png") exitAction.helptext = u"Exit program" action.activated.connect(self.quit, sender=exitAction) self._file_menu = Menu(name=u"File") self._file_menu.addAction(exitAction) self._edit_menu = Menu(name=u"Edit") self._view_menu = Menu(name=u"View") self._tools_menu = Menu(name=u"Tools") self._window_menu = Menu(name=u"Window") self._help_menu = Menu(name=u"Help") self._action_show_statusbar = Action(u"Statusbar", checkable=True) self._action_show_statusbar.helptext = u"Toggle statusbar" action.activated.connect(self.toggleStatusbar, sender=self._action_show_statusbar) self._action_show_toolbar = Action(u"Toolbar", checkable=True) self._action_show_toolbar.helptext = u"Toggle toolbar" action.activated.connect(self.toggleToolbar, sender=self._action_show_toolbar) self._action_show_toolbox = Action(u"Tool box", checkable=True) self._action_show_toolbox.helptext = u"Toggle tool box" action.activated.connect(self.toggleToolbox, sender=self._action_show_toolbox) self._view_menu.addAction(self._action_show_statusbar) self._view_menu.addAction(self._action_show_toolbar) self._view_menu.addAction(self._action_show_toolbox) self._view_menu.addSeparator() #These 3 are enabled by default therefore should be checked self._action_show_statusbar.setChecked(True) self._action_show_toolbar.setChecked(True) self._action_show_toolbox.setChecked(True) test_action1 = Action(u"Cycle buttonstyles", "gui/icons/cycle_styles.png") test_action1.helptext = u"Cycles button styles. There are currently four button styles." action.activated.connect(self._actionActivated, sender=test_action1) self._view_menu.addAction(test_action1) test_action2 = Action(u"Toggle Blocking") test_action2.helptext = u"Toggles the blocking infos for the instances." action.activated.connect(self.toggleBlocking, sender=test_action2) self._view_menu.addAction(test_action2) test_action3 = Action(u"Toggle Grid") test_action3.helptext = u"Toggles the grids of the map." action.activated.connect(self.toggleGrid, sender=test_action3) self._view_menu.addAction(test_action3) test_action4 = Action(u"Toggle Coordinates") test_action4.helptext = u"Toggles the coordinates of the map." action.activated.connect(self.toggleCoordinates, sender=test_action4) self._view_menu.addAction(test_action4) self._mapgroup = ActionGroup(exclusive=True, name="Mapgroup") self._mapbar.addAction(self._mapgroup) self._window_menu.addAction(self._mapgroup) help_action = Action(u"Help", "gui/icons/help.png") help_action.helptext = u"Displays a window with some simple instructions" action.activated.connect(self._showHelpDialog, sender=help_action) self._help_menu.addAction(help_action) self._menubar.addMenu(self._file_menu) self._menubar.addMenu(self._edit_menu) self._menubar.addMenu(self._view_menu) self._menubar.addMenu(self._tools_menu) self._menubar.addMenu(self._window_menu) self._menubar.addMenu(self._help_menu) def _actionActivated(self, sender): self._toolbar.button_style += 1 def _showHelpDialog(self, sender): """ Shows the help dialog """ if self._help_dialog is not None: self._help_dialog.show() return self._help_dialog = pychan.loadXML("gui/help.xml") self._help_dialog.findChild(name="closeButton").capture( self._help_dialog.hide) f = open('lang/infotext.txt', 'r') self._help_dialog.findChild(name="helpText").text = unicode(f.read()) f.close() self._help_dialog.show() def toggleStatusbar(self): """ Toggles status bar """ statusbar = self.getStatusBar() if statusbar.max_size[1] > 0: statusbar.min_size = (statusbar.min_size[0], 0) statusbar.max_size = (statusbar.max_size[0], 0) self._action_show_statusbar.setChecked(False) else: statusbar.min_size = (statusbar.min_size[0], statusbar.min_size[0]) statusbar.max_size = (statusbar.max_size[0], statusbar.max_size[0]) self._action_show_statusbar.setChecked(True) statusbar.adaptLayout() def toggleToolbar(self): """ Toggles toolbar """ toolbar = self.getToolBar() if toolbar.isVisible(): self._toolbar_docked = toolbar.isDocked() self._toolbar_dockname = toolbar.dockareaname toolbar.hide() self._action_show_toolbar.setChecked(False) else: if not self._toolbar_docked: tx = toolbar.x ty = toolbar.y toolbar.show() toolbar.x = tx toolbar.y = ty else: toolbar.setDocked(True) self.dockWidgetTo(toolbar, self._toolbar_dockname) self._action_show_toolbar.setChecked(True) def toggleToolbox(self): """ Toggles tool box """ toolbox = self.getToolbox() if toolbox.isVisible(): self._toolbox_docked = toolbox.isDocked() self._toolbox_dockname = toolbox.dockareaname toolbox.hide() self._action_show_toolbox.setChecked(False) else: if not self._toolbox_docked: tx = toolbox.x ty = toolbox.y toolbox.show() toolbox.x = tx toolbox.y = ty else: toolbox.setDocked(True) self.dockWidgetTo(toolbox, self._toolbox_dockname) self._action_show_toolbox.setChecked(True) #toolbox.adaptLayout() def toggleBlocking(self, sender): if self._mapview is not None: for cam in self._mapview.getMap().getCameras(): r = fife.BlockingInfoRenderer.getInstance(cam) r.setEnabled(not r.isEnabled()) def toggleGrid(self, sender): if self._mapview is not None: for cam in self._mapview.getMap().getCameras(): r = fife.GridRenderer.getInstance(cam) r.setEnabled(not r.isEnabled()) def toggleCoordinates(self, sender): if self._mapview is not None: for cam in self._mapview.getMap().getCameras(): r = fife.CoordinateRenderer.getInstance(cam) if not r.isEnabled(): r.clearActiveLayers() color = str( self._settings.get("Colors", "Coordinate", "255,255,255")) r.setFont(get_manager().getDefaultFont()) r.setColor(*[int(c) for c in color.split(',')]) for layer in self._mapview.getMap().getLayers(): if layer.areInstancesVisible(): r.addActiveLayer(layer) r.setEnabled(True) else: r.setEnabled(False) def getToolbox(self): return self._toolbox def getPluginManager(self): return self._pluginmanager def getEngine(self): return self.engine def getMapViews(self): return self._mapviewlist def getActiveMapView(self): return self._mapview def getSettings(self): return self._settings def getObject(self): return self._mapeditor.getObject() def showMapView(self, mapview): """ Switches to mapview. """ if mapview is None or mapview == self._mapview: return if self._mapview != None and mapview != self._mapview: # need to disable the cameras from the previous map # if it exists before switching if self._mapview.getMap() != None: for cam in self._mapview.getMap().getCameras(): cam.resetRenderers() cam.setEnabled(False) # if light model is set then enable LightRenderer for all layers if self._lighting_mode is not 0: for cam in mapview.getMap().getCameras(): renderer = fife.LightRenderer.getInstance(cam) renderer.activateAllLayers(mapview.getMap()) renderer.setEnabled(not renderer.isEnabled()) events.preMapShown.send(sender=self, mapview=mapview) self._mapview = mapview self._mapview.show() events.postMapShown.send(sender=self, mapview=mapview) def createListener(self): """ Creates the event listener. This is called by ApplicationBase """ if self._eventlistener is None: self._eventlistener = EventListener(self.engine) return self._eventlistener def getEventListener(self): """ Returns the event listener """ return self._eventlistener def newMapView(self, map): """ Creates a new map view """ mapview = MapView(map) self._mapviewlist.append(mapview) map_action = Action(unicode(map.getId())) action.activated.connect(cbwa(self.showMapView, mapview), sender=map_action, weak=False) self._mapgroup.addAction(map_action) self.showMapView(mapview) events.mapAdded.send(sender=self, map=map) return mapview def _mapRemoved(self, mapview): index = self._mapviewlist.index(mapview) - 1 for cam in mapview.getMap().getCameras(): cam.resetRenderers() cam.setEnabled(False) self._mapviewlist.remove(mapview) # Remove tab for map_action in self._mapgroup.getActions(): if map_action.text == unicode(mapview.getMap().getId()): self._mapgroup.removeAction(map_action) break # Change mapview if len(self._mapviewlist) > 0: if index < 0: index = 0 self._change_map = index else: self._mapview = None def openFile(self, path): """ Opens a file """ parts = path.split(os.sep) for mapview in self._mapviewlist: if path == mapview._map.getFilename(): self.getStatusBar( ).text = u"Map already loaded, omitting map " + parts[-1] return events.onOpenMapFile.send(sender=self, path=path) try: map = None fife_loader = fife.MapLoader(self.engine.getModel(), self.engine.getVFS(), self.engine.getImageManager(), self.engine.getRenderBackend()) if self._lighting_mode == 0 and fife_loader.isLoadable(path): map = fife_loader.load(path) else: # TODO: vtchill - once lights are supported by the c++ map loader this can be removed map = loaders.loadMapFile(path, self.engine, extensions={'lights': True}) if map: self.getStatusBar().text = u"Loaded map: " + parts[-1] return self.newMapView(map) else: self.getStatusBar( ).text = u"Map could not be loaded: " + parts[-1] return None except: traceback.print_exc(sys.exc_info()[1]) errormsg = u"Opening map failed:\n" errormsg += u"File: " + unicode( path, sys.getfilesystemencoding()) + u"\n" errormsg += u"Error: " + unicode(sys.exc_info()[1]) ErrorDialog(errormsg) return None def saveAll(self): """ Saves all open maps """ tmpview = self._mapview for mapview in self._mapviewlist: self._mapview = mapview self._filemanager.save() self._mapview = tmpview def quit(self): """ Quits the editor. An onQuit signal is sent before the application closes """ events.onQuit.send(sender=self) self._pluginmanager.stop() self._settings.saveSettings() ApplicationBase.quit(self) def _pump(self): """ Called once per frame """ # ApplicationBase and Engine should be done initializing at this point if self._inited == False: self._initGui() self._initTools() if self._mapfile: self.openFile(self._mapfile) self._inited = True # FIXME: This isn't very nice, but it is needed to change the map # outside the callback. if self._change_map >= 0 and len(self._mapviewlist) > 0: if self._change_map >= len(self._mapviewlist): self._change_map = len(self._mapviewlist) - 1 mapview = self._mapviewlist[self._change_map] self.showMapView(mapview) self._change_map = -1 events.onPump.send(sender=self) def __sendMouseEvent(self, event, **kwargs): """ Function used to capture mouse events for EventListener """ ms_event = fife.MouseEvent type = event.getType() if type == ms_event.MOVED: mouseMoved.send(sender=self._maparea, event=event) elif type == ms_event.PRESSED: mousePressed.send(sender=self._maparea, event=event) elif type == ms_event.RELEASED: mouseReleased.send(sender=self._maparea, event=event) elif type == ms_event.WHEEL_MOVED_DOWN: mouseWheelMovedDown.send(sender=self._maparea, event=event) elif type == ms_event.WHEEL_MOVED_UP: mouseWheelMovedUp.send(sender=self._maparea, event=event) elif type == ms_event.CLICKED: mouseClicked.send(sender=self._maparea, event=event) elif type == ms_event.ENTERED: mouseEntered.send(sender=self._maparea, event=event) elif type == ms_event.EXITED: mouseExited.send(sender=self._maparea, event=event) elif type == ms_event.DRAGGED: mouseDragged.send(sender=self._maparea, event=event) def __sendKeyEvent(self, event, **kwargs): """ Function used to capture key events for EventListener """ type = event.getType() if type == fife.KeyEvent.PRESSED: keyPressed.send(sender=self._maparea, event=event) elif type == fife.KeyEvent.RELEASED: keyReleased.send(sender=self._maparea, event=event)
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)