Exemplo n.º 1
0
    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
Exemplo n.º 2
0
 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)
Exemplo n.º 3
0
 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
Exemplo n.º 4
0
 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
Exemplo n.º 5
0
 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
Exemplo n.º 6
0
    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
Exemplo n.º 7
0
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)
Exemplo n.º 8
0
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)
Exemplo n.º 9
0
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))))
Exemplo n.º 10
0
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
Exemplo n.º 11
0
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)
Exemplo n.º 13
0
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)
Exemplo n.º 14
0
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
Exemplo n.º 15
0
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)