def addDock(self, name, widget, area=Qt.LeftDockWidgetArea, allowed_areas=Qt.AllDockWidgetAreas): dock_widget = QDockWidget(name) dock_widget.setObjectName("%sDock" % name) dock_widget.setWidget(widget) dock_widget.setAllowedAreas(allowed_areas) dock_widget.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.addDockWidget(area, dock_widget) return dock_widget
def create_dockwidget(self, title): """Add to parent QMainWindow as a dock widget""" dock = QDockWidget(title, self.parent_widget) dock.setObjectName(self.__class__.__name__ + "_dw") dock.setAllowedAreas(self._allowed_areas) dock.setFeatures(self._features) dock.setWidget(self) dock.visibilityChanged.connect(self.visibility_changed) self.dockwidget = dock return (dock, self._location)
def create_dockwidget(self): """Creates a QDockWidget suitable for wrapping this plugin""" dock = QDockWidget(self.get_plugin_title(), self.main) dock.setObjectName(self.__class__.__name__ + "_dockwidget") dock.setAllowedAreas(self.ALLOWED_AREAS) dock.setFeatures(self.FEATURES) dock.setWidget(self) self.dockwidget = dock return dock, self.LOCATION
def create_dockwidget(self): """Creates a QDockWidget suitable for wrapping this plugin""" dock = QDockWidget(self.get_plugin_title(), self.main) dock.setObjectName(self.__class__.__name__+"_dockwidget") dock.setAllowedAreas(self.ALLOWED_AREAS) dock.setFeatures(self.FEATURES) dock.setWidget(self) self.dockwidget = dock return dock, self.LOCATION
def createDockWidget(self, widget, area, title, key=None): dock = QDockWidget() dock.setWidget(widget) dock.setWindowTitle(title) dock.setObjectName(title) self.addDockWidget(area, dock) if not hasattr(self, "dockWidgets"): self.dockWidgets = {} if key is None: key = title self.dockWidgets[key] = dock
def addDock(self, name, widget, area=Qt.RightDockWidgetArea, allowed_areas=Qt.AllDockWidgetAreas): dock_widget = QDockWidget(name) dock_widget.setObjectName("%sDock" % name) dock_widget.setWidget(widget) dock_widget.setAllowedAreas(allowed_areas) self.addDockWidget(area, dock_widget) self.__view_menu.addAction(dock_widget.toggleViewAction()) return dock_widget
class JupyterConsole(BaseExtension): preferences_ui = 'extensions.JupyterConsole.preferences' @BaseExtension.as_thread(wait=500) def event_startup(self): from jupyter_tabwidget import ConsoleTabWidget self.set_busy(True) self._jupyter_console = ConsoleTabWidget(self.main_window) self._dock_widget = QDockWidget(u'Console', self.main_window) self._dock_widget.setObjectName(u'JupyterConsole') self._dock_widget.setWidget(self._jupyter_console) self._dock_widget.closeEvent = self._on_close_event self.main_window.addDockWidget( Qt.BottomDockWidgetArea, self._dock_widget ) self._set_visible(cfg.jupyter_visible) self._shortcut_focus = QShortcut( QKeySequence(cfg.jupyter_focus_shortcut), self.main_window, self._focus, context=Qt.ApplicationShortcut ) self.set_busy(False) def fire(self, event, **kwdict): if event != 'startup': oslogger.debug('ignoring events until after startup') return JupyterConsole.fire = BaseExtension.fire self.fire(event, **kwdict) def activate(self): if not hasattr(self, '_jupyter_console'): oslogger.debug('ignoring activate until after startup') return self._set_visible(not cfg.jupyter_visible) def event_run_experiment(self, fullscreen): oslogger.debug(u'capturing stdout') self._jupyter_console.current.capture_stdout() def event_end_experiment(self, ret_val): self._jupyter_console.current.release_stdout() self._jupyter_console.current.show_prompt() oslogger.debug(u'releasing stdout') def event_jupyter_start_kernel(self, kernel): self._jupyter_console.add(kernel=kernel) def event_jupyter_run_file(self, path, debug=False): self._set_visible(True) if not os.path.isfile(path): return self._jupyter_console.current.change_dir(os.path.dirname(path)) if debug: self._jupyter_console.current.run_debug( path, breakpoints=self.extension_manager.provide( 'pyqode_breakpoints' ) ) else: self._jupyter_console.current.run_file(path) def event_jupyter_change_dir(self, path): self._jupyter_console.current.change_dir(path) def event_jupyter_run_code(self, code, editor=None): self._set_visible(True) self._jupyter_console.current.execute(code) def event_jupyter_run_silent(self, code): self._jupyter_console.current.execute(code) def event_jupyter_run_system_command(self, cmd): self._jupyter_console.current.run_system_command(cmd) def event_jupyter_write(self, msg): try: self._jupyter_console.current.write(msg) except AttributeError: oslogger.error(safe_decode(msg)) def event_jupyter_focus(self): self._jupyter_console.current.focus() def event_jupyter_show_prompt(self): self._jupyter_console.current.show_prompt() def event_jupyter_restart(self): self._jupyter_console.current.restart() def event_jupyter_interrupt(self): self._jupyter_console.current.interrupt() def event_set_workspace_globals(self, global_dict): self._jupyter_console.current.set_workspace_globals(global_dict) def provide_jupyter_workspace_name(self): try: return self._jupyter_console.current.name except AttributeError: return None def provide_workspace_kernel(self): try: return self._jupyter_console.current._kernel except AttributeError: return None def provide_workspace_language(self): try: return self._jupyter_console.current.language except AttributeError: return None def provide_workspace_logging_commands(self): from jupyter_tabwidget.constants import LOGGING_LEVEL_CMD try: kernel = self._jupyter_console.current.language except AttributeError: return None return LOGGING_LEVEL_CMD.get(kernel, None) def provide_jupyter_workspace_globals(self): return self.get_workspace_globals() def provide_jupyter_list_workspace_globals(self): return self.list_workspace_globals() def provide_jupyter_workspace_variable(self, name): return self._jupyter_console.current.get_workspace_variable(name) def provide_jupyter_kernel_running(self): try: return self._jupyter_console.current.running() except AttributeError: return False def provide_jupyter_check_syntax(self, code): return self._jupyter_console.current.check_syntax(code) def get_workspace_globals(self): try: return self._jupyter_console.current.get_workspace_globals() except AttributeError: return {u'no reply': None} def list_workspace_globals(self): try: return self._jupyter_console.current.list_workspace_globals() except Exception as e: print(e) return [] def event_close(self): if not hasattr(self, '_jupyter_console'): oslogger.debug('ignoring close all') return self._jupyter_console.close_all() def _set_visible(self, visible): cfg.jupyter_visible = visible self.set_checked(visible) if visible: self._dock_widget.show() self._jupyter_console.current.focus() else: self._dock_widget.hide() def _focus(self): self._set_visible(True) self._jupyter_console.current.focus() def _on_close_event(self, e): self._set_visible(False)
class WorkspaceExplorer(BaseExtension): @BaseExtension.as_thread(wait=2500) def event_startup(self): dm = DataMatrix(length=0) dm.initializing = -1 self._workspace_cache = {} self._label_kernel_not_supported = QLabel('<b>' + _('Kernel not supported') + '</b>') self._label_kernel_not_supported.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) self._qdm = WorkspaceMatrix(dm, read_only=True) self._qdm.setFont(QFont(cfg.pyqode_font_name, cfg.pyqode_font_size)) self._qdm.cell_double_clicked.connect(self._inspect_variable) self._dock_widget = QDockWidget(self.main_window) self._dock_widget.setWidget(self._qdm) self._dock_widget.closeEvent = self._on_close_event self._dock_widget.setWindowTitle(_(u'Workspace')) self._dock_widget.setObjectName('WorkspaceExplorer') self._dock_widget.visibilityChanged.connect( self._on_visibility_changed) self.main_window.addDockWidget(Qt.RightDockWidgetArea, self._dock_widget) self._set_visible(cfg.workspace_visible) def _inspect_variable(self, row, column): if self.extension_manager.provide('jupyter_kernel_running'): self.extension_manager.fire( 'notify', message=_(u'Cannot inspect variables in running kernel')) return if not row: return self.extension_manager.fire( 'data_viewer_inspect', name=self._qdm.dm.name[row - 1], workspace=self.extension_manager.provide('jupyter_workspace_name')) def activate(self): if not hasattr(self, '_qdm'): oslogger.info('ignoring activate until after startup') return self._set_visible(not cfg.workspace_visible) def _on_visibility_changed(self, visible): if not visible: return self._update( self.extension_manager.provide('jupyter_workspace_name'), lambda: self.extension_manager.provide('jupyter_workspace_globals')) def _on_close_event(self, e): self._set_visible(False) def _update(self, name, workspace_func): if (not hasattr(self, '_dock_widget') or not self._dock_widget.isVisible()): return self._dock_widget.setWidget(self._qdm) self._dock_widget.setWindowTitle(_(u'Workspace ({})').format(name)) workspace = workspace_func() self._workspace_cache[name] = workspace # If the workspace didn't reply, we try again in a second if workspace is None or workspace.get(u'no reply', False) is None: QTimer.singleShot(1000, lambda: self._update(name, workspace_func)) return # If the current kernel doesn't expose its workspace, indicate this if workspace.get(u'not supported', False) is None: dm = DataMatrix(length=0) dm.kernel_not_supported = -1 self._dock_widget.setWidget(self._label_kernel_not_supported) # Create a DataMatrix that exposes the workspace else: dm = DataMatrix(length=len(workspace)) dm.sorted = False dm.name = '' dm.value = '' dm.shape = '' dm.type = '' for row, (var, data) in zip(dm, workspace.items()): if data is None: oslogger.warning(u'invalid workspace data: {}'.format(var)) continue value, type_, shape = data row.value = value row.name = var if shape is not None: row.shape = repr(shape) row.type = type_ self._qdm.dm = dm self._qdm.refresh() def _set_visible(self, visible): cfg.workspace_visible = visible self.set_checked(visible) if visible: self._dock_widget.show() else: self._dock_widget.hide() def event_workspace_update(self, name, workspace_func): self._update(name, workspace_func) def event_workspace_restart(self, name, workspace_func): self._update(name, workspace_func) def event_workspace_switch(self, name, workspace_func): # When a kernel is running (which includes being a debugging session) # it doesn't respond to silent requests for the workspace. Therefore # we use cached copy of the last update. if self.extension_manager.provide('jupyter_kernel_running'): self._update(name, lambda: self._workspace_cache.get(name, {})) return self._update(name, workspace_func) def event_workspace_new(self, name, workspace_func): self._update(name, workspace_func)
class MainWindow(QMainWindow): """Main window of the locator app""" __clsName = "LocatorMainWindow" def _tr(self, string): """Translate the string using :py:func:`QApplication.translate`""" return QApplication.translate(self.__clsName, string) def __init__(self, parent=None): super().__init__(parent) # Create viewer widget self._viewer = micro_view.MicroViewWidget() self._viewer.setObjectName("viewer") self._viewer.showLocalizationsChanged.connect(self.setShowPreview) # Create dock widgets fileChooser = file_chooser.FileChooser() fileChooser.selected.connect(self.open) self._fileModel = fileChooser.model() self._fileModel.rowsRemoved.connect(self._checkFileList) self._fileDock = QDockWidget(self.tr("File selection"), self) self._fileDock.setObjectName("fileDock") self._fileDock.setWidget(fileChooser) self._locOptionsWidget = locate_options.Container() self._locOptionsWidget.setObjectName("locOptionsWidget") self._locOptionsDock = QDockWidget(self.tr("Localization options"), self) self._locOptionsDock.setObjectName("locOptionsDock") self._locOptionsDock.setWidget(self._locOptionsWidget) self._locFilterWidget = locate_filter.FilterWidget() self._locFilterWidget.filterChanged.connect(self._filterLocalizations) self._locFilterDock = QDockWidget(self.tr("Localization filter"), self) self._locFilterDock.setObjectName("locFilterDock") self._locFilterDock.setWidget(self._locFilterWidget) locSaveWidget = locate_saver.SaveWidget() self._locSaveDock = QDockWidget(self.tr("Save localizations"), self) self._locSaveDock.setObjectName("locSaveDock") self._locSaveDock.setWidget(locSaveWidget) for d in (self._fileDock, self._locOptionsDock, self._locFilterDock, self._locSaveDock): d.setFeatures(d.features() & ~QDockWidget.DockWidgetClosable) self.addDockWidget(Qt.LeftDockWidgetArea, d) self.setDockOptions(self.dockOptions() | QMainWindow.VerticalTabs) self.setCentralWidget(self._viewer) # set up the preview worker self._previewWorker = workers.PreviewWorker(self) self._locOptionsWidget.optionsChanged.connect( self._makePreviewWorkerWork) self._viewer.currentFrameChanged.connect(self._makePreviewWorkerWork) self._previewWorker.finished.connect(self._previewFinished) self._previewWorker.error.connect(self._previewError) self._previewWorker.enabled = True self._previewWorker.busyChanged.connect(self._setBusyCursor) # set up the batch worker self._batchWorker = workers.BatchWorker(self) self._batchWorker.fileFinished.connect(self._locateRunnerFinished) self._batchWorker.fileError.connect(self._locateRunnerError) # batch progress dialog self._progressDialog = batch_progress.BatchProgressDialog(self) self._batchWorker.fileFinished.connect( self._progressDialog.increaseValue) self._batchWorker.fileError.connect(self._progressDialog.increaseValue) self._progressDialog.canceled.connect(self._batchWorker.stop) # Some things to keep track of self._currentFile = QPersistentModelIndex() self._currentLocData = pd.DataFrame(columns=["x", "y"]) self._roiPolygon = QPolygonF() # load settings and restore window geometry settings = QSettings("sdt", "locator") v = settings.value("MainWindow/geometry") if v is not None: self.restoreGeometry(v) v = settings.value("MainWindow/state") if v is not None: self.restoreState(v) # restore enable/disable preview show = settings.value("Viewer/showPreview", True, type=bool) self._viewer.showLocalizations = show QMetaObject.connectSlotsByName(self) @Slot(QModelIndex) @Slot(str) def open(self, file): """Open an image sequence Open an image sequence from a file and load it into the viewer widget. This is a PyQt slot. Parameters ---------- file : QModelIndex or str Index of the entry in a `FileListModel` or the file name. If `file` is a string, add the file to the `FileListModel` and show it. """ if isinstance(file, str): file = self._fileModel.addItem(file) filename = file.data(FileListModel.FileNameRole) try: ims = pims.open(filename) except Exception as e: QMessageBox.critical(self, self.tr("Error opening image"), self.tr(str(e))) ims = None file = None if isinstance(ims, collections.Iterable) and not len(ims): QMessageBox.critical(self, self.tr(""), self.tr("Empty image")) ims = None file = None self._currentFile = QPersistentModelIndex(file) self._viewer.setImageSequence(ims) self._viewer.zoomFit() # also the options widget needs to know how many frames there are self._locOptionsWidget.numFrames = (0 if (ims is None) else len(ims)) if file is not None: self.setWindowTitle("locator - {}".format(filename)) else: self.setWindowTitle("locator") @Slot(int) def on_viewer_frameReadError(self, frameno): """Slot getting called when a frame could not be read""" QMessageBox.critical( self, self.tr("Read Error"), self.tr("Could not read frame number {}".format(frameno + 1))) @Slot() def _makePreviewWorkerWork(self): """Called when something happens that requires a new preview e. g. a new frame is displayed.. """ if (not self._currentFile.isValid() or not self._viewer.showLocalizations): return cur_method = self._locOptionsWidget.method cur_opts = self._locOptionsWidget.options file_method = self._currentFile.data(FileListModel.LocMethodRole) file_opts = self._currentFile.data(FileListModel.LocOptionsRole) file_roi = self._currentFile.data(FileListModel.ROIRole) file_frameRange = self._currentFile.data(FileListModel.FrameRangeRole) curFrame = self._viewer.getCurrentFrame() curFrameNo = self._viewer.currentFrameNumber if (file_method == cur_method and file_opts == cur_opts and (self._roiPolygon == file_roi or cur_method == "load file") and file_frameRange[0] <= curFrameNo < file_frameRange[1]): data = self._currentFile.data(FileListModel.LocDataRole) data = data[data["frame"] == curFrameNo] self._currentLocData = data self._locFilterWidget.setVariables(data.columns.values.tolist()) self._filterLocalizations() return if cur_method == "load file": fname = os.path.join(*determine_filename( self._currentFile.data(FileListModel.FileNameRole), cur_opts["fmt"])) # TODO: Move to worker thread try: data = load(fname) # sdt.data.load except Exception: data = pd.DataFrame() modelIdx = QModelIndex(self._currentFile) self._fileModel.setData(modelIdx, data, FileListModel.LocDataRole) self._fileModel.setData(modelIdx, cur_opts, FileListModel.LocOptionsRole) self._fileModel.setData(modelIdx, cur_method, FileListModel.LocMethodRole) self._fileModel.setData(modelIdx, (-np.inf, np.inf), FileListModel.FrameRangeRole) # call recursively to update viewer self._makePreviewWorkerWork() return self._previewWorker.processImage(curFrame, cur_opts, cur_method, self._roiPolygon) def closeEvent(self, event): """Window is closed, save state""" settings = QSettings("sdt", "locator") settings.setValue("MainWindow/geometry", self.saveGeometry()) settings.setValue("MainWindow/state", self.saveState()) settings.setValue("Viewer/showPreview", self._viewer.showLocalizations) super().closeEvent(event) @Slot() def _checkFileList(self): """If currently previewed file was removed from list, remove preview This gets triggered by the file list model's ``rowsRemoved`` signal """ if not self._currentFile.isValid(): self._locOptionsWidget.numFrames = 0 self._viewer.setImageSequence(None) @Slot(bool) def _setBusyCursor(self, busy): if busy: QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) else: QApplication.restoreOverrideCursor() @Slot(pd.DataFrame) def _previewFinished(self, data): """The preview worker finished Update the filter widget with the data column names and filter the data using ``_filterLocalizations``. """ self._currentLocData = data self._locFilterWidget.setVariables(data.columns.values.tolist()) self._filterLocalizations() @Slot(Exception) def _previewError(self, err): QMessageBox.critical( self, self.tr("Localization error"), self.tr("Failed to create preview.\n\n{}").format(err)) @Slot() def _filterLocalizations(self): """Set good/bad localizations in the viewer Anything that passes the filter (from the filter widget) and is in the ROI polygon is considered a good localization. Anything that does not pass the filter and is in the ROI is considered bad. Anything outside the ROI is not considered at all. Call the viewer's ``setLocalizationData`` accordingly. """ filterFunc = self._locFilterWidget.getFilter() good = filterFunc(self._currentLocData) self._viewer.setLocalizationData(self._currentLocData[good], self._currentLocData[~good]) @Slot(QPolygonF) def on_viewer_roiChanged(self, roi): """Update ROI polygon and filter localizations""" self._roiPolygon = roi self._makePreviewWorkerWork() def setShowPreview(self, show): if (self._viewer.showLocalizations == show and self._previewWorker.enabled == show): return self._previewWorker.enabled = show self._viewer.showLocalizations = show self._makePreviewWorkerWork() @Property(bool, fset=setShowPreview, doc="Show preview of localizations") def showPreview(self): return self._viewer.showLocalizations def _saveMetadata(self, fname): """Save metadata to YAML This saves currently selected algorithm, options, ROI, and filter to the file specified by ``fname``. Parameters ---------- fname : str Name of the output file """ metadata = collections.OrderedDict() metadata["algorithm"] = self._locOptionsWidget.method metadata["options"] = self._locOptionsWidget.options metadata["roi"] = self._roiPolygon metadata["filter"] = self._locFilterWidget.filterString with open(fname, "w") as f: yaml.dump(metadata, f, default_flow_style=False) @Slot() def on_locOptionsWidget_save(self): # save options fname, _ = qtpy.compat.getsavefilename( self, self.tr("Save file"), "", self.tr("YAML data (*.yaml)") + ";;" + self.tr("All files (*)")) if not fname: # cancelled return try: self._saveMetadata(fname) except Exception as e: QMessageBox.critical(self, self.tr("Error writing to file"), self.tr(str(e))) @Slot() def on_locOptionsWidget_load(self): # load options fname, _ = qtpy.compat.getopenfilename( self, self.tr("Save file"), "", self.tr("YAML data (*.yaml)") + ";;" + self.tr("All files (*)")) if not fname: # cancelled return try: with open(fname) as f: md = yaml.safe_load(f) if not isinstance(md, dict): raise RuntimeError() except Exception: QMessageBox.critical(self, self.tr("Error loading settings"), self.tr("Error reading file.")) return algo = md.get("algorithm") if isinstance(algo, str): try: self._locOptionsWidget.method = algo except Exception: QMessageBox.critical(self, self.tr("Error loading settings"), self.tr("Unsupported algorithm")) return opts = md.get("options") self._locOptionsWidget.options = opts filt = md.get("filter") if isinstance(filt, str): self._locFilterWidget.filterString = filt roi = md.get("roi") with contextlib.suppress(Exception): vert = [] for x, y in roi: vert.append(QPointF(x, y)) r = QPolygonF(vert) self._viewer.roi = r self._roiPolygon = r @Slot(str) def on_locateSaveWidget_locateAndSave(self, format): """Locate all features in all files and save the data and metadata""" # TODO: check if current localizations are up-to-date # only run locate if not self._progressDialog.value = 0 self._progressDialog.maximum = self._fileModel.rowCount() self._progressDialog.show() optWid = self._locOptionsWidget self._batchWorker.processFiles(self._fileModel, optWid.frameRange, optWid.options, optWid.method, self._roiPolygon) @Slot(int, pd.DataFrame, dict) def _locateRunnerFinished(self, idx, data, options): """A LocateRunner finished locating all peaks in a sequence Save data and metadata to a file with the same name as the image file, except for the extension. Parameters ---------- index : QModelIndex Index of the file in the file list model data : pandas.DataFrame Localization data options : dict Options used for locating peaks """ optsWidget = self._locOptionsWidget index = self._fileModel.index(idx) self._fileModel.setData(index, data, FileListModel.LocDataRole) self._fileModel.setData(index, options, FileListModel.LocOptionsRole) self._fileModel.setData(index, optsWidget.method, FileListModel.LocMethodRole) self._fileModel.setData(index, self._roiPolygon, FileListModel.ROIRole) self._fileModel.setData(index, optsWidget.frameRange, FileListModel.FrameRangeRole) saveFormat = self._locSaveDock.widget().getFormat() saveFileName = self._fileModel.data(index, FileListModel.FileNameRole) metaFileName = os.path.join(*determine_filename(saveFileName, "yaml")) fdir, fname = determine_filename(saveFileName, saveFormat) saveFileName = os.path.join(fdir, fname) os.makedirs(fdir, exist_ok=True) filterFunc = self._locFilterWidget.getFilter() data = data[filterFunc(data)] save(saveFileName, data) # sdt.data.save self._saveMetadata(metaFileName) @Slot(int, Exception) def _locateRunnerError(self, idx, e): """A LocateRunner encountered an error Show an error message box. Parameters ---------- index : QModelIndex Index (in the file list model) of the file that caused the error """ index = self._fileModel.index(idx) QMessageBox.critical( self, self.tr("Localization error"), self.tr("Failed to locate features in {}\n\n{}".format( index.data(file_chooser.FileListModel.FileNameRole), str(e))))
def main(): """Execute QDarkStyle example.""" parser = argparse.ArgumentParser( description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument( '--qt_from', default='qtpy', type=str, choices=[ 'pyqt5', 'pyqt', 'pyside2', 'pyside', 'qtpy', 'pyqtgraph', 'qt.py' ], help= "Choose which binding and/or abstraction is to be used to run the example." ) parser.add_argument( '--no_dark', action='store_true', help="Exihibts the original window (without jam_darkstyle).") parser.add_argument('--test', action='store_true', help="Auto close window after 2s.") parser.add_argument('--reset', action='store_true', help="Reset GUI settings (position, size) then opens.") parser.add_argument('--screenshots', action='store_true', help="Generate screenshots on images folder.") # Parsing arguments from command line args = parser.parse_args() # To avoid problems when testing without screen if args.test or args.screenshots: os.environ['QT_QPA_PLATFORM'] = 'offscreen' # Set QT_API variable before importing QtPy if args.qt_from in ['pyqt', 'pyqt5', 'pyside', 'pyside2']: os.environ['QT_API'] = args.qt_from elif args.qt_from == 'pyqtgraph': os.environ['QT_API'] = os.environ['PYQTGRAPH_QT_LIB'] elif args.qt_from in ['qt.py', 'qt']: try: import Qt except ImportError: print('Could not import Qt (Qt.Py)') else: os.environ['QT_API'] = Qt.__binding__ # QtPy imports from qtpy import API_NAME, QT_VERSION, PYQT_VERSION, PYSIDE_VERSION from qtpy import __version__ as QTPY_VERSION from qtpy.QtWidgets import (QApplication, QMainWindow, QDockWidget, QStatusBar, QLabel, QPushButton, QMenu) from qtpy.QtCore import QTimer, Qt, QSettings # Set API_VERSION variable API_VERSION = '' if PYQT_VERSION: API_VERSION = PYQT_VERSION elif PYSIDE_VERSION: API_VERSION = PYSIDE_VERSION else: API_VERSION = 'Not found' # Import examples UI from mw_menus_ui import Ui_MainWindow as ui_main from dw_buttons_ui import Ui_DockWidget as ui_buttons from dw_displays_ui import Ui_DockWidget as ui_displays from dw_inputs_fields_ui import Ui_DockWidget as ui_inputs_fields from dw_inputs_no_fields_ui import Ui_DockWidget as ui_inputs_no_fields from dw_widgets_ui import Ui_DockWidget as ui_widgets from dw_views_ui import Ui_DockWidget as ui_views from dw_containers_tabs_ui import Ui_DockWidget as ui_containers_tabs from dw_containers_no_tabs_ui import Ui_DockWidget as ui_containers_no_tabs # create the application app = QApplication(sys.argv) app.setOrganizationName('QDarkStyle') app.setApplicationName('QDarkStyle Example') style = '' if not args.no_dark: style = jam_darkstyle.load_stylesheet() app.setStyleSheet(style) # create main window window = QMainWindow() window.setObjectName('mainwindow') ui = ui_main() ui.setupUi(window) title = ("QDarkStyle Example - " + "(QDarkStyle=v" + jam_darkstyle.__version__ + ", QtPy=v" + QTPY_VERSION + ", " + API_NAME + "=v" + API_VERSION + ", Qt=v" + QT_VERSION + ", Python=v" + platform.python_version() + ")") _logger.info(title) window.setWindowTitle(title) # Create docks for buttons dw_buttons = QDockWidget() dw_buttons.setObjectName('buttons') ui_buttons = ui_buttons() ui_buttons.setupUi(dw_buttons) window.addDockWidget(Qt.RightDockWidgetArea, dw_buttons) # Add actions on popup toolbuttons menu = QMenu() for action in ['Action A', 'Action B', 'Action C']: menu.addAction(action) ui_buttons.toolButtonDelayedPopup.setMenu(menu) ui_buttons.toolButtonInstantPopup.setMenu(menu) ui_buttons.toolButtonMenuButtonPopup.setMenu(menu) # Create docks for buttons dw_displays = QDockWidget() dw_displays.setObjectName('displays') ui_displays = ui_displays() ui_displays.setupUi(dw_displays) window.addDockWidget(Qt.RightDockWidgetArea, dw_displays) # Create docks for inputs - no fields dw_inputs_no_fields = QDockWidget() dw_inputs_no_fields.setObjectName('inputs_no_fields') ui_inputs_no_fields = ui_inputs_no_fields() ui_inputs_no_fields.setupUi(dw_inputs_no_fields) window.addDockWidget(Qt.RightDockWidgetArea, dw_inputs_no_fields) # Create docks for inputs - fields dw_inputs_fields = QDockWidget() dw_inputs_fields.setObjectName('inputs_fields') ui_inputs_fields = ui_inputs_fields() ui_inputs_fields.setupUi(dw_inputs_fields) window.addDockWidget(Qt.RightDockWidgetArea, dw_inputs_fields) # Create docks for widgets dw_widgets = QDockWidget() dw_widgets.setObjectName('widgets') ui_widgets = ui_widgets() ui_widgets.setupUi(dw_widgets) window.addDockWidget(Qt.LeftDockWidgetArea, dw_widgets) # Create docks for views dw_views = QDockWidget() dw_views.setObjectName('views') ui_views = ui_views() ui_views.setupUi(dw_views) window.addDockWidget(Qt.LeftDockWidgetArea, dw_views) # Create docks for containers - no tabs dw_containers_no_tabs = QDockWidget() dw_containers_no_tabs.setObjectName('containers_no_tabs') ui_containers_no_tabs = ui_containers_no_tabs() ui_containers_no_tabs.setupUi(dw_containers_no_tabs) window.addDockWidget(Qt.LeftDockWidgetArea, dw_containers_no_tabs) # Create docks for containters - tabs dw_containers_tabs = QDockWidget() dw_containers_tabs.setObjectName('containers_tabs') ui_containers_tabs = ui_containers_tabs() ui_containers_tabs.setupUi(dw_containers_tabs) window.addDockWidget(Qt.LeftDockWidgetArea, dw_containers_tabs) # Tabify right docks window.tabifyDockWidget(dw_buttons, dw_displays) window.tabifyDockWidget(dw_displays, dw_inputs_fields) window.tabifyDockWidget(dw_inputs_fields, dw_inputs_no_fields) # Tabify left docks window.tabifyDockWidget(dw_containers_no_tabs, dw_containers_tabs) window.tabifyDockWidget(dw_containers_tabs, dw_widgets) window.tabifyDockWidget(dw_widgets, dw_views) # Issues #9120, #9121 on Spyder qstatusbar = QStatusBar() qstatusbar.addWidget( QLabel('Issue Spyder #9120, #9121 - background not matching.')) qstatusbar.addWidget(QPushButton('OK')) # Add info also in status bar for screenshots get it qstatusbar.addWidget(QLabel('INFO: ' + title)) window.setStatusBar(qstatusbar) # Todo: add report info and other info in HELP graphical # Auto quit after 2s when in test mode if args.test: QTimer.singleShot(2000, app.exit) # Save screenshots for different displays and quit if args.screenshots: window.showFullScreen() create_screenshots(app, window, args.no_dark) # Do not read settings when taking screenshots - like reset else: _read_settings(window, args.reset, QSettings) window.showMaximized() app.exec_() _write_settings(window, QSettings) return window
class MainWindow(QMainWindow): def __init__(self, argv): super(MainWindow, self).__init__() self.main_widget = None self.graphic_settings_dock = None self.zero_loss_peak_dock = None self.projects_dock = None self.spectra = Spectra() self.init_ui() self.read_settings() self.parse_arguments(argv) def init_ui(self): # Define standard icon. standard_icon = self.style().standardIcon # Central widget. self.main_widget = SpectrumWidget(self.spectra) self.main_widget.setFocus() self.setCentralWidget(self.main_widget) # Open spectrum action open_spectrum_action = QAction(standard_icon(QStyle.SP_DialogOpenButton), 'Open spectrum', self) open_spectrum_action.setShortcut('Ctrl+O') open_spectrum_action.setStatusTip('Open spectrum') open_spectrum_action.triggered.connect(self.open_spectrum) # Exit action exit_action = QAction(standard_icon(QStyle.SP_TitleBarCloseButton), 'Exit', self) exit_action.setShortcut('Ctrl+Q') exit_action.setStatusTip('Exit application') exit_action.triggered.connect(self.close) # Status bar. self.statusBar() # Menu bar. menubar = self.menuBar() file_menu = menubar.addMenu('&File') file_menu.addAction(open_spectrum_action) file_menu.addAction(exit_action) view_menu = menubar.addMenu('&View') analysis_menu = menubar.addMenu('&Analysis') # Toolbar file_toolbar = self.addToolBar('File') file_toolbar.addAction(open_spectrum_action) file_toolbar.addAction(exit_action) view_menu.addAction(file_toolbar.toggleViewAction()) analysis_toolbar = self.addToolBar('Analysis') view_menu.addAction(analysis_toolbar.toggleViewAction()) view_menu.addSeparator() # Dock widget. self.graphic_settings_dock = QDockWidget("Graphic settings", self) self.graphic_settings_dock.setObjectName("graphic_settings_dock") self.graphic_settings_dock.setAllowedAreas(Qt.AllDockWidgetAreas) label_test = QLabel("Test label") self.graphic_settings_dock.setWidget(label_test) view_menu.addAction(self.graphic_settings_dock.toggleViewAction()) self.addDockWidget(Qt.AllDockWidgetAreas, self.graphic_settings_dock) print(self.graphic_settings_dock.objectName()) self.zero_loss_peak_dock = ZeroLossPeakWidget(self, self.spectra) analysis_menu.addAction(self.zero_loss_peak_dock.toggleViewAction()) self.addDockWidget(Qt.AllDockWidgetAreas, self.zero_loss_peak_dock) self.projects_dock = ProjectWidget(self) view_menu.addAction(self.projects_dock.toggleViewAction()) self.addDockWidget(Qt.AllDockWidgetAreas, self.projects_dock) # Final options. self.setWindowTitle('pySEM-EELS') self.show() def closeEvent(self, event): self.save_settings() super(MainWindow, self).closeEvent(event) def save_settings(self): settings = QSettings("openMicroanalysis", "pysemeelsgui") # print(settings.fileName()) settings.beginGroup("MainWindow") settings.setValue("geometry", self.saveGeometry()) settings.setValue("window_state", self.saveState()) settings.endGroup() settings.beginGroup("graphic_settings_dock") settings.setValue("visible", self.graphic_settings_dock.isVisible()) settings.endGroup() settings.beginGroup("zero_loss_peak_dock") settings.setValue("visible", self.zero_loss_peak_dock.isVisible()) settings.endGroup() settings.beginGroup("projects_dock") settings.setValue("visible", self.projects_dock.isVisible()) settings.endGroup() def read_settings(self): settings = QSettings("openMicroanalysis", "pysemeelsgui") # print(settings.fileName()) # settings.clear() settings.beginGroup("MainWindow") geometry_value = settings.value("geometry") if geometry_value is None: self.setGeometry(300, 300, 600, 400) else: self.restoreGeometry(geometry_value) window_state_value = settings.value("window_state") if window_state_value is not None: self.restoreState(window_state_value) settings.endGroup() settings.beginGroup("graphic_settings_dock") visible_value = settings.value("visible") if visible_value is not None: if visible_value == "true": self.graphic_settings_dock.setVisible(True) elif visible_value == "false": self.graphic_settings_dock.setVisible(False) settings.endGroup() settings.beginGroup("zero_loss_peak_dock") visible_value = settings.value("visible") if visible_value is not None: if visible_value == "true": self.zero_loss_peak_dock.setVisible(True) elif visible_value == "false": self.zero_loss_peak_dock.setVisible(False) settings.endGroup() def parse_arguments(self, argv): option_parser = optparse.OptionParser() option_parser.add_option("-s", "--spectrum", action="store", type="string", dest="spectrum_file", help="Open a eels spectrum") options, arguments = option_parser.parse_args() logging.info("Remaining arguments: {}".format(arguments)) logging.info("Spectrum file: {}".format(options.spectrum_file)) if options.spectrum_file: self.spectra.open_spectrum(options.spectrum_file) elv_file = self.spectra.get_current_elv_file() spectrum_data = elv_file.get_spectrum_data() self.main_widget.update_figure(spectrum_data) def open_spectrum(self): self.statusBar().showMessage("Opening spectrum", 2000) path = os.path.dirname(__file__) formats = ["*.elv"] spectrum_filter = "Spectrum file ({:s})".format(" ".join(formats)) file_names = QFileDialog.getOpenFileName(self, "Open an EELS spectrum", path, spectrum_filter) self.spectra.open_spectrum(file_names) elv_file = self.spectra.get_current_elv_file() spectrum_data = elv_file.get_spectrum_data() self.main_widget.update_figure(spectrum_data)
class MainWindow(QMainWindow): def __init__(self): self.logger = logging.getLogger(APPLICATION_NAME + '.MainWindow') self.logger.info("MainWindow.__init__") super(MainWindow, self).__init__() self.init_ui() self.read_settings() def init_ui(self): # Define standard icon. standard_icon = self.style().standardIcon # Central widget. self.main_widget = SpectrumWidget() self.main_widget.setFocus() self.setCentralWidget(self.main_widget) # Project action new_project_action = QAction(QIcon(':/oi/svg/document.svg'), 'New project', self) new_project_action.setShortcut('Ctrl+N') new_project_action.setStatusTip('New project') new_project_action.triggered.connect(self.new_project) open_project_action = QAction(QIcon(':/oi/svg/envelope-open.svg'), 'Open project', self) open_project_action.setShortcut('Ctrl+O') open_project_action.setStatusTip('Open project') open_project_action.triggered.connect(self.open_project) close_project_action = QAction(QIcon(':/oi/svg/envelope-closed.svg'), 'Close project', self) close_project_action.setShortcut('Ctrl+C') close_project_action.setStatusTip('Close project') close_project_action.triggered.connect(self.close_project) save_project_action = QAction(QIcon(':/oi/svg/hard-drive.svg'), 'Save project', self) save_project_action.setShortcut('Ctrl+S') save_project_action.setStatusTip('Save project') save_project_action.triggered.connect(self.save_project) saveas_project_action = QAction(QIcon(':/oi/svg/hard-drive.svg'), 'Save project as ...', self) # saveas_project_action.setShortcut('Ctrl+S') saveas_project_action.setStatusTip('Save project as ...') saveas_project_action.triggered.connect(self.saveas_project) # Spectrum action import_spectrum_action = QAction(QIcon(':/oi/svg/account-login.svg'), 'Import spectrum', self) import_spectrum_action.setShortcut('Ctrl+I') import_spectrum_action.setStatusTip('Import spectrum') import_spectrum_action.triggered.connect(self.import_spectrum) export_spectrum_action = QAction(QIcon(':/oi/svg/account-logout.svg'), 'Export spectrum', self) # export_spectrum_action.setShortcut('Ctrl+I') export_spectrum_action.setStatusTip('Export spectrum') export_spectrum_action.triggered.connect(self.export_spectrum) # Exit action exit_action = QAction(QIcon(':/oi/svg/x.svg'), 'Exit', self) exit_action.setShortcut('Ctrl+Q') exit_action.setStatusTip('Exit application') exit_action.triggered.connect(self.close) # Status bar. self.statusBar() # Menu bar. menubar = self.menuBar() file_menu = menubar.addMenu('&File') file_menu.addAction(new_project_action) file_menu.addAction(open_project_action) file_menu.addAction(save_project_action) file_menu.addAction(saveas_project_action) file_menu.addAction(close_project_action) file_menu.addSeparator() file_menu.addAction(exit_action) view_menu = menubar.addMenu('&View') spectrum_menu = menubar.addMenu('&Spectrum') spectrum_menu.addAction(import_spectrum_action) analysis_menu = menubar.addMenu('&Analysis') # Toolbar file_toolbar = self.addToolBar('File') file_toolbar.addAction(new_project_action) file_toolbar.addAction(open_project_action) file_toolbar.addAction(save_project_action) file_toolbar.addAction(saveas_project_action) file_toolbar.addAction(close_project_action) file_toolbar.addAction(exit_action) view_menu.addAction(file_toolbar.toggleViewAction()) spectrum_toolbar = self.addToolBar('Spectrum') spectrum_toolbar.addAction(import_spectrum_action) view_menu.addAction(spectrum_toolbar.toggleViewAction()) analysis_toolbar = self.addToolBar('Analysis') view_menu.addAction(analysis_toolbar.toggleViewAction()) view_menu.addSeparator() # Dock widget. self.graphic_settings_dock = QDockWidget("Graphic settings", self) self.graphic_settings_dock.setObjectName("graphic_settings_dock") self.graphic_settings_dock.setAllowedAreas(Qt.AllDockWidgetAreas) label_test = QLabel("Test label") self.graphic_settings_dock.setWidget(label_test) view_menu.addAction(self.graphic_settings_dock.toggleViewAction()) self.addDockWidget(Qt.AllDockWidgetAreas, self.graphic_settings_dock) print(self.graphic_settings_dock.objectName()) # Final options. self.setWindowTitle('X-ray spectrum analyzer') self.show() def closeEvent(self, event): self.save_settings() super(MainWindow, self).closeEvent(event) def save_settings(self): settings = QSettings("openMicroanalysis", "xrayspectrumanalyzergui") # print(settings.fileName()) settings.beginGroup("MainWindow") settings.setValue("geometry", self.saveGeometry()) settings.setValue("window_state", self.saveState()) settings.endGroup() settings.beginGroup("graphic_settings_dock") settings.setValue("visible", self.graphic_settings_dock.isVisible()) settings.endGroup() # settings.beginGroup("zero_loss_peak_dock") # settings.setValue("visible", self.zero_loss_peak_dock.isVisible()) # settings.endGroup() def read_settings(self): settings = QSettings("openMicroanalysis", "xrayspectrumanalyzergui") # print(settings.fileName()) # settings.clear() settings.beginGroup("MainWindow") geometry_value = settings.value("geometry") if geometry_value is None: self.setGeometry(300, 300, 600, 400) else: self.restoreGeometry(geometry_value) window_state_value = settings.value("window_state") if window_state_value is not None: self.restoreState(window_state_value) settings.endGroup() settings.beginGroup("graphic_settings_dock") visible_value = settings.value("visible") if visible_value is not None: if visible_value == "true": self.graphic_settings_dock.setVisible(True) elif visible_value == "false": self.graphic_settings_dock.setVisible(False) settings.endGroup() # settings.beginGroup("zero_loss_peak_dock") # visible_value = settings.value("visible") # if visible_value is not None: # if visible_value == "true": # self.zero_loss_peak_dock.setVisible(True) # elif visible_value == "false": # self.zero_loss_peak_dock.setVisible(False) # settings.endGroup() def import_spectrum(self): self.statusBar().showMessage("Import spectrum", 2000) path = os.path.dirname(__file__) formats = ["*.msa", "*.txt"] file_filters = "Spectrum file ({:s})".format(" ".join(formats)) file_names = QFileDialog.getOpenFileName(self, "Import an x-ray spectrum", path, file_filters) def export_spectrum(self): self.statusBar().showMessage("Export spectrum", 2000) def new_project(self): self.statusBar().showMessage("New project", 2000) def open_project(self): self.statusBar().showMessage("Open project", 2000) def close_project(self): self.statusBar().showMessage("Close project", 2000) def save_project(self): self.statusBar().showMessage("Save project", 2000) def saveas_project(self): self.statusBar().showMessage("Save project as ...", 2000) def create_gui(self): self.logger.info("MainWindow.create_gui") self._create_main_window() self._create_actions() self._create_menus() self._create_toolbars() self._create_tooltip() self._create_spectra_display() self._create_data_display() self._create_operations_display() self._create_layout() self._create_statusbar() self._read_settings() self.show() def _create_main_window(self): self.setGeometry(300, 300, 500, 500) self.setWindowTitle('Spectrum Analyzer') # self.setWindowIcon(QIcon('../../../images/cog.svg')) self.setWindowIcon(self.style().standardIcon(QStyle.SP_DesktopIcon)) self._center_main_window() def _center_main_window(self): self.logger.info("MainWindow._center_main_window") qr = self.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) def _create_menus(self): self.logger.info("MainWindow._create_menus") self.fileMenu = self.menuBar().addMenu("&File") self.fileMenu.addAction(self.newAct) self.fileMenu.addAction(self.openAct) self.fileMenu.addAction(self.saveAct) self.fileMenu.addAction(self.saveAsAct) self.fileMenu.addSeparator() self.fileMenu.addAction(self.exitAct) self.menuBar().addSeparator() self.helpMenu = self.menuBar().addMenu("&Help") self.helpMenu.addAction(self.aboutAct) self.helpMenu.addAction(self.aboutQtAct) def _create_layout(self): mainLayout = QHBoxLayout() mainLayout.addWidget(self.dataGroupBox) mainLayout.addWidget(self.plotGroupBox) mainLayout.addWidget(self.operationsGroupBox) self.mainGroupBox = QGroupBox("Main layout") self.mainGroupBox.setLayout(mainLayout) self.setCentralWidget(self.mainGroupBox) def _create_spectra_display(self): self.plotGroupBox = QGroupBox("Plot layout") self.figure1 = Figure(facecolor=(1, 1, 1), edgecolor=(0, 0, 0)) self.canvas1 = FigureCanvas(self.figure1) self.canvas1.setParent(self.plotGroupBox) self.canvas1.setFocusPolicy(Qt.StrongFocus) self.canvas1.setFocus() self.canvas1.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.canvas1.updateGeometry() self.mpl_toolbar1 = NavigationToolbar(self.canvas1, self.plotGroupBox) self.canvas1.mpl_connect('key_press_event', self.on_key_press) self.figure2 = Figure(facecolor=(1, 1, 1), edgecolor=(0, 0, 0)) self.canvas2 = FigureCanvas(self.figure2) self.canvas2.setParent(self.plotGroupBox) self.mpl_toolbar2 = NavigationToolbar(self.canvas1, self.plotGroupBox) layout = QVBoxLayout() layout.addWidget(self.canvas1) layout.addWidget(self.mpl_toolbar1) layout.addWidget(self.canvas2) layout.addWidget(self.mpl_toolbar2) self.plotGroupBox.setLayout(layout) def _create_data_display(self): self.dataGroupBox = QGroupBox("Data layout") data_layout = QVBoxLayout() group_box = QGroupBox("Spectra") self.spectra_list_view = QListWidget(self) self.spectra_list_view.setMinimumWidth(200) layout = QVBoxLayout() layout.addWidget(self.spectra_list_view) group_box.setLayout(layout) data_layout.addWidget(group_box) group_box = QGroupBox("ROI") roi_list_view = QListWidget(self) layout = QVBoxLayout() layout.addWidget(roi_list_view) group_box.setLayout(layout) data_layout.addWidget(group_box) group_box = QGroupBox("Elements") element_list_view = QListWidget(self) layout = QVBoxLayout() layout.addWidget(element_list_view) group_box.setLayout(layout) data_layout.addWidget(group_box) self.dataGroupBox.setLayout(data_layout) def _create_operations_display(self): self.operationsGroupBox = QGroupBox("Operations layout") results_layout = QVBoxLayout() group_box = QGroupBox("Operation") results_layout.addWidget(group_box) group_box = QGroupBox("Results") results_layout.addWidget(group_box) self.operationsGroupBox.setLayout(results_layout) def _create_tooltip(self): QToolTip.setFont(QFont('SansSerif', 10)) self.setToolTip('This is a <b>QWidget</b> widget') def _create_actions(self): self.logger.info("MainWindow._create_actions") self.newAct = QAction(self.style().standardIcon(QStyle.SP_FileIcon), "&New", self, shortcut=QKeySequence.New, statusTip="Create a new file", triggered=self.newFile) self.openAct = QAction(self.style().standardIcon( QStyle.SP_DirOpenIcon), "&Open...", self, shortcut=QKeySequence.Open, statusTip="Open an existing file", triggered=self.open) self.saveAct = QAction(self.style().standardIcon( QStyle.SP_DialogSaveButton), "&Save", self, shortcut=QKeySequence.Save, statusTip="Save the document to disk", triggered=self.save) self.saveAsAct = QAction( self.style().standardIcon(QStyle.SP_DialogSaveButton), "Save &As...", self, shortcut=QKeySequence.SaveAs, statusTip="Save the document under a new name", triggered=self.saveAs) self.exitAct = QAction(self.style().standardIcon( QStyle.SP_DialogCloseButton), "E&xit", self, shortcut="Ctrl+Q", statusTip="Exit the application", triggered=self.close) self.textEdit = QTextEdit() self.aboutAct = QAction(self.style().standardIcon( QStyle.SP_MessageBoxInformation), "&About", self, statusTip="Show the application's About box", triggered=self.about) self.aboutQtAct = QAction(self.style().standardIcon( QStyle.SP_TitleBarMenuButton), "About &Qt", self, statusTip="Show the Qt library's About box", triggered=QApplication().aboutQt) def _create_toolbars(self): self.logger.info("MainWindow._create_toolbars") self.fileToolBar = self.addToolBar("File") self.fileToolBar.addAction(self.newAct) self.fileToolBar.addAction(self.openAct) self.fileToolBar.addAction(self.saveAct) def _create_statusbar(self): self.logger.info("MainWindow._create_statusbar") self.statusBar().showMessage("Ready") def _read_settings(self): self.logger.info("MainWindow._read_settings") settings = QSettings(ORGANIZATION_NAME, APPLICATION_NAME) pos = settings.value("pos", QPoint(200, 200)) size = settings.value("size", QSize(400, 400)) self.resize(size) self.move(pos) def _write_settings(self): self.logger.info("MainWindow._write_settings") settings = QSettings(ORGANIZATION_NAME, APPLICATION_NAME) settings.setValue("pos", self.pos()) settings.setValue("size", self.size()) def maybeSave(self): self.logger.info("MainWindow.maybeSave") if self.textEdit.document().isModified(): ret = QMessageBox.warning( self, "Application", "The document has been modified.\nDo you want to save " "your changes?", QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel) if ret == QMessageBox.Save: return self.save() elif ret == QMessageBox.Cancel: return False return True def closeEvent(self, event): self.logger.info("MainWindow.closeEvent") if self.maybeSave(): self._write_settings() event.accept() else: event.ignore() def newFile(self): self.logger.info("MainWindow.newFile") if self.maybeSave(): self.textEdit.clear() self.setCurrentFile('') def open(self): self.logger.info("MainWindow.open") if self.maybeSave(): filepath, _filtr = QFileDialog.getOpenFileName(self) if filepath: self.spectrumAnalyzer.readSpectrum(filepath) filename = os.path.basename(filepath) self.spectra_list_view.addItem(filename) self.spectrumAnalyzer.plotSpectrum(self.figure1) self.canvas1.draw() def save(self): self.logger.info("MainWindow.save") if self.curFile: return self.saveFile(self.curFile) return self.saveAs() def saveAs(self): self.logger.info("MainWindow.saveAs") fileName, _filtr = QFileDialog.getSaveFileName(self) if fileName: return self.saveFile(fileName) return False def about(self): self.logger.info("MainWindow.about") QMessageBox.about( self, "About xrayspectrumanalyzer", "The <b>xrayspectrumanalyzer</b> extract peak intensity from EDS spectrum." ) def documentWasModified(self): self.logger.info("MainWindow.documentWasModified") self.setWindowModified(self.textEdit.document().isModified()) def on_key_press(self, event): print('you pressed', event.key) # implement the default mpl key press events described at # http://matplotlib.org/users/navigation_toolbar.html#navigation-keyboard-shortcuts key_press_handler(event, self.canvas1, self.mpl_toolbar1)
class WorkspaceExplorer(BaseExtension): @BaseExtension.as_thread(wait=2500) def event_startup(self): dm = DataMatrix(length=0) dm.initializing = -1 self._qdm = WorkspaceMatrix(dm, read_only=True) self._qdm.cell_double_clicked.connect(self._inspect_variable) self._dock_widget = QDockWidget(self.main_window) self._dock_widget.setWidget(self._qdm) self._dock_widget.closeEvent = self._on_close_event self._dock_widget.setWindowTitle(_(u'Workspace')) self._dock_widget.setObjectName('WorkspaceExplorer') self._dock_widget.visibilityChanged.connect( self._on_visibility_changed) self.main_window.addDockWidget(Qt.RightDockWidgetArea, self._dock_widget) self._set_visible(cfg.workspace_visible) def _inspect_variable(self, row, column): if not row: return name = self._qdm.dm.name[row - 1] self.extension_manager.fire( 'data_viewer_inspect', name=name, workspace=self.extension_manager.provide('jupyter_workspace_name')) def activate(self): if not hasattr(self, '_qdm'): oslogger.info('ignoring activate until after startup') return self._set_visible(not cfg.workspace_visible) def _on_visibility_changed(self, visible): if not visible: return self._update( self.extension_manager.provide('jupyter_workspace_name'), lambda: self.extension_manager.provide('jupyter_workspace_globals')) def _on_close_event(self, e): self._set_visible(False) def _update(self, name, workspace_func): if (not hasattr(self, '_dock_widget') or not self._dock_widget.isVisible()): return self._dock_widget.setWindowTitle(_(u'Workspace ({})').format(name)) workspace = workspace_func() # If the workspace didn't reply, we try again in a second if workspace is None or workspace.get(u'no reply', False) is None: QTimer.singleShot(1000, lambda: self._update(name, workspace_func)) return # If the current kernel doesn't expose its workspace, indicate this if workspace.get(u'not supported', False) is None: dm = DataMatrix(length=0) dm.kernel_not_supported = -1 # Create a DataMatrix that exposes the workspace else: dm = DataMatrix(length=len(workspace)) dm.sorted = False dm.name = '' dm.value = '' dm.shape = '' dm.type = '' for row, (var, data) in zip(dm, workspace.items()): if data is None: oslogger.warning(u'invalid workspace data: {}'.format(var)) continue value, type_, shape = data row.value = value row.name = var if shape is not None: row.shape = repr(shape) row.type = type_ self._qdm.dm = dm self._qdm.refresh() def _set_visible(self, visible): cfg.workspace_visible = visible self.set_checked(visible) if visible: self._dock_widget.show() else: self._dock_widget.hide() def event_workspace_update(self, name, workspace_func): self._update(name, workspace_func) def event_workspace_restart(self, name, workspace_func): self._update(name, workspace_func) def event_workspace_switch(self, name, workspace_func): self._update(name, workspace_func) def event_workspace_new(self, name, workspace_func): self._update(name, workspace_func)
class MainWindow(QMainWindow): def __init__(self, parent=None): super().__init__(parent) self.recording_enabled = False self.serial = serial.Serial() self.rootnode = JsonNode('') self._connected = False self._dirty = False self._filename = None # settings self.settings = QSettingsManager() set_default_settings(self.settings) # Controller Settings self.settingsDialog = None # object explorer self.objectexplorer = ObjectExplorer(self.rootnode, self) self.objectexplorer.nodevalue_changed.connect(self.send_serialdata) self.objectexplorer.nodeproperty_changed.connect(self.set_dirty) self.objectexplorerDockWidget = QDockWidget(self.tr("object explorer"), self) self.objectexplorerDockWidget.setObjectName( "objectexplorer_dockwidget") self.objectexplorerDockWidget.setWidget(self.objectexplorer) # plot widget self.plot = PlotWidget(self.rootnode, self.settings, self) # plot settings self.plotsettings = PlotSettingsWidget(self.settings, self.plot, self) self.plotsettingsDockWidget = QDockWidget(self.tr("plot settings"), self) self.plotsettingsDockWidget.setObjectName("plotsettings_dockwidget") self.plotsettingsDockWidget.setWidget(self.plotsettings) # log widget self.loggingWidget = LoggingWidget(self) self.loggingDockWidget = QDockWidget(self.tr("logger"), self) self.loggingDockWidget.setObjectName("logging_dockwidget") self.loggingDockWidget.setWidget(self.loggingWidget) # record widget self.recordWidget = RecordWidget(self.rootnode, self) self.recordDockWidget = QDockWidget(self.tr("data recording"), self) self.recordDockWidget.setObjectName("record_dockwidget") self.recordDockWidget.setWidget(self.recordWidget) # actions and menus self._init_actions() self._init_menus() # statusbar statusbar = self.statusBar() statusbar.setVisible(True) self.connectionstateLabel = QLabel(self.tr("Not connected")) statusbar.addPermanentWidget(self.connectionstateLabel) statusbar.showMessage(self.tr("Ready")) # layout self.setCentralWidget(self.plot) self.addDockWidget(Qt.LeftDockWidgetArea, self.objectexplorerDockWidget) self.addDockWidget(Qt.LeftDockWidgetArea, self.plotsettingsDockWidget) self.addDockWidget(Qt.BottomDockWidgetArea, self.loggingDockWidget) self.addDockWidget(Qt.BottomDockWidgetArea, self.recordDockWidget) self.load_settings() def _init_actions(self): # Serial Dialog self.serialdlgAction = QAction(self.tr("Serial Settings..."), self) self.serialdlgAction.setShortcut("F6") self.serialdlgAction.setIcon(QIcon(pixmap("configure.png"))) self.serialdlgAction.triggered.connect(self.show_serialdlg) # Connect self.connectAction = QAction(self.tr("Connect"), self) self.connectAction.setShortcut("F5") self.connectAction.setIcon(QIcon(pixmap("network-connect-3.png"))) self.connectAction.triggered.connect(self.toggle_connect) # Quit self.quitAction = QAction(self.tr("Quit"), self) self.quitAction.setShortcut("Alt+F4") self.quitAction.setIcon(QIcon(pixmap("window-close-3.png"))) self.quitAction.triggered.connect(self.close) # Save Config as self.saveasAction = QAction(self.tr("Save as..."), self) self.saveasAction.setShortcut("Ctrl+Shift+S") self.saveasAction.setIcon(QIcon(pixmap("document-save-as-5.png"))) self.saveasAction.triggered.connect(self.show_savecfg_dlg) # Save file self.saveAction = QAction(self.tr("Save"), self) self.saveAction.setShortcut("Ctrl+S") self.saveAction.setIcon(QIcon(pixmap("document-save-5.png"))) self.saveAction.triggered.connect(self.save_file) # Load file self.loadAction = QAction(self.tr("Open..."), self) self.loadAction.setShortcut("Ctrl+O") self.loadAction.setIcon(QIcon(pixmap("document-open-7.png"))) self.loadAction.triggered.connect(self.show_opencfg_dlg) # New self.newAction = QAction(self.tr("New"), self) self.newAction.setShortcut("Ctrl+N") self.newAction.setIcon(QIcon(pixmap("document-new-6.png"))) self.newAction.triggered.connect(self.new) # start recording self.startrecordingAction = QAction(self.tr("Start recording"), self) self.startrecordingAction.setShortcut("F9") self.startrecordingAction.setIcon(QIcon(pixmap("media-record-6.png"))) self.startrecordingAction.triggered.connect(self.start_recording) # stop recording self.stoprecordingAction = QAction(self.tr("Stop recording"), self) self.stoprecordingAction.setShortcut("F10") self.stoprecordingAction.setIcon(QIcon(pixmap("media-playback-stop-8.png"))) self.stoprecordingAction.setEnabled(False) self.stoprecordingAction.triggered.connect(self.stop_recording) # clear record self.clearrecordAction = QAction(self.tr("Clear"), self) self.clearrecordAction.setIcon(QIcon(pixmap("editclear.png"))) self.clearrecordAction.triggered.connect(self.clear_record) # export record self.exportcsvAction = QAction(self.tr("Export to csv..."), self) self.exportcsvAction.setIcon(QIcon(pixmap("text_csv.png"))) self.exportcsvAction.triggered.connect(self.export_csv) # show record settings self.recordsettingsAction = QAction(self.tr("Settings..."), self) self.recordsettingsAction.setIcon(QIcon(pixmap("configure.png"))) self.recordsettingsAction.triggered.connect(self.show_recordsettings) # Info self.infoAction = QAction(self.tr("Info"), self) self.infoAction.setShortcut("F1") self.infoAction.triggered.connect(self.show_info) def _init_menus(self): # file menu self.fileMenu = self.menuBar().addMenu(self.tr("File")) self.fileMenu.addAction(self.newAction) self.fileMenu.addAction(self.loadAction) self.fileMenu.addAction(self.saveAction) self.fileMenu.addAction(self.saveasAction) self.fileMenu.addSeparator() self.fileMenu.addAction(self.connectAction) self.fileMenu.addAction(self.serialdlgAction) self.fileMenu.addSeparator() self.fileMenu.addAction(self.quitAction) # view menu self.viewMenu = self.menuBar().addMenu(self.tr("View")) self.viewMenu.addAction( self.objectexplorerDockWidget.toggleViewAction()) self.viewMenu.addAction(self.plotsettingsDockWidget.toggleViewAction()) self.viewMenu.addAction(self.loggingDockWidget.toggleViewAction()) self.viewMenu.addAction(self.recordDockWidget.toggleViewAction()) # record menu self.recordMenu = self.menuBar().addMenu(self.tr("Record")) self.recordMenu.addAction(self.startrecordingAction) self.recordMenu.addAction(self.stoprecordingAction) self.recordMenu.addAction(self.exportcsvAction) self.recordMenu.addSeparator() self.recordMenu.addAction(self.clearrecordAction) self.recordMenu.addSeparator() self.recordMenu.addAction(self.recordsettingsAction) # info menu self.menuBar().addAction(self.infoAction) def show_info(self): QMessageBox.about( self, QApplication.applicationName(), "%s %s\n" "Copyright (c) by %s" % ( QCoreApplication.applicationName(), QCoreApplication.applicationVersion(), QCoreApplication.organizationName(), ) ) def load_file(self, filename): old_filename = self.filename if self.filename != filename else None self.filename = filename try: with open(filename, 'rb') as f: try: self.objectexplorer.model().beginResetModel() self.rootnode.load(bytearray_to_utf8(f.read())) self.objectexplorer.model().endResetModel() except ValueError as e: critical(self, "File '%s' is not a valid config file." % filename) logger.error(str(e)) if old_filename is not None: self.load_file(old_filename) else: self.filename = None except FileNotFoundError as e: logger.error(str(e)) self.filename = None self.objectexplorer.refresh() def load_settings(self): settings = QSettings() # window geometry try: self.restoreGeometry(settings.value(GEOMETRY_SETTING)) except: logger.debug("error restoring window geometry") # window state try: self.restoreState(settings.value(WINDOWSTATE_SETTING)) except: logger.debug("error restoring window state") # filename self.filename = settings.value(FILENAME_SETTING) if self.filename is not None: self.load_file(self.filename) def save_settings(self): settings = QSettings() settings.setValue(WINDOWSTATE_SETTING, self.saveState()) settings.setValue(GEOMETRY_SETTING, self.saveGeometry()) settings.setValue(FILENAME_SETTING, self.filename) def closeEvent(self, event): if self.dirty: res = QMessageBox.question( self, QCoreApplication.applicationName(), self.tr("Save changes to file '%s'?" % self.filename if self.filename is not None else "unknown"), QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel ) if res == QMessageBox.Cancel: event.ignore() return elif res == QMessageBox.Yes: self.save_file() self.save_settings() try: self.worker.quit() except AttributeError: pass try: self.serial.close() except (SerialException, AttributeError): pass def new(self): self.objectexplorer.model().beginResetModel() self.rootnode.clear() self.objectexplorer.model().endResetModel() def send_reset(self): jsonstring = json.dumps({"resetpid": 1}) self.serial.write(bytearray(jsonstring, 'utf-8')) def receive_serialdata(self, time, data): self.loggingWidget.log_input(data) try: self.rootnode.from_json(data) except ValueError as e: logger.error(str(e)) # refresh widgets self.objectexplorer.refresh() self.plot.refresh(time) if self.recording_enabled: self.recordWidget.add_data(time, self.rootnode) def send_serialdata(self, node): if isinstance(node, JsonItem): if self.serial.isOpen(): s = node.to_json() self.serial.write(utf8_to_bytearray(s + '\n')) self.loggingWidget.log_output(s.strip()) def show_serialdlg(self): dlg = SerialDialog(self.settings, self) dlg.exec_() def toggle_connect(self): if self.serial.isOpen(): self.disconnect() else: self.connect() def connect(self): # Load port setting port = self.settings.get(PORT_SETTING) baudrate = self.settings.get(BAUDRATE_SETTING) # If no port has been selected before show serial settings dialog if port is None: if self.show_serialdlg() == QDialog.Rejected: return port = self.settings.get(PORT_SETTING) baudrate = self.settings.get(BAUDRATE_SETTING) # Serial connection try: self.serial.port = port self.serial.baudrate = baudrate self.serial.open() except ValueError: QMessageBox.critical( self, QCoreApplication.applicationName(), self.tr("Serial parameters e.g. baudrate, databits are out " "of range.") ) except SerialException: QMessageBox.critical( self, QCoreApplication.applicationName(), self.tr("The device '%s' can not be found or can not be " "configured." % port) ) else: self.worker = SerialWorker(self.serial, self) self.worker.data_received.connect(self.receive_serialdata) self.worker.start() self.connectAction.setText(self.tr("Disconnect")) self.connectAction.setIcon(QIcon(pixmap("network-disconnect-3.png"))) self.serialdlgAction.setEnabled(False) self.connectionstateLabel.setText( self.tr("Connected to %s") % port) self._connected = True self.objectexplorer.refresh() def disconnect(self): self.worker.quit() self.serial.close() self.connectAction.setText(self.tr("Connect")) self.connectAction.setIcon(QIcon(pixmap("network-connect-3.png"))) self.serialdlgAction.setEnabled(True) self.connectionstateLabel.setText(self.tr("Not connected")) self._connected = False self.objectexplorer.refresh() def show_savecfg_dlg(self): filename, _ = QFileDialog.getSaveFileName( self, self.tr("Save configuration file..."), directory=os.path.expanduser("~"), filter="Json file (*.json)" ) if filename: self.filename = filename self.save_file() def save_file(self): if self.filename is not None: config_string = self.rootnode.dump() with open(self.filename, 'w') as f: f.write(config_string) self.dirty = False else: self.show_savecfg_dlg() def show_opencfg_dlg(self): # show file dialog filename, _ = QFileDialog.getOpenFileName( self, self.tr("Open configuration file..."), directory=os.path.expanduser("~"), filter=self.tr("Json file (*.json);;All files (*.*)") ) # load config file if filename: self.load_file(filename) def refresh_window_title(self): s = "%s %s" % (QCoreApplication.applicationName(), QCoreApplication.applicationVersion()) if self.filename is not None: s += " - " + self.filename if self.dirty: s += "*" self.setWindowTitle(s) def start_recording(self): self.recording_enabled = True self.startrecordingAction.setEnabled(False) self.stoprecordingAction.setEnabled(True) def stop_recording(self): self.recording_enabled = False self.startrecordingAction.setEnabled(True) self.stoprecordingAction.setEnabled(False) def export_csv(self): filename, _ = QFileDialog.getSaveFileName( self, QCoreApplication.applicationName(), filter="CSV files(*.csv);;All files (*.*)" ) if filename == "": return # get current dataframe and export to csv df = self.recordWidget.dataframe decimal = self.settings.get(DECIMAL_SETTING) df = df.applymap(lambda x: str(x).replace(".", decimal)) df.to_csv( filename, index_label="time", sep=self.settings.get(SEPARATOR_SETTING) ) def clear_record(self): self.recordWidget.clear() def show_recordsettings(self): dlg = CSVSettingsDialog(self) dlg.exec_() # filename property @property def filename(self): return self._filename @filename.setter def filename(self, value=""): self._filename = value self.refresh_window_title() # dirty property @property def dirty(self): return self._dirty @dirty.setter def dirty(self, value): self._dirty = value self.refresh_window_title() def set_dirty(self): self.dirty = True # connected property @property def connected(self): return self._connected
def _main(args): # To avoid problems when testing without screen if args.test or args.screenshots: os.environ['QT_QPA_PLATFORM'] = 'offscreen' # Set QT_API variable before importing QtPy if args.qt_from in ['pyqt', 'pyqt5', 'pyside', 'pyside2']: os.environ['QT_API'] = args.qt_from elif args.qt_from == 'pyqtgraph': os.environ['QT_API'] = os.environ['PYQTGRAPH_QT_LIB'] elif args.qt_from in ['qt.py', 'qt']: try: import Qt except ImportError: print('Could not import Qt (Qt.Py)') else: os.environ['QT_API'] = Qt.__binding__ # QtPy imports from qtpy import API_NAME, QT_VERSION, PYQT_VERSION, PYSIDE_VERSION from qtpy import __version__ as QTPY_VERSION from qtpy.QtWidgets import (QApplication, QMainWindow, QDockWidget, QStatusBar, QLabel, QMenu) from qtpy.QtCore import QTimer, Qt, QSettings # Set API_VERSION variable API_VERSION = '' if PYQT_VERSION: API_VERSION = PYQT_VERSION elif PYSIDE_VERSION: API_VERSION = PYSIDE_VERSION else: API_VERSION = 'Not found' # Import examples UI from mw_menus_ui import Ui_MainWindow as ui_main from dw_buttons_ui import Ui_DockWidget as ui_buttons from dw_displays_ui import Ui_DockWidget as ui_displays from dw_inputs_fields_ui import Ui_DockWidget as ui_inputs_fields from dw_inputs_no_fields_ui import Ui_DockWidget as ui_inputs_no_fields from dw_widgets_ui import Ui_DockWidget as ui_widgets from dw_views_ui import Ui_DockWidget as ui_views from dw_containers_tabs_ui import Ui_DockWidget as ui_containers_tabs from dw_containers_no_tabs_ui import Ui_DockWidget as ui_containers_no_tabs # qrainbowstyle.useDarwinButtons() QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps) QApplication.setAttribute(Qt.AA_EnableHighDpiScaling) # create the application if not QApplication.instance(): app = QApplication(sys.argv) else: app = QApplication.instance() app.setOrganizationName('QRainbowStyle') app.setApplicationName('QRainbowStyle Example') styles = qrainbowstyle.getAvailableStyles() style = args.style if not args.style: style = styles[random.randint(0, len(styles)) - 1] app.setStyleSheet(qrainbowstyle.load_stylesheet(style=str(style))) # create main window window = qrainbowstyle.windows.FramelessWindow() window.setTitlebarHeight(30) widget = QMainWindow(window) widget.setWindowFlags(Qt.Widget) widget.setObjectName('mainwindow') ui = ui_main() ui.setupUi(widget) window.addContentWidget(widget) title = ("QRainbowStyle Example - " + "(QRainbowStyle=v" + qrainbowstyle.__version__ + ", QtPy=v" + QTPY_VERSION + ", " + API_NAME + "=v" + API_VERSION + ", Qt=v" + QT_VERSION + ", Python=v" + platform.python_version() + ")") _logger.info(title) window.setWindowTitle(title) # Create docks for buttons dw_buttons = QDockWidget() dw_buttons.setObjectName('buttons') ui_buttons = ui_buttons() ui_buttons.setupUi(dw_buttons) widget.addDockWidget(Qt.RightDockWidgetArea, dw_buttons) # Add actions on popup toolbuttons menu = QMenu() for action in ['Action A', 'Action B', 'Action C']: menu.addAction(action) ui_buttons.toolButtonDelayedPopup.setMenu(menu) ui_buttons.toolButtonInstantPopup.setMenu(menu) ui_buttons.toolButtonMenuButtonPopup.setMenu(menu) # Create docks for buttons dw_displays = QDockWidget() dw_displays.setObjectName('displays') ui_displays = ui_displays() ui_displays.setupUi(dw_displays) widget.addDockWidget(Qt.RightDockWidgetArea, dw_displays) # Create docks for inputs - no fields dw_inputs_no_fields = QDockWidget() dw_inputs_no_fields.setObjectName('inputs_no_fields') ui_inputs_no_fields = ui_inputs_no_fields() ui_inputs_no_fields.setupUi(dw_inputs_no_fields) widget.addDockWidget(Qt.RightDockWidgetArea, dw_inputs_no_fields) # Create docks for inputs - fields dw_inputs_fields = QDockWidget() dw_inputs_fields.setObjectName('inputs_fields') ui_inputs_fields = ui_inputs_fields() ui_inputs_fields.setupUi(dw_inputs_fields) widget.addDockWidget(Qt.RightDockWidgetArea, dw_inputs_fields) # Create docks for widgets dw_widgets = QDockWidget() dw_widgets.setObjectName('widgets') ui_widgets = ui_widgets() ui_widgets.setupUi(dw_widgets) widget.addDockWidget(Qt.LeftDockWidgetArea, dw_widgets) # Create docks for views dw_views = QDockWidget() dw_views.setObjectName('views') ui_views = ui_views() ui_views.setupUi(dw_views) widget.addDockWidget(Qt.LeftDockWidgetArea, dw_views) # Create docks for containers - no tabs dw_containers_no_tabs = QDockWidget() dw_containers_no_tabs.setObjectName('containers_no_tabs') ui_containers_no_tabs = ui_containers_no_tabs() ui_containers_no_tabs.setupUi(dw_containers_no_tabs) widget.addDockWidget(Qt.LeftDockWidgetArea, dw_containers_no_tabs) # Create docks for containters - tabs dw_containers_tabs = QDockWidget() dw_containers_tabs.setObjectName('containers_tabs') ui_containers_tabs = ui_containers_tabs() ui_containers_tabs.setupUi(dw_containers_tabs) widget.addDockWidget(Qt.LeftDockWidgetArea, dw_containers_tabs) # Tabify right docks widget.tabifyDockWidget(dw_buttons, dw_displays) widget.tabifyDockWidget(dw_displays, dw_inputs_fields) widget.tabifyDockWidget(dw_inputs_fields, dw_inputs_no_fields) # Tabify left docks widget.tabifyDockWidget(dw_containers_no_tabs, dw_containers_tabs) widget.tabifyDockWidget(dw_containers_tabs, dw_widgets) widget.tabifyDockWidget(dw_widgets, dw_views) # Issues #9120, #9121 on Spyder qstatusbar = QStatusBar() qstatusbar.addWidget(QLabel('Style')) qstatusbarbutton = qrainbowstyle.widgets.StylePickerHorizontal() qstatusbar.addWidget(qstatusbarbutton) qstatusbar.setSizeGripEnabled(False) # Add info also in status bar for screenshots get it qstatusbar.addWidget(QLabel('INFO: ' + title)) widget.setStatusBar(qstatusbar) # Todo: add report info and other info in HELP graphical # Auto quit after 2s when in test mode if args.test: QTimer.singleShot(2000, app.exit) _read_settings(widget, args.reset, QSettings) window.show() # window.showMaximized() app.exec_() _write_settings(widget, QSettings)