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.initial_chart_width = None self.initial_chart_height = None self.has_first_undock_occurred = 0 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.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 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.update_axes_position() def make_undocked_plot_larger(self): # only make undocked plot larger the first time it is undocked as the undocked size gets remembered if self.plot_dock.isFloating() and self.has_first_undock_occurred == 0: factor = 1.0 aspect_ratio = self.initial_chart_width / self.initial_chart_height new_height = self.initial_chart_height * factor docked_height = self.dock_window.height() if docked_height > new_height: new_height = docked_height new_width = new_height * aspect_ratio self.plot_dock.resize(new_width, new_height) self.has_first_undock_occurred = 1 self.update_axes_position() 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.canvas.draw() def update_figure(self): self.toolbar.update() self.update_legend(self.get_axes()[0]) self.update_axes_position() self.figure.canvas.draw() self.update_fitbrowser() def update_axes_position(self): """ Set axes position so that labels are always visible - it deliberately ignores height of ylabel (and less importantly the length of xlabel). This is because the plot window typically has a very small height when docked in the UI. """ ax = self.get_axes()[0] y0_lab = ax.xaxis.get_tightbbox( renderer=self.figure.canvas.get_renderer() ).transformed( self.figure.transFigure.inverted() ).y0 # vertical coord of bottom left corner of xlabel in fig ref. frame x0_lab = ax.yaxis.get_tightbbox( renderer=self.figure.canvas.get_renderer() ).transformed( self.figure.transFigure.inverted() ).x0 # horizontal coord of bottom left corner ylabel in fig ref. frame pos = ax.get_position() x0_ax = pos.x0 + 0.05 - x0_lab # move so that ylabel left bottom corner at horizontal coord 0.05 y0_ax = pos.y0 + 0.05 - y0_lab # move so that xlabel left bottom corner at vertical coord 0.05 ax.set_position([x0_ax, y0_ax, 0.95 - x0_ax, 0.95 - y0_ax]) 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 try: self.fit_browser.removeWorkspaceAndSpectra(ws.name()) except: pass # name may not be available if ws has just been deleted 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
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 _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)