class gtoRemote(QObject): def __init__(self, gtomain, parent=None): try: super(gtoRemote, self).__init__(parent) self.gtomain = gtomain self.iface = gtomain.iface self.debug = gtomain.debug self.info = gtoInfo(self) self.fs_watcher = None if 'remote_watch_file' in gtomain.settings: remote_watch_path = gtomain.settings.get( 'remote_watch_file', None) if remote_watch_path is not None and remote_watch_path != "": remote_watch_path = self.gtomain.helper.getFilePath( remote_watch_path) self.remote_watch_file = os.path.basename( remote_watch_path) self.remote_watch_dir = os.path.dirname(remote_watch_path) if self.debug: self.info.log("Watching:", self.remote_watch_dir) if not os.path.exists(self.remote_watch_dir): os.makedirs(self.remote_watch_dir) if self.debug: self.info.log("Created:", self.remote_watch_dir) self.paths = [self.remote_watch_dir] self.fs_watcher = QFileSystemWatcher(self.paths) #if file already exists self.directory_changed(self.paths[0]) self.fs_watcher.directoryChanged.connect( self.directory_changed) self.fs_watcher.fileChanged.connect(self.file_changed) except Exception as e: self.info.err(e) def unload(self): try: if self.fs_watcher is not None: self.fs_watcher.directoryChanged.disconnect() self.fs_watcher.fileChanged.disconnect() self.fs_watcher = None except Exception as e: self.info.err(e) def directory_changed(self, path): try: if self.debug: self.info.log('Directory Changed: %s' % path) for f in os.listdir(path): #self.info.log(os.listdir(path)) #if (self.debug and f.lower().endswith(".json")) or f.lower() == self.remote_watch_file.lower(): if f.lower() == self.remote_watch_file.lower(): if self.debug: self.info.log("Execute", f.lower()) self.fs_watcher.blockSignals(True) self.excuteCommand(path, f) self.fs_watcher.blockSignals(False) except Exception as e: self.info.err(e) def file_changed(self, path): try: if self.debug: self.info.log('File Changed: %s' % path) except Exception as e: self.info.err(e) def excuteCommand(self, path, f): try: if self.debug: self.info.log('excute command') filename = path + '/' + f #time.sleep(0.5) f = io.open(filename, encoding='utf-8') jdata = json.load(f) f.close() res = True for cmd in jdata['commands']: if self.debug: self.info.log(cmd) method = getattr(self, cmd['ecommand']) res = res and (method(self.gtomain, self.debug, ** cmd['config'])) if self.debug: self.info.log('result:', res) if res: os.remove(filename) except Exception as e: self.info.err(e) def writeRemoteFile(self, jdata, prefix=''): try: if self.debug: self.info.log('writeRemoteFile:', 'data:', jdata) remotefile = self.gtomain.settings['remote_file'] remotefile = self.gtomain.helper.getFilePath(remotefile, True) remotefile = '%s%s' % (remotefile, prefix) if self.debug: self.info.log("remotefile", remotefile) # write the file # from io import StringIO # io = StringIO() # json.dump(jdata,io,ensure_ascii=False, sort_keys=True,indent=4) # io.close() with open(remotefile, 'w', encoding='utf8') as outfile: sort = True #simplejson.dump(jdata, outfile,ensure_ascii=False, sort_keys=sort,indent=4)#,encoding='utf8')#.encode('utf8') json.dump(jdata, outfile, ensure_ascii=False, sort_keys=sort, indent=4) # ,encoding='utf8')#.encode('utf8') # import pickle # with open(remotefile, 'wb') as f: # pickle.dump(jdata,f) #activate/start remote app if self.debug: self.info.log('writeRemoteFile:', 'settings:', self.gtomain.settings) remote_app_file = self.gtomain.settings['remote_app_file'] remote_app_title = self.gtomain.settings['remote_app_title'] if os.name == 'nt': try: from .gto_windows import ActivateApp ActivateApp(self.gtomain, self.debug, remote_app_title, remote_app_file) except Exception as e: self.info.err(e) else: os.startfile(remote_app_file) except Exception as e: self.info.err(e) def getLayerByName(self, layername): try: layers = QgsProject.instance().mapLayersByName(layername) if layers: return layers[0] # duplicte names => take the first else: return None except Exception as e: self.info.err(e) def getFeatures(self, gtoobj, debug, **kwargs): try: if self.debug: self.info.log('getFeatures:', 'parameters:', kwargs) layername = kwargs['objectclass'] layer = self.getLayerByName(layername) request = QgsFeatureRequest() if 'whereclause' in kwargs: whereclause = kwargs['whereclause'] request.setFilterExpression(whereclause) elif 'attribute' in kwargs: attribute = kwargs['attribute'] values = kwargs['data'] expr_in = '' for v in values: expr_in = expr_in + '%s ,' % str(v) expr_in = expr_in[:-1] expr = '"' + attribute + '" IN (%s)' % expr_in if self.debug: self.info.log("expr: %s" % expr) request.setFilterExpression(expr) features = layer.getFeatures(request) ids = [f.id() for f in features] if self.debug: self.info.log("res from request ids:", layer, ids) return layer, ids except Exception as e: gtoobj.info.err(e) def ZOOMTOFEATURESET(self, gtoobj, debug, **kwargs): try: scale = kwargs.get('scale', 0) iface = gtoobj.iface layer, ids = self.getFeatures(gtoobj, debug, **kwargs) iface.setActiveLayer(layer) prj = QgsProject.instance() prj.layerTreeRoot().findLayer( layer.id()).setItemVisibilityCheckedParentRecursive(True) #legend.setCurrentLayer(layer) #legend.setLayerVisible(layer, True) layer.selectByIds(ids) iface.mapCanvas().zoomToSelected() if scale > 0: iface.mapCanvas().zoomScale(scale) return True except Exception as e: gtoobj.info.err(e) def SETSELECTSET(self, gtoobj, debug, **kwargs): try: iface = gtoobj.iface layer, ids = self.getFeatures(gtoobj, debug, **kwargs) layer.removeSelection() layer.selectByIds(ids) self.iface.mapCanvas().refresh() return True except Exception as e: gtoobj.info.err(e) def GETCOORDINATE(self, gtoobj, debug, **kwargs): try: objclass = kwargs['objectclass'] id = kwargs['id'] esubcommand = kwargs['esubcommand'] iface = gtoobj.iface from qgis.gui import QgsMapToolEmitPoint # create tool prevTool = iface.mapCanvas().mapTool() curTool = QgsMapToolEmitPoint(iface.mapCanvas()) def on_click(coordinate, clickedMouseButton): if debug: gtoobj.info.log("Coordinate:", coordinate) if clickedMouseButton == Qt.LeftButton: if esubcommand == 'GETCOORDINATE_ID': #jdata = {"commands": [{"ecommand": "SETCOORDINATE", "config": {"esubcommand": "SETCOORDINATE_ID","objectclass": objclass.encode('utf8'),"id":id, "x": round( coordinate.x(),3),"y":round(coordinate.y(),3)}}]} jdata = { "commands": [{ "ecommand": "SETCOORDINATE", "config": { "esubcommand": "SETCOORDINATE_ID", "objectclass": objclass, "id": id, "x": round(coordinate.x(), 3), "y": round(coordinate.y(), 3) } }] } self.writeRemoteFile(jdata) if debug: self.info.log("Set prev tool:", prevTool.toolName()) if prevTool is curTool: iface.mapCanvas().setMapTool(None) else: iface.mapCanvas().setMapTool(prevTool) else: if debug: self.info.log('Unknown esubcommand:', esubcommand) def tool_changed(tool): # another tool was activated iface.mapCanvas().mapToolSet.disconnect(tool_changed) #curTool.deleteLater() curTool.canvasClicked.connect(on_click) iface.mapCanvas().setMapTool(curTool) iface.mapCanvas().mapToolSet.connect(tool_changed) return True except Exception as e: gtoobj.info.err(e) def getSelectedFeatures(self, gtoobj, debug, layer, attribute): try: data = [] for f in layer.selectedFeatures(): val = f[attribute] try: if int(val) == val: val = int(val) except: pass data.append("%s" % str(val)) return data except Exception as e: gtoobj.info.err(e)
class Editor(CodeEditor, ComponentMixin): name = 'Code Editor' # This signal is emitted whenever the currently-open file changes and # autoreload is enabled. triggerRerender = pyqtSignal(bool) sigFilenameChanged = pyqtSignal(str) preferences = Parameter.create(name='Preferences', children=[{ 'name': 'Font size', 'type': 'int', 'value': 12 }, { 'name': 'Autoreload', 'type': 'bool', 'value': False }, { 'name': 'Autoreload delay', 'type': 'int', 'value': 50 }, { 'name': 'Autoreload: watch imported modules', 'type': 'bool', 'value': False }, { 'name': 'Line wrap', 'type': 'bool', 'value': False }, { 'name': 'Color scheme', 'type': 'list', 'values': ['Spyder', 'Monokai', 'Zenburn'], 'value': 'Spyder' }]) EXTENSIONS = 'py' def __init__(self, parent=None): self._watched_file = None super(Editor, self).__init__(parent) ComponentMixin.__init__(self) self.setup_editor(linenumbers=True, markers=True, edge_line=False, tab_mode=False, show_blanks=True, font=QFontDatabase.systemFont( QFontDatabase.FixedFont), language='Python', filename='') self._actions = \ {'File' : [QAction(icon('new'), 'New', self, shortcut='ctrl+N', triggered=self.new), QAction(icon('open'), 'Open', self, shortcut='ctrl+O', triggered=self.open), QAction(icon('save'), 'Save', self, shortcut='ctrl+S', triggered=self.save), QAction(icon('save_as'), 'Save as', self, shortcut='ctrl+shift+S', triggered=self.save_as), QAction(icon('autoreload'), 'Automatic reload and preview', self,triggered=self.autoreload, checkable=True, checked=False, objectName='autoreload'), ]} for a in self._actions.values(): self.addActions(a) self._fixContextMenu() # autoreload support self._file_watcher = QFileSystemWatcher(self) # we wait for 50ms after a file change for the file to be written completely self._file_watch_timer = QTimer(self) self._file_watch_timer.setInterval( self.preferences['Autoreload delay']) self._file_watch_timer.setSingleShot(True) self._file_watcher.fileChanged.connect( lambda val: self._file_watch_timer.start()) self._file_watch_timer.timeout.connect(self._file_changed) self.updatePreferences() def _fixContextMenu(self): menu = self.menu menu.removeAction(self.run_cell_action) menu.removeAction(self.run_cell_and_advance_action) menu.removeAction(self.run_selection_action) menu.removeAction(self.re_run_last_cell_action) def updatePreferences(self, *args): self.set_color_scheme(self.preferences['Color scheme']) font = self.font() font.setPointSize(self.preferences['Font size']) self.set_font(font) self.findChild(QAction, 'autoreload') \ .setChecked(self.preferences['Autoreload']) self._file_watch_timer.setInterval( self.preferences['Autoreload delay']) self.toggle_wrap_mode(self.preferences['Line wrap']) self._clear_watched_paths() self._watch_paths() def confirm_discard(self): if self.modified: rv = confirm( self, 'Please confirm', 'Current document is not saved - do you want to continue?') else: rv = True return rv def new(self): if not self.confirm_discard(): return self.set_text('') self.filename = '' self.reset_modified() def open(self): if not self.confirm_discard(): return curr_dir = Path(self.filename).abspath().dirname() fname = get_open_filename(self.EXTENSIONS, curr_dir) if fname != '': self.load_from_file(fname) def load_from_file(self, fname): self.set_text_from_file(fname) self.filename = fname self.reset_modified() def save(self): if self._filename != '': if self.preferences['Autoreload']: self._file_watcher.blockSignals(True) self._file_watch_timer.stop() with open(self._filename, 'w') as f: f.write(self.toPlainText()) if self.preferences['Autoreload']: self._file_watcher.blockSignals(False) self.triggerRerender.emit(True) self.reset_modified() else: self.save_as() def save_as(self): fname = get_save_filename(self.EXTENSIONS) if fname != '': with open(fname, 'w') as f: f.write(self.toPlainText()) self.filename = fname self.reset_modified() def _update_filewatcher(self): if self._watched_file and (self._watched_file != self.filename or not self.preferences['Autoreload']): self._clear_watched_paths() self._watched_file = None if self.preferences[ 'Autoreload'] and self.filename and self.filename != self._watched_file: self._watched_file = self._filename self._watch_paths() @property def filename(self): return self._filename @filename.setter def filename(self, fname): self._filename = fname self._update_filewatcher() self.sigFilenameChanged.emit(fname) def _clear_watched_paths(self): paths = self._file_watcher.files() if paths: self._file_watcher.removePaths(paths) def _watch_paths(self): if Path(self._filename).exists(): self._file_watcher.addPath(self._filename) if self.preferences['Autoreload: watch imported modules']: module_paths = self.get_imported_module_paths(self._filename) if module_paths: self._file_watcher.addPaths(module_paths) # callback triggered by QFileSystemWatcher def _file_changed(self): # neovim writes a file by removing it first so must re-add each time self._watch_paths() self.set_text_from_file(self._filename) self.triggerRerender.emit(True) # Turn autoreload on/off. def autoreload(self, enabled): self.preferences['Autoreload'] = enabled self._update_filewatcher() def reset_modified(self): self.document().setModified(False) @property def modified(self): return self.document().isModified() def saveComponentState(self, store): if self.filename != '': store.setValue(self.name + '/state', self.filename) def restoreComponentState(self, store): filename = store.value(self.name + '/state') if filename and self.filename == '': try: self.load_from_file(filename) except IOError: self._logger.warning(f'could not open {filename}') def get_imported_module_paths(self, module_path): finder = ModuleFinder([os.path.dirname(module_path)]) imported_modules = [] try: finder.run_script(module_path) except SyntaxError as err: self._logger.warning(f'Syntax error in {module_path}: {err}') except Exception as err: self._logger.warning( f'Cannot determine imported modules in {module_path}: {type(err).__name__} {err}' ) else: for module_name, module in finder.modules.items(): if module_name != '__main__': path = getattr(module, '__file__', None) if path is not None and os.path.isfile(path): imported_modules.append(path) return imported_modules
class MainWindow(QMainWindow): OnlineHelpUrl = QUrl("https://eth-cscs.github.io/serialbox2/sdb.html") def __init__(self): super().__init__() Logger.info("Setup main window") self.__input_serializer_data = SerializerData("Input Serializer") self.__input_stencil_data = StencilData(self.__input_serializer_data) self.__reference_serializer_data = SerializerData( "Reference Serializer") self.__reference_stencil_data = StencilData( self.__reference_serializer_data) self.__stencil_field_mapper = StencilFieldMapper( self.__input_stencil_data, self.__reference_stencil_data, GlobalConfig()["async"]) self.__file_system_watcher = QFileSystemWatcher() self.__file_system_watcher.directoryChanged[str].connect( self.popup_reload_box) self.__file_system_watcher_last_modify = time() # Load from session? self.__session_manager = SessionManager() if GlobalConfig()["default_session"]: self.__session_manager.load_from_file() self.__session_manager.set_serializer_data( self.__input_serializer_data) self.__session_manager.set_serializer_data( self.__reference_serializer_data) # Setup GUI self.setWindowTitle('sdb - stencil debugger (%s)' % Version().sdb_version()) self.resize(1200, 600) if GlobalConfig()["center_window"]: self.center() if GlobalConfig()["move_window"]: self.move(GlobalConfig()["move_window"]) self.setWindowIcon(Icon("logo-small.png")) self.init_menu_tool_bar() # Tabs self.__tab_highest_valid_state = TabState.Setup self.__widget_tab = QTabWidget(self) # Setup tab self.__widget_tab.addTab( SetupWindow(self, self.__input_serializer_data, self.__reference_serializer_data), "Setup") # Stencil tab self.__widget_tab.addTab( StencilWindow(self, self.__stencil_field_mapper, self.__input_stencil_data, self.__reference_stencil_data), "Stencil") # Result tab self.__widget_tab.addTab( ResultWindow(self, self.__widget_tab.widget(TabState.Stencil.value), self.__stencil_field_mapper), "Result") # Error tab self.__widget_tab.addTab(ErrorWindow(self), "Error") self.__widget_tab.currentChanged.connect(self.switch_to_tab) self.__widget_tab.setTabEnabled(TabState.Setup.value, True) self.__widget_tab.setTabEnabled(TabState.Stencil.value, False) self.__widget_tab.setTabEnabled(TabState.Result.value, False) self.__widget_tab.setTabEnabled(TabState.Error.value, False) self.__widget_tab.setTabToolTip(TabState.Setup.value, "Setup Input and Refrence Serializer") self.__widget_tab.setTabToolTip( TabState.Stencil.value, "Set the stencil to compare and define the mapping of the fields") self.__widget_tab.setTabToolTip(TabState.Result.value, "View to comparison result") self.__widget_tab.setTabToolTip( TabState.Error.value, "Detailed error desscription of the current field") self.__tab_current_state = TabState.Setup self.set_tab_highest_valid_state(TabState.Setup) self.switch_to_tab(TabState.Setup) self.setCentralWidget(self.__widget_tab) # If the MainWindow is closed, kill all popup windows self.setAttribute(Qt.WA_DeleteOnClose) Logger.info("Starting main loop") self.show() def init_menu_tool_bar(self): Logger.info("Setup menu toolbar") action_exit = QAction("Exit", self) action_exit.setShortcut("Ctrl+Q") action_exit.setStatusTip("Exit the application") action_exit.triggered.connect(self.close) action_about = QAction("&About", self) action_about.setStatusTip("Show the application's About box") action_about.triggered.connect(self.popup_about_box) action_save_session = QAction(Icon("filesave.png"), "&Save", self) action_save_session.setStatusTip("Save current session") action_save_session.setShortcut("Ctrl+S") action_save_session.triggered.connect(self.save_session) action_open_session = QAction(Icon("fileopen.png"), "&Open", self) action_open_session.setShortcut("Ctrl+O") action_open_session.setStatusTip("Open session") action_open_session.triggered.connect(self.open_session) action_help = QAction(Icon("help.png"), "&Online Help", self) action_help.setStatusTip("Online Help") action_help.setToolTip("Online Help") action_help.triggered.connect(self.go_to_online_help) self.__action_continue = QAction(Icon("next_cursor.png"), "Continue", self) self.__action_continue.setStatusTip("Continue to next tab") self.__action_continue.triggered.connect(self.switch_to_next_tab) self.__action_continue.setEnabled(True) self.__action_back = QAction(Icon("prev_cursor.png"), "Back", self) self.__action_back.setStatusTip("Back to previous tab") self.__action_back.triggered.connect(self.switch_to_previous_tab) self.__action_back.setEnabled(False) self.__action_reload = QAction(Icon("step_in.png"), "Reload", self) self.__action_reload.setStatusTip( "Reload Input and Reference Serializer") self.__action_reload.setShortcut("Ctrl+R") self.__action_reload.triggered.connect(self.reload_serializer) self.__action_reload.setEnabled(False) self.__action_try_switch_to_error_tab = QAction( Icon("visualize.png"), "Detailed error description", self) self.__action_try_switch_to_error_tab.setStatusTip( "Detailed error desscription of the current field") self.__action_try_switch_to_error_tab.triggered.connect( self.try_switch_to_error_tab) self.__action_try_switch_to_error_tab.setEnabled(False) menubar = self.menuBar() menubar.setNativeMenuBar(False) self.statusBar() file_menu = menubar.addMenu('&File') file_menu.addAction(action_open_session) file_menu.addAction(action_save_session) file_menu.addAction(action_exit) edit_menu = menubar.addMenu('&Edit') edit_menu.addAction(self.__action_back) edit_menu.addAction(self.__action_continue) edit_menu.addAction(self.__action_reload) help_menu = menubar.addMenu('&Help') help_menu.addAction(action_about) help_menu.addAction(action_help) toolbar = self.addToolBar("Toolbar") toolbar.addAction(action_help) toolbar.addAction(action_open_session) toolbar.addAction(action_save_session) toolbar.addAction(self.__action_back) toolbar.addAction(self.__action_continue) toolbar.addAction(self.__action_reload) toolbar.addAction(self.__action_try_switch_to_error_tab) def center(self): qr = self.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) def closeEvent(self, event): self.__session_manager.update_serializer_data( self.__input_serializer_data) self.__session_manager.update_serializer_data( self.__reference_serializer_data) if GlobalConfig()["default_session"]: self.__session_manager.store_to_file() # ===----------------------------------------------------------------------------------------=== # TabWidgets # ==-----------------------------------------------------------------------------------------=== def tab_widget(self, idx): return self.__widget_tab.widget( idx if not isinstance(idx, TabState) else idx.value) def switch_to_tab(self, tab): idx = tab.value if isinstance(tab, TabState) else tab if self.__tab_current_state == TabState(idx): return Logger.info("Switching to %s tab" % TabState(idx).name) self.__tab_current_state = TabState(idx) self.__widget_tab.setCurrentIndex(idx) self.tab_widget(idx).make_update() self.__action_try_switch_to_error_tab.setEnabled( TabState(idx) == TabState.Result) # Error tab is always disabled if not in "Error" self.__widget_tab.setTabEnabled(TabState.Error.value, TabState(idx) == TabState.Error) # First tab if idx == 0: self.__action_continue.setEnabled(True) self.__action_back.setEnabled(False) # Last tab elif idx == self.__widget_tab.count() - 1: self.__action_continue.setEnabled(False) self.__action_back.setEnabled(True) # Middle tab else: self.__action_continue.setEnabled(True) self.__action_back.setEnabled(True) def set_tab_highest_valid_state(self, state): """Set the state at which the data is valid i.e everything <= self.valid_tab_state is valid """ self.__tab_highest_valid_state = state self.enable_tabs_according_to_tab_highest_valid_state() def enable_tabs_according_to_tab_highest_valid_state(self): """Enable/Disable tabs according to self.__tab_highest_valid_state """ if self.__tab_highest_valid_state == TabState.Setup: self.__widget_tab.setTabEnabled(TabState.Setup.value, True) self.__widget_tab.setTabEnabled(TabState.Stencil.value, False) self.__widget_tab.setTabEnabled(TabState.Result.value, False) self.__widget_tab.setTabEnabled(TabState.Error.value, False) self.__action_try_switch_to_error_tab.setEnabled(False) watched_directories = self.__file_system_watcher.directories() if watched_directories: self.__file_system_watcher.removePaths( self.__file_system_watcher.directories()) elif self.__tab_highest_valid_state == TabState.Stencil: self.__file_system_watcher.addPath( self.__input_serializer_data.serializer.directory) self.__file_system_watcher.addPath( self.__reference_stencil_data.serializer.directory) self.__widget_tab.setTabEnabled(TabState.Setup.value, True) self.__widget_tab.setTabEnabled(TabState.Stencil.value, True) self.__widget_tab.setTabEnabled(TabState.Result.value, False) self.__widget_tab.setTabEnabled(TabState.Error.value, False) self.__widget_tab.widget( TabState.Stencil.value).initial_field_match() self.__action_reload.setEnabled(True) self.__action_try_switch_to_error_tab.setEnabled(False) elif self.__tab_highest_valid_state == TabState.Result: self.__widget_tab.setTabEnabled(TabState.Setup.value, True) self.__widget_tab.setTabEnabled(TabState.Stencil.value, True) self.__widget_tab.setTabEnabled(TabState.Result.value, True) self.__widget_tab.setTabEnabled(TabState.Error.value, True) self.__action_try_switch_to_error_tab.setEnabled(True) elif self.__tab_highest_valid_state == TabState.Error: self.__widget_tab.setTabEnabled(TabState.Setup.value, True) self.__widget_tab.setTabEnabled(TabState.Stencil.value, True) self.__widget_tab.setTabEnabled(TabState.Result.value, True) self.__action_try_switch_to_error_tab.setEnabled(False) def switch_to_next_tab(self): self.__widget_tab.currentWidget().make_continue() def switch_to_previous_tab(self): self.__widget_tab.currentWidget().make_back() def try_switch_to_error_tab(self): if self.__widget_tab.widget( TabState.Result.value).try_switch_to_error_tab(): self.__widget_tab.setTabEnabled(TabState.Error.value, True) def error_window_set_result_data(self, result_data): self.__widget_tab.widget( TabState.Error.value).set_result_data(result_data) # ===----------------------------------------------------------------------------------------=== # PopupWidgets # ==-----------------------------------------------------------------------------------------=== def popup_about_box(self): self.__about_widget = PopupAboutWidget(self) def popup_error_box(self, msg): Logger.error( msg.replace("<b>", "").replace("</b>", "").replace("<br />", ":").replace("<br/>", ":")) msg_box = QMessageBox() msg_box.setWindowTitle("Error") msg_box.setIcon(QMessageBox.Critical) msg_box.setText(msg) msg_box.setStandardButtons(QMessageBox.Ok) reply = msg_box.exec_() # Blocking def popup_reload_box(self, path): self.__file_system_watcher.blockSignals(True) reply = QMessageBox.question( self, "Reload serializer?", "The path \"%s\" has changed.\nDo want to reload the serializers?" % path, QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) if reply == QMessageBox.Yes: self.reload_serializer() self.__file_system_watcher.blockSignals(False) # ===----------------------------------------------------------------------------------------=== # Session manager # ==-----------------------------------------------------------------------------------------=== def save_session(self): Logger.info("Try saving current session") dialog = QFileDialog(self, "Save current session") dialog.setAcceptMode(QFileDialog.AcceptSave) dialog.setDefaultSuffix("json") dialog.setDirectory(getcwd()) if not dialog.exec_(): Logger.info("Abort saving current session") return filename = dialog.selectedFiles() self.__session_manager.update_serializer_data( self.__input_serializer_data) self.__session_manager.update_serializer_data( self.__reference_serializer_data) ret, msglist = self.__session_manager.store_to_file(filename[0]) if not ret: self.popup_error_box("Failed to save configuration file: %s\n%s " % (filename[0], msglist[0])) def open_session(self): Logger.info("Try opening session") filename = QFileDialog.getOpenFileName( self, "Open Session", getcwd(), "JSON configuration (*.json)")[0] if filename is None or filename is "": Logger.info("Abort opening session") return ret, msglist = self.__session_manager.load_from_file(filename) if not ret: self.popup_error_box("Failed to load configuration file: %s\n%s " % (filename, msglist[0])) else: Logger.info("Successfully opened session") self.__session_manager.set_serializer_data( self.__input_serializer_data) self.__session_manager.set_serializer_data( self.__reference_serializer_data) self.switch_to_tab(TabState.Setup) @property def session_manager(self): return self.__session_manager # ===----------------------------------------------------------------------------------------=== # Reload Serializer # ==-----------------------------------------------------------------------------------------=== def reload_serializer(self): Logger.info("Reloading serializers") try: self.__input_serializer_data.reload() self.__reference_serializer_data.reload() if self.__widget_tab.currentIndex() == TabState.Error.value: self.switch_to_tab(TabState.Result) self.__widget_tab.currentWidget().make_update() except RuntimeError as e: self.popup_error_box(str(e)) self.set_tab_highest_valid_state(TabState.Setup) self.switch_to_tab(TabState.Setup) self.__widget_tab.currentWidget().make_update() # ===----------------------------------------------------------------------------------------=== # Online help # ==-----------------------------------------------------------------------------------------=== def go_to_online_help(self): Logger.info("Opening online help") QDesktopServices.openUrl(MainWindow.OnlineHelpUrl)