def __init__(self, fileName, parent=None): QObject.__init__(self) sweepCollection = IvSweepCollection(str(fileName)) self.sweepCollection = sweepCollection tableModel = SweepTableModel(sweepCollection) tableView = QTableView() tableView.setModel(tableModel) tableView.setItemDelegateForColumn(0, CheckBoxDelegate(parent=tableView)) tableView.setItemDelegateForColumn(1, CheckBoxDelegate(parent=tableView)) self.tableModel = tableModel tableView.resizeColumnsToContents() tableView.setSelectionMode(QAbstractItemView.SingleSelection) tableView.setSelectionBehavior(QAbstractItemView.SelectRows) sm = tableView.selectionModel() sm.currentRowChanged.connect(self.selectedRowChanged) self.tableView = tableView dockWidget = QDockWidget('Sweeps') dockWidget.setWidget(tableView) self.sweepTableDock = dockWidget hkDock = HkDockWidget(sweepCollection.hk) hkDock.setWindowTitle('HK - %s' % str(fileName)) self.hkDock = hkDock ivGraphWidget = IvGraphWidget(sweepCollection) tableModel.plotToggled.connect(ivGraphWidget.showSweep) #tableModel.badToggled.connect(self.toggleBad) self.ivGraphWidget = ivGraphWidget
def test_main_window_find_window(main_window, qtbot): widget = QWidget() qtbot.addWidget(widget) dock = QDockWidget() qtbot.addWidget(dock) dock.setWidget(widget) main_window.addDockWidget(Qt.RightDockWidgetArea, dock) assert LucidMainWindow.find_window(widget) == main_window
def __init__(self, data_viewer, name, value, workspace): QDockWidget.__init__(self, data_viewer.main_window) self._data_viewer = data_viewer self._name = name self._workspace = workspace self.setObjectName('DataDockWidget_{}'.format(name)) self.refresh(value)
def __init__(self, parent): """ """ QDockWidget.__init__(self, parent) self.iPythonWidget = None return
def __init__( self, config_folder: Union[str, Path, None] = None, title="PartSeg", settings: Optional[BaseSettings] = None, load_dict: Optional[Register] = None, signal_fun=None, ): if settings is None: if config_folder is None: raise ValueError("wrong config folder") if not os.path.exists(config_folder): import_config() settings: BaseSettings = self.get_setting_class()(config_folder) errors = settings.load() if errors: errors_message = QMessageBox() errors_message.setText("There are errors during start") errors_message.setInformativeText( "During load saved state some of data could not be load properly\n" "The files has prepared backup copies in " " state directory (Help > State directory)") errors_message.setStandardButtons(QMessageBox.Ok) text = "\n".join("File: " + x[0] + "\n" + str(x[1]) for x in errors) errors_message.setDetailedText(text) errors_message.exec_() super().__init__() if signal_fun is not None: self.show_signal.connect(signal_fun) self.settings = settings self._load_dict = load_dict self.viewer_list: List[Viewer] = [] self.files_num = 1 self.setAcceptDrops(True) self.setWindowTitle(title) self.title_base = title app = QApplication.instance() if app is not None: app.setStyleSheet(settings.style_sheet) self.settings.theme_changed.connect(self.change_theme) self.channel_info = "" self.multiple_files = None self.settings.request_load_files.connect(self.read_drop) self.recent_file_menu = QMenu("Open recent") self._refresh_recent() self.settings.connect_(FILE_HISTORY, self._refresh_recent) self.settings.napari_settings.appearance.events.theme.connect( self.change_theme) self.settings.set_parent(self) self.console = None self.console_dock = QDockWidget("console", self) self.console_dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.BottomDockWidgetArea) # self.console_dock.setWidget(self.console) self.console_dock.hide() self.addDockWidget(Qt.BottomDockWidgetArea, self.console_dock)
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 __init__(self, subprocess_manager): QDockWidget.__init__(self, subprocess_manager.main_window) self._subprocess_manager = subprocess_manager self._qdm = QDataMatrix(self._subprocess_manager.dm(), read_only=True) self.setWidget(self._qdm) self.setWindowTitle(_('Subprocesses')) self.setObjectName('SubprocessManager') self.visibilityChanged.connect(self._refresh)
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, 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 __init__(self, tab_to_dockwidget, widget, name): QDockWidget.__init__(self, name, tab_to_dockwidget.main_window) self._tab_to_dockwidget = tab_to_dockwidget self.setWidget(widget) self.setObjectName(str(widget)) if hasattr(widget, u'__item__'): self._item = tab_to_dockwidget.experiment.items[widget.__item__] else: self._item = None
def _onViewerChanged(self, v_id, dock: QtWidgets.QDockWidget): if self._model.isActive(v_id): return if self._model.getActiveTab(): old_dock = self._model.getActiveTab() title = old_dock.windowTitle() title = title.replace(" <<", "") old_dock.setWindowTitle(title) v = self._model.getViewerCtrl(v_id) self._model.setActiveViewer(v) dock.setWindowTitle("{} <<".format(dock.windowTitle())) self._notifySubscribers(v, self._viewer_changed_subscribers)
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 build_layout(self): # TODO: Allow save/restore https://stackoverflow.com/questions/14288635/any-easy-way-to-store-dock-widows-layout-and-sizes-in-settings-with-qt # Clear out docks for dockwidget in self.findChildren(QDockWidget): if dockwidget.parent() == self: self.removeDockWidget(dockwidget) # Make new docks self.topwidget = QDockWidget(parent=self) self.leftwidget = QDockWidget(parent=self) self.rightwidget = QDockWidget(parent=self) self.bottomwidget = QDockWidget(parent=self) self.lefttopwidget = QDockWidget(parent=self) self.righttopwidget = QDockWidget(parent=self) self.leftbottomwidget = QDockWidget(parent=self) self.rightbottomwidget = QDockWidget(parent=self) # Place the docks self.addDockWidget(Qt.LeftDockWidgetArea, self.lefttopwidget) self.addDockWidget(Qt.RightDockWidgetArea, self.righttopwidget) self.addDockWidget(Qt.TopDockWidgetArea, self.topwidget) self.addDockWidget(Qt.LeftDockWidgetArea, self.leftwidget) self.addDockWidget(Qt.RightDockWidgetArea, self.rightwidget) self.addDockWidget(Qt.BottomDockWidgetArea, self.bottomwidget) self.addDockWidget(Qt.LeftDockWidgetArea, self.leftbottomwidget) self.addDockWidget(Qt.RightDockWidgetArea, self.rightbottomwidget) # Adjust spanning self.setCorner(Qt.TopLeftCorner, Qt.LeftDockWidgetArea) self.setCorner(Qt.TopRightCorner, Qt.RightDockWidgetArea) self.setCorner(Qt.BottomLeftCorner, Qt.LeftDockWidgetArea) self.setCorner(Qt.BottomRightCorner, Qt.RightDockWidgetArea)
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 setup_figure(self): self.figure = Figure() self.figure.canvas = FigureCanvas(self.figure) self.figure.canvas.mpl_connect('button_press_event', self.mouse_click) self.figure.add_subplot(111, projection="mantid") self.toolbar = FittingPlotToolbar(self.figure.canvas, self, False) self.toolbar.setMovable(False) self.dock_window = QMainWindow(self.group_plot) self.dock_window.setWindowFlags(Qt.Widget) self.dock_window.setDockOptions(QMainWindow.AnimatedDocks) self.dock_window.setCentralWidget(self.toolbar) self.plot_dock = QDockWidget() self.plot_dock.setWidget(self.figure.canvas) self.plot_dock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.plot_dock.setAllowedAreas(Qt.BottomDockWidgetArea) self.plot_dock.setWindowTitle("Fit Plot") self.plot_dock.topLevelChanged.connect(self.make_undocked_plot_larger) self.initial_chart_width, self.initial_chart_height = self.plot_dock.width( ), self.plot_dock.height() self.plot_dock.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.dock_window.addDockWidget(Qt.BottomDockWidgetArea, self.plot_dock) self.vLayout_plot.addWidget(self.dock_window) self.fit_browser = EngDiffFitPropertyBrowser( self.figure.canvas, ToolbarStateManager(self.toolbar)) # remove SequentialFit from fit menu (implemented a different way) qmenu = self.fit_browser.getFitMenu() qmenu.removeAction([ qact for qact in qmenu.actions() if qact.text() == "Sequential Fit" ][0]) # hide unnecessary properties of browser hide_props = [ 'Minimizer', 'Cost function', 'Max Iterations', 'Output', 'Ignore invalid data', 'Peak Radius', 'Plot Composite Members', 'Convolve Composite Members', 'Show Parameter Errors', 'Evaluate Function As' ] self.fit_browser.removePropertiesFromSettingsBrowser(hide_props) self.fit_browser.toggleWsListVisible() self.fit_browser.closing.connect(self.toolbar.handle_fit_browser_close) self.vLayout_fitprop.addWidget(self.fit_browser) self.fit_browser.hide()
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
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 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 __init__(self, title, parent): QDockWidget.__init__(self, title, parent) self.widget = QWidget(self) self.figure = Figure() # Figure(figsize=(4., 5), dpi=100) self.canvas = FigureCanvas(self.figure) self.canvas.setParent(self.widget) self.canvas.setFocusPolicy(QtCore.Qt.StrongFocus) self.setFocusPolicy(QtCore.Qt.StrongFocus) self.toolbar = NavigationToolbar(self.canvas, self) self.toolbar.hide() FigureCanvas.setSizePolicy(self.canvas, QSizePolicy.Expanding, QSizePolicy.Expanding) FigureCanvas.updateGeometry(self.canvas) vbox = QVBoxLayout() vbox.addWidget(self.canvas) vbox.addWidget(self.toolbar) self.toolbar.show() self.widget.setLayout(vbox) self.setWidget(self.widget)
def add_dock_widget(self, area: str = 'bottom', widget: QWidget = None, allowed_areas=None): """Convenience method to add a QDockWidget to the main window Parameters ---------- area : str Side of the main window to which the new dock widget will be added. Must be in {'left', 'right', 'top', 'bottom'} widget : QWidget, optional If provided, `widget` will be added as QDockWidget's main widget allowed_areas : Qt.DockWidgetArea, optional Areas, relative to main window, that the new dock is allowed to go. """ areas = { 'left': Qt.LeftDockWidgetArea, 'right': Qt.RightDockWidgetArea, 'top': Qt.TopDockWidgetArea, 'bottom': Qt.BottomDockWidgetArea, } if area not in areas: raise ValueError(f'side argument must be in {list(areas.keys())}') dock_widget = QDockWidget(self._qt_window) dock_widget.setAllowedAreas(allowed_areas or (Qt.LeftDockWidgetArea | Qt.BottomDockWidgetArea | Qt.RightDockWidgetArea | Qt.TopDockWidgetArea)) dock_widget.setMinimumHeight(50) dock_widget.setMinimumWidth(50) if isinstance(widget, QWidget): dock_widget.setWidget(widget) widget.setParent(dock_widget) self._qt_window.addDockWidget(areas[area], dock_widget) return dock_widget
def test_main_window_raise(main_window, qtbot, start_floating, close, finish_floating): # Add our docks dock1 = QDockWidget() qtbot.addWidget(dock1) dock2 = QDockWidget() qtbot.addWidget(dock2) main_window.addDockWidget(Qt.RightDockWidgetArea, dock1) main_window.addDockWidget(Qt.RightDockWidgetArea, dock2) # Setup dock dock1.setFloating(start_floating) if close: dock1.close() # Re-raise # main_window.raise_dock(dock1) assert dock1.isFloating() == finish_floating
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 _create_dock_widget(window, name, area, *, max_width=None): # create dock widget dock = QDockWidget(name) # add scroll area scroll = QScrollArea(dock) dock.setWidget(scroll) # give the scroll area a child widget widget = QWidget(scroll) scroll.setWidget(widget) scroll.setWidgetResizable(True) dock.setAllowedAreas(area) dock.setTitleBarWidget(QLabel(name)) window.addDockWidget(area, dock) dock_layout = QVBoxLayout() widget.setLayout(dock_layout) # Fix resize grip size # https://stackoverflow.com/a/65050468/2175965 styles = ['margin: 4px;'] if max_width is not None: styles.append(f'max-width: {max_width};') style_sheet = 'QDockWidget { ' + ' \n'.join(styles) + '\n}' dock.setStyleSheet(style_sheet) return dock, dock_layout
def appendHeader(self, header, **kwargs): filename = header._documents["start"][0]["filename"] self.active_filename = filename self.status_bar.setText("Loading Filename:" + filename) dataset, bkgs, drks = read_als_hdf5(filename) slice_widget = MyCatalogView() dw = QDockWidget() dw.setWidget(slice_widget) dw.setWindowTitle(filename) slice_widget.setImage(dataset) dock_children = self._main_view.findChildren(QDockWidget) print(dock_children) #if len(dock_children) == 0: # self._main_view.addDockWidget(Qt.LeftDockWidgetArea, dw) #else: # self._main_view.tabifyDockWidget(dock_children[0], dw) self._main_view.addDockWidget(Qt.LeftDockWidgetArea, dw) self.status_bar.setText("Done Loading Filename:" + filename)
def add_new_viewer_selected(self, checked): if self.top_controls_add_new_selector.count() == 0: return selected = self.top_controls_add_new_selector.currentIndex() if selected < 0: return workflow = self.top_controls_add_new_selector.currentData(Qt.UserRole) print("WORKFLOW", workflow, workflow.name) dock_widget = QDockWidget() viewer = CatalogView() dock_widget.setWidget(viewer) dock_widget.setWindowTitle(workflow.name) if len(self.active_workflows) == 0: self._main_view.addDockWidget(Qt.RightDockWidgetArea, dock_widget) else: self._main_view.tabifyDockWidget(self.active_workflows[-1][0], dock_widget) self.active_workflows.append((dock_widget, workflow))
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)
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()
class FittingPlotView(QtWidgets.QWidget, Ui_plot): def __init__(self, parent=None): super(FittingPlotView, self).__init__(parent) self.setupUi(self) self.figure = None self.toolbar = None self.fitprop_toolbar = None self.fit_browser = None self.plot_dock = None self.dock_window = None self.setup_figure() self.setup_toolbar() def setup_figure(self): self.figure = Figure() self.figure.canvas = FigureCanvas(self.figure) self.figure.canvas.mpl_connect('button_press_event', self.mouse_click) self.figure.add_subplot(111, projection="mantid") self.figure.tight_layout() self.toolbar = FittingPlotToolbar(self.figure.canvas, self, False) self.toolbar.setMovable(False) self.dock_window = QMainWindow(self.group_plot) self.dock_window.setWindowFlags(Qt.Widget) self.dock_window.setDockOptions(QMainWindow.AnimatedDocks) self.dock_window.setCentralWidget(self.toolbar) self.plot_dock = QDockWidget() self.plot_dock.setWidget(self.figure.canvas) self.plot_dock.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.plot_dock.setAllowedAreas(Qt.BottomDockWidgetArea) self.plot_dock.setWindowTitle("Fit Plot") self.dock_window.addDockWidget(Qt.BottomDockWidgetArea, self.plot_dock) self.vLayout_plot.addWidget(self.dock_window) self.fit_browser = EngDiffFitPropertyBrowser( self.figure.canvas, ToolbarStateManager(self.toolbar)) # remove SequentialFit from fit menu (implemented a different way) qmenu = self.fit_browser.getFitMenu() qmenu.removeAction([ qact for qact in qmenu.actions() if qact.text() == "Sequential Fit" ][0]) # hide unnecessary properties of browser hide_props = [ 'StartX', 'EndX', 'Minimizer', 'Cost function', 'Max Iterations', 'Output', 'Ignore invalid data', 'Peak Radius', 'Plot Composite Members', 'Convolve Composite Members', 'Show Parameter Errors', 'Evaluate Function As' ] self.fit_browser.removePropertiesFromSettingsBrowser(hide_props) self.fit_browser.toggleWsListVisible() self.fit_browser.closing.connect(self.toolbar.handle_fit_browser_close) self.vLayout_fitprop.addWidget(self.fit_browser) self.fit_browser.hide() def mouse_click(self, event): if event.button == event.canvas.buttond.get(Qt.RightButton): menu = QMenu() self.fit_browser.add_to_menu(menu) menu.exec_(QCursor.pos()) def resizeEvent(self, QResizeEvent): self.figure.tight_layout() def ensure_fit_dock_closed(self): if self.plot_dock.isFloating(): self.plot_dock.close() def setup_toolbar(self): self.toolbar.sig_home_clicked.connect(self.display_all) self.toolbar.sig_toggle_fit_triggered.connect(self.fit_toggle) # ================= # Component Setters # ================= def fit_toggle(self): """Toggle fit browser and tool on/off""" if self.fit_browser.isVisible(): self.fit_browser.hide() else: self.fit_browser.show() def clear_figure(self): self.figure.clf() self.figure.add_subplot(111, projection="mantid") self.figure.tight_layout() self.figure.canvas.draw() def update_figure(self): self.toolbar.update() self.figure.tight_layout() self.update_legend(self.get_axes()[0]) self.figure.canvas.draw() self.update_fitbrowser() def update_fitbrowser(self): is_visible = self.fit_browser.isVisible() self.toolbar.set_fit_checkstate(False) self.fit_browser.hide() if self.fit_browser.getWorkspaceNames() and is_visible: self.toolbar.set_fit_checkstate(True) self.fit_browser.show() def remove_ws_from_fitbrowser(self, ws): # only one spectra per workspace self.fit_browser.removeWorkspaceAndSpectra(ws.name()) def update_legend(self, ax): if ax.get_lines(): ax.make_legend() ax.get_legend().set_title("") else: if ax.get_legend(): ax.get_legend().remove() def display_all(self): for ax in self.get_axes(): if ax.lines: ax.relim() ax.autoscale() self.update_figure() def read_fitprop_from_browser(self): return self.fit_browser.read_current_fitprop() def update_browser(self, status, func_str, setup_name): self.fit_browser.fitResultsChanged.emit(status) self.fit_browser.changeWindowTitle.emit(status) # update browser with output function and save setup if successful if "success" in status.lower(): self.fit_browser.loadFunction(func_str) self.fit_browser.save_current_setup(setup_name) # ================= # Component Getters # ================= def get_axes(self): return self.figure.axes def get_figure(self): return self.figure
def __init__(self, hkData, parent=None): QDockWidget.__init__(self, parent) self.hkData = hkData faaTimeAxis = pg.DateAxisItem(orientation='bottom') faaTempPlot = pg.PlotWidget(axisItems={'bottom': faaTimeAxis}) gggTimeAxis = pg.DateAxisItem(orientation='bottom') gggTempPlot = pg.PlotWidget(axisItems={'bottom': gggTimeAxis}) for plot in [gggTempPlot, faaTempPlot]: plot.setBackground('w') plot.showGrid(x=True, y=True) plot.setLabel('left', 'T', 'K') #plot.setLabel('bottom', 'time') plot.addLegend() faaTempPlot.setXLink(gggTempPlot) pens = { 'BusThermometer': 'r', 'RuOx2005Thermometer': 'b', 'BoxThermometer': 'g', 'GGG': 'k' } for thermometerId in self.hkData.thermometers.keys(): thermo = self.hkData.thermometers[thermometerId] try: pen = pens[thermometerId] except KeyError: pen = 'k' curve = pg.PlotDataItem(name=thermometerId, pen=pen) curve.setData(thermo.t, thermo.T) #curve.setPen(pen) if thermometerId in [ 'BoxThermometer', 'BusThermometer', 'RuOx2005Thermometer' ]: faaTempPlot.addItem(curve) elif thermometerId in ['GGG']: gggTempPlot.addItem(curve) else: print('Ignoring thermometer:', thermometerId) magnetTimeAxis = pg.DateAxisItem(orientation='bottom') magnetPlot = pg.PlotWidget(axisItems={'bottom': magnetTimeAxis}) magnetPlot.setBackground('w') magnetPlot.showGrid(x=True, y=True) magnetPlot.setLabel('left', 'Magnet I', 'A') #magnetPlot.setLabel('bottom', 'time') magnetPlot.addLegend() magnet = hkData.magnet magnet.Ifine curve = pg.PlotDataItem(name='I (fine)', pen='b') curve.setData(magnet.t, magnet.Ifine) magnetPlot.addItem(curve) curve = pg.PlotDataItem(name='I (coarse)', pen='r') curve.setData(magnet.t, magnet.Icoarse) magnetPlot.addItem(curve) magnetPlot.setXLink(faaTempPlot) splitter = QSplitter(Qt.Vertical) splitter.addWidget(faaTempPlot) splitter.addWidget(gggTempPlot) splitter.addWidget(magnetPlot) self.setWidget(splitter) self.faaTempPlot = faaTempPlot self.gggTempPlot = gggTempPlot self.magnetPlot = magnetPlot self.lri = None
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))))
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): def __init__(self): super(MainWindow, self).__init__() self.mdiArea = QMdiArea() self.mdiArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) self.mdiArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) # self.mdiArea.setViewMode(QMdiArea.TabbedView) self.setCentralWidget(self.mdiArea) self.create_menus() self.setWindowTitle("Boa data") def create_menus(self): exit_action = QAction('&Exit', self) # exitAction = QtGui.QAction(QtGui.QIcon('exit.png'), '&Exit', self) exit_action.setShortcut('Ctrl+Q') exit_action.setStatusTip('Exit application') exit_action.triggered.connect(qApp.quit) menubar = self.menuBar() file_menu = menubar.addMenu('&File') open_menu = file_menu.addMenu('&Open') open_file_action = QAction('&File', self) open_file_action.triggered.connect(self.openFile) open_dir_action = QAction('&Directory', self) open_dir_action.triggered.connect(self.openDirDialog) open_menu.addAction(open_file_action) open_menu.addAction(open_dir_action) file_menu.addAction(exit_action) def openFile(self): pass def openDirDialog(self): dialog = QFileDialog(self) dialog.setFileMode(QFileDialog.DirectoryOnly) if dialog.exec_(): directory = dialog.selectedFiles()[0] self.openDir(directory) def openDir(self, path): node = DirectoryTree(path) model = DataTreeModel(node) self.show_tree(model) def show_tree(self, model): widget = DataTreeView(model, main_window=self) self.tree_dock = QDockWidget(model.title, self) self.tree_dock.setWidget(widget) self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.tree_dock) def show_view(self, view, data_object): sw = QMdiSubWindow() widget = view(data_object).create_widget() sw.setWidget(widget) sw.setAttribute(QtCore.Qt.WA_DeleteOnClose) sw.setWindowTitle(data_object.title + "(" + view.title + ")") self.mdiArea.addSubWindow(sw) sw.show() def show_object(self, data_object): sw = DataObjectWindow(data_object=data_object, parent=self) self.mdiArea.addSubWindow(sw) sw.show() # sw.widget().show() # widget.setFocus()
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)
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 show_tree(self, model): widget = DataTreeView(model, main_window=self) self.tree_dock = QDockWidget(model.title, self) self.tree_dock.setWidget(widget) self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.tree_dock)