0
0
mirror of https://github.com/bec-project/bec_widgets.git synced 2025-07-14 03:31:50 +02:00

fix(plot_base): ability to choose between popup or side panel gui mode

This commit is contained in:
2025-02-19 17:30:49 +01:00
committed by wyzula_j
parent f54e69f1cf
commit 3aa2f2225f
4 changed files with 363 additions and 186 deletions

View File

@ -1,6 +1,6 @@
from qtpy.QtWidgets import QDialog, QDialogButtonBox, QHBoxLayout, QPushButton, QVBoxLayout, QWidget from qtpy.QtWidgets import QDialog, QDialogButtonBox, QHBoxLayout, QPushButton, QVBoxLayout, QWidget
from bec_widgets.qt_utils.error_popups import SafeSlot as Slot from bec_widgets.qt_utils.error_popups import SafeSlot
class SettingWidget(QWidget): class SettingWidget(QWidget):
@ -20,14 +20,14 @@ class SettingWidget(QWidget):
def set_target_widget(self, target_widget: QWidget): def set_target_widget(self, target_widget: QWidget):
self.target_widget = target_widget self.target_widget = target_widget
@Slot() @SafeSlot()
def accept_changes(self): def accept_changes(self):
""" """
Accepts the changes made in the settings widget and applies them to the target widget. Accepts the changes made in the settings widget and applies them to the target widget.
""" """
pass pass
@Slot(dict) @SafeSlot(dict)
def display_current_settings(self, config_dict: dict): def display_current_settings(self, config_dict: dict):
""" """
Displays the current settings of the target widget in the settings widget. Displays the current settings of the target widget in the settings widget.
@ -54,12 +54,13 @@ class SettingsDialog(QDialog):
settings_widget: SettingWidget = None, settings_widget: SettingWidget = None,
window_title: str = "Settings", window_title: str = "Settings",
config: dict = None, config: dict = None,
modal: bool = False,
*args, *args,
**kwargs, **kwargs,
): ):
super().__init__(parent, *args, **kwargs) super().__init__(parent, *args, **kwargs)
self.setModal(False) self.setModal(modal)
self.setWindowTitle(window_title) self.setWindowTitle(window_title)
@ -92,7 +93,7 @@ class SettingsDialog(QDialog):
ok_button.setDefault(True) ok_button.setDefault(True)
ok_button.setAutoDefault(True) ok_button.setAutoDefault(True)
@Slot() @SafeSlot()
def accept(self): def accept(self):
""" """
Accept the changes made in the settings widget and close the dialog. Accept the changes made in the settings widget and close the dialog.
@ -100,7 +101,7 @@ class SettingsDialog(QDialog):
self.widget.accept_changes() self.widget.accept_changes()
super().accept() super().accept()
@Slot() @SafeSlot()
def apply_changes(self): def apply_changes(self):
""" """
Apply the changes made in the settings widget without closing the dialog. Apply the changes made in the settings widget without closing the dialog.

View File

@ -1,14 +1,18 @@
from __future__ import annotations from __future__ import annotations
from enum import Enum
import numpy as np
import pyqtgraph as pg import pyqtgraph as pg
from bec_lib import bec_logger from bec_lib import bec_logger
from qtpy.QtCore import QPoint, QPointF, Qt, Signal from qtpy.QtCore import QPoint, QPointF, Qt, Signal
from qtpy.QtWidgets import QLabel, QVBoxLayout, QWidget from qtpy.QtWidgets import QHBoxLayout, QLabel, QMainWindow, QVBoxLayout, QWidget
from bec_widgets.qt_utils.error_popups import SafeProperty, SafeSlot from bec_widgets.qt_utils.error_popups import SafeProperty, SafeSlot
from bec_widgets.qt_utils.round_frame import RoundedFrame from bec_widgets.qt_utils.round_frame import RoundedFrame
from bec_widgets.qt_utils.settings_dialog import SettingsDialog
from bec_widgets.qt_utils.side_panel import SidePanel from bec_widgets.qt_utils.side_panel import SidePanel
from bec_widgets.qt_utils.toolbar import MaterialIconAction, ModularToolBar, SeparatorAction from bec_widgets.qt_utils.toolbar import MaterialIconAction, ModularToolBar, ToolbarBundle
from bec_widgets.utils import ConnectionConfig, Crosshair, EntryValidator from bec_widgets.utils import ConnectionConfig, Crosshair, EntryValidator
from bec_widgets.utils.bec_widget import BECWidget from bec_widgets.utils.bec_widget import BECWidget
from bec_widgets.utils.fps_counter import FPSCounter from bec_widgets.utils.fps_counter import FPSCounter
@ -20,7 +24,6 @@ from bec_widgets.widgets.plots_next_gen.toolbar_bundles.mouse_interactions impor
) )
from bec_widgets.widgets.plots_next_gen.toolbar_bundles.plot_export import PlotExportBundle from bec_widgets.widgets.plots_next_gen.toolbar_bundles.plot_export import PlotExportBundle
from bec_widgets.widgets.plots_next_gen.toolbar_bundles.roi_bundle import ROIBundle from bec_widgets.widgets.plots_next_gen.toolbar_bundles.roi_bundle import ROIBundle
from bec_widgets.widgets.utility.visual.dark_mode_button.dark_mode_button import DarkModeButton
logger = bec_logger.logger logger = bec_logger.logger
@ -42,6 +45,12 @@ class BECViewBox(pg.ViewBox):
self.update() self.update()
class UIMode(Enum):
NONE = 0
POPUP = 1
SIDE = 2
class PlotBase(BECWidget, QWidget): class PlotBase(BECWidget, QWidget):
PLUGIN = False PLUGIN = False
RPC = False RPC = False
@ -59,6 +68,7 @@ class PlotBase(BECWidget, QWidget):
config: ConnectionConfig | None = None, config: ConnectionConfig | None = None,
client=None, client=None,
gui_id: str | None = None, gui_id: str | None = None,
popups: bool = False,
) -> None: ) -> None:
if config is None: if config is None:
config = ConnectionConfig(widget_class=self.__class__.__name__) config = ConnectionConfig(widget_class=self.__class__.__name__)
@ -74,6 +84,8 @@ class PlotBase(BECWidget, QWidget):
self.layout.setContentsMargins(0, 0, 0, 0) self.layout.setContentsMargins(0, 0, 0, 0)
self.layout.setSpacing(0) self.layout.setSpacing(0)
self.layout_manager = LayoutManagerWidget(parent=self) self.layout_manager = LayoutManagerWidget(parent=self)
self.layout_manager.layout.setContentsMargins(0, 0, 0, 0)
self.layout_manager.layout.setSpacing(0)
# Property Manager # Property Manager
self.state_manager = WidgetStateManager(self) self.state_manager = WidgetStateManager(self)
@ -82,12 +94,14 @@ class PlotBase(BECWidget, QWidget):
self.entry_validator = EntryValidator(self.dev) self.entry_validator = EntryValidator(self.dev)
# Base widgets elements # Base widgets elements
self._ui_mode = UIMode.POPUP if popups else UIMode.SIDE
self.axis_settings_dialog = None
self.plot_widget = pg.GraphicsLayoutWidget(parent=self) self.plot_widget = pg.GraphicsLayoutWidget(parent=self)
self.plot_item = pg.PlotItem(viewBox=BECViewBox(enableMenu=True)) self.plot_item = pg.PlotItem(viewBox=BECViewBox(enableMenu=True))
self.plot_widget.addItem(self.plot_item) self.plot_widget.addItem(self.plot_item)
self.side_panel = SidePanel(self, orientation="left", panel_max_width=280) self.side_panel = SidePanel(self, orientation="left", panel_max_width=280)
self.toolbar = ModularToolBar(target_widget=self, orientation="horizontal") self.toolbar = ModularToolBar(target_widget=self, orientation="horizontal")
self.init_toolbar() self._init_toolbar()
# PlotItem Addons # PlotItem Addons
self.plot_item.addLegend() self.plot_item.addLegend()
@ -115,13 +129,14 @@ class PlotBase(BECWidget, QWidget):
self.layout_manager.add_widget_relative(self.side_panel, self.round_plot_widget, "left") self.layout_manager.add_widget_relative(self.side_panel, self.round_plot_widget, "left")
self.layout_manager.add_widget_relative(self.toolbar, self.fps_label, "top") self.layout_manager.add_widget_relative(self.toolbar, self.fps_label, "top")
self.add_side_menus() self.ui_mode = self._ui_mode # to initiate the first time
# PlotItem ViewBox Signals # PlotItem ViewBox Signals
self.plot_item.vb.sigStateChanged.connect(self.viewbox_state_changed) self.plot_item.vb.sigStateChanged.connect(self.viewbox_state_changed)
def init_toolbar(self): def _init_toolbar(self):
self.popup_bundle = None
self.performance_bundle = ToolbarBundle("performance")
self.plot_export_bundle = PlotExportBundle("plot_export", target_widget=self) self.plot_export_bundle = PlotExportBundle("plot_export", target_widget=self)
self.mouse_bundle = MouseInteractionToolbarBundle("mouse_interaction", target_widget=self) self.mouse_bundle = MouseInteractionToolbarBundle("mouse_interaction", target_widget=self)
# self.state_export_bundle = SaveStateBundle("state_export", target_widget=self) #TODO ATM disabled, cannot be used in DockArea, which is exposed to the user # self.state_export_bundle = SaveStateBundle("state_export", target_widget=self) #TODO ATM disabled, cannot be used in DockArea, which is exposed to the user
@ -133,33 +148,130 @@ class PlotBase(BECWidget, QWidget):
self.toolbar.add_bundle(self.mouse_bundle, target_widget=self) self.toolbar.add_bundle(self.mouse_bundle, target_widget=self)
self.toolbar.add_bundle(self.roi_bundle, target_widget=self) self.toolbar.add_bundle(self.roi_bundle, target_widget=self)
self.toolbar.add_action("separator_1", SeparatorAction(), target_widget=self) self.performance_bundle.add_action(
self.toolbar.add_action(
"fps_monitor", "fps_monitor",
MaterialIconAction(icon_name="speed", tooltip="Show FPS Monitor", checkable=True), MaterialIconAction(
target_widget=self, icon_name="speed", tooltip="Show FPS Monitor", checkable=True, parent=self
),
) )
self.toolbar.addWidget(DarkModeButton(toolbar=True)) self.toolbar.add_bundle(self.performance_bundle, target_widget=self)
self.toolbar.widgets["fps_monitor"].action.toggled.connect( self.toolbar.widgets["fps_monitor"].action.toggled.connect(
lambda checked: setattr(self, "enable_fps_monitor", checked) lambda checked: setattr(self, "enable_fps_monitor", checked)
) )
# hide some options by default
self.toolbar.toggle_action_visibility("fps_monitor", False)
def add_side_menus(self): def add_side_menus(self):
"""Adds multiple menus to the side panel.""" """Adds multiple menus to the side panel."""
# Setting Axis Widget # Setting Axis Widget
axis_setting = AxisSettings(target_widget=self) try:
self.side_panel.add_menu( axis_setting = AxisSettings(target_widget=self)
action_id="axis", self.side_panel.add_menu(
icon_name="settings", action_id="axis",
tooltip="Show Axis Settings", icon_name="settings",
widget=axis_setting, tooltip="Show Axis Settings",
title="Axis Settings", widget=axis_setting,
title="Axis Settings",
)
except ValueError:
return
def add_popups(self):
"""
Add popups to the toolbar.
"""
self.popup_bundle = ToolbarBundle("popup_bundle")
settings = MaterialIconAction(
icon_name="settings", tooltip="Show Axis Settings", checkable=True, parent=self
) )
self.popup_bundle.add_action("axis", settings)
self.toolbar.add_bundle(self.popup_bundle, target_widget=self)
self.toolbar.widgets["axis"].action.triggered.connect(self.show_axis_settings_popup)
def show_axis_settings_popup(self):
"""
Show the axis settings dialog.
"""
settings_action = self.toolbar.widgets["axis"].action
if self.axis_settings_dialog is None or not self.axis_settings_dialog.isVisible():
axis_setting = AxisSettings(target_widget=self, popup=True)
self.axis_settings_dialog = SettingsDialog(
self, settings_widget=axis_setting, window_title="Axis Settings", modal=False
)
# When the dialog is closed, update the toolbar icon and clear the reference
self.axis_settings_dialog.finished.connect(self._axis_settings_closed)
self.axis_settings_dialog.show()
settings_action.setChecked(True)
else:
# If already open, bring it to the front
self.axis_settings_dialog.raise_()
self.axis_settings_dialog.activateWindow()
settings_action.setChecked(True) # keep it toggled
def _axis_settings_closed(self):
"""
Slot for when the axis settings dialog is closed.
"""
self.axis_settings_dialog = None
self.toolbar.widgets["axis"].action.setChecked(False)
################################################################################ ################################################################################
# Toggle UI Elements # Toggle UI Elements
################################################################################ ################################################################################
@property
def ui_mode(self) -> UIMode:
return self._ui_mode
@ui_mode.setter
def ui_mode(self, mode: UIMode):
if not isinstance(mode, UIMode):
raise ValueError("ui_mode must be an instance of UIMode")
self._ui_mode = mode
# First, clear both UI elements:
if self.popup_bundle is not None:
for action_id in self.toolbar.bundles["popup_bundle"]:
self.toolbar.widgets[action_id].action.setVisible(False)
if self.axis_settings_dialog is not None and self.axis_settings_dialog.isVisible():
self.axis_settings_dialog.close()
self.side_panel.hide()
# Now, apply the new mode:
if mode == UIMode.POPUP:
if self.popup_bundle is None:
self.add_popups()
else:
for action_id in self.toolbar.bundles["popup_bundle"]:
self.toolbar.widgets[action_id].action.setVisible(True)
elif mode == UIMode.SIDE:
self.add_side_menus()
self.side_panel.show()
@SafeProperty(bool, doc="Enable popups setting dialogs for the plot widget.")
def enable_popups(self):
return self.ui_mode == UIMode.POPUP
@enable_popups.setter
def enable_popups(self, value: bool):
if value:
self.ui_mode = UIMode.POPUP
else:
if self.ui_mode == UIMode.POPUP:
self.ui_mode = UIMode.NONE
@SafeProperty(bool, doc="Show Side Panel")
def enable_side_panel(self) -> bool:
return self.ui_mode == UIMode.SIDE
@enable_side_panel.setter
def enable_side_panel(self, value: bool):
if value:
self.ui_mode = UIMode.SIDE
else:
if self.ui_mode == UIMode.SIDE:
self.ui_mode = UIMode.NONE
@SafeProperty(bool, doc="Show Toolbar") @SafeProperty(bool, doc="Show Toolbar")
def enable_toolbar(self) -> bool: def enable_toolbar(self) -> bool:
@ -167,15 +279,22 @@ class PlotBase(BECWidget, QWidget):
@enable_toolbar.setter @enable_toolbar.setter
def enable_toolbar(self, value: bool): def enable_toolbar(self, value: bool):
self.toolbar.setVisible(value) if value:
# Disable popup mode
@SafeProperty(bool, doc="Show Side Panel") if self._popups:
def enable_side_panel(self) -> bool: # Directly update the internal flag to avoid recursion
return self.side_panel.isVisible() self._popups = False
# Hide the popup bundle if it exists and close any open dialogs
@enable_side_panel.setter if self.popup_bundle is not None:
def enable_side_panel(self, value: bool): for action in self.toolbar.bundles["popup_bundle"].actions:
self.side_panel.setVisible(value) action.setVisible(False)
if self.axis_settings_dialog is not None and self.axis_settings_dialog.isVisible():
self.axis_settings_dialog.close()
self.side_panel.show()
# Add side menus if not already added
self.add_side_menus()
else:
self.side_panel.hide()
@SafeProperty(bool, doc="Enable the FPS monitor.") @SafeProperty(bool, doc="Enable the FPS monitor.")
def enable_fps_monitor(self) -> bool: def enable_fps_monitor(self) -> bool:
@ -591,16 +710,34 @@ class PlotBase(BECWidget, QWidget):
item.ctrlMenu.deleteLater() item.ctrlMenu.deleteLater()
class DemoPlotBase(QMainWindow): # pragma: no cover:
def __init__(self):
super().__init__()
self.main_widget = QWidget()
self.setCentralWidget(self.main_widget)
self.main_widget.layout = QHBoxLayout(self.main_widget)
self.plot_popup = PlotBase(popups=True)
self.plot_popup.title = "PlotBase with popups"
self.plot_side_panels = PlotBase(popups=False)
self.plot_side_panels.title = "PlotBase with side panels"
self.plot_popup.plot_item.plot(np.random.rand(100), pen=(255, 0, 0))
self.plot_side_panels.plot_item.plot(np.random.rand(100), pen=(0, 255, 0))
self.main_widget.layout.addWidget(self.plot_side_panels)
self.main_widget.layout.addWidget(self.plot_popup)
self.resize(1400, 600)
if __name__ == "__main__": # pragma: no cover: if __name__ == "__main__": # pragma: no cover:
import sys import sys
from qtpy.QtWidgets import QApplication from qtpy.QtWidgets import QApplication
app = QApplication(sys.argv) app = QApplication(sys.argv)
widget = PlotBase() window = DemoPlotBase()
widget.show() window.show()
# Just some example data and parameters to test
widget.y_grid = True
widget.plot_item.plot([1, 2, 3, 4, 5], [1, 2, 3, 4, 5])
sys.exit(app.exec_()) sys.exit(app.exec_())

View File

@ -9,7 +9,7 @@ from bec_widgets.utils.widget_io import WidgetIO
class AxisSettings(SettingWidget): class AxisSettings(SettingWidget):
def __init__(self, parent=None, target_widget=None, *args, **kwargs): def __init__(self, parent=None, target_widget=None, popup=False, *args, **kwargs):
super().__init__(parent=parent, *args, **kwargs) super().__init__(parent=parent, *args, **kwargs)
# This is a settings widget that depends on the target widget # This is a settings widget that depends on the target widget
@ -18,9 +18,15 @@ class AxisSettings(SettingWidget):
self.setProperty("skip_settings", True) self.setProperty("skip_settings", True)
self.setObjectName("AxisSettings") self.setObjectName("AxisSettings")
current_path = os.path.dirname(__file__) current_path = os.path.dirname(__file__)
form = UILoader().load_ui(os.path.join(current_path, "axis_settings_vertical.ui"), self) if popup:
form = UILoader().load_ui(
os.path.join(current_path, "axis_settings_horizontal.ui"), self
)
else:
form = UILoader().load_ui(os.path.join(current_path, "axis_settings_vertical.ui"), self)
self.target_widget = target_widget self.target_widget = target_widget
self.popup = popup
# # Scroll area # # Scroll area
self.scroll_area = QScrollArea(self) self.scroll_area = QScrollArea(self)
@ -34,10 +40,13 @@ class AxisSettings(SettingWidget):
# self.layout.addWidget(self.ui) # self.layout.addWidget(self.ui)
self.ui = form self.ui = form
self.connect_all_signals() if self.target_widget is not None and self.popup is False:
if self.target_widget is not None: self.connect_all_signals()
self.target_widget.property_changed.connect(self.update_property) self.target_widget.property_changed.connect(self.update_property)
if self.popup is True:
self.fetch_all_properties()
def connect_all_signals(self): def connect_all_signals(self):
for widget in [ for widget in [
self.ui.title, self.ui.title,
@ -93,3 +102,49 @@ class AxisSettings(SettingWidget):
was_blocked = widget_to_set.blockSignals(True) was_blocked = widget_to_set.blockSignals(True)
WidgetIO.set_value(widget_to_set, value) WidgetIO.set_value(widget_to_set, value)
widget_to_set.blockSignals(was_blocked) widget_to_set.blockSignals(was_blocked)
def fetch_all_properties(self):
"""
Fetch all properties from the target widget and update the settings widget.
"""
for widget in [
self.ui.title,
self.ui.inner_axes,
self.ui.outer_axes,
self.ui.x_label,
self.ui.x_min,
self.ui.x_max,
self.ui.x_log,
self.ui.x_grid,
self.ui.y_label,
self.ui.y_min,
self.ui.y_max,
self.ui.y_log,
self.ui.y_grid,
]:
property_name = widget.objectName()
value = getattr(self.target_widget, property_name)
WidgetIO.set_value(widget, value)
def accept_changes(self):
"""
Apply all properties from the settings widget to the target widget.
"""
for widget in [
self.ui.title,
self.ui.inner_axes,
self.ui.outer_axes,
self.ui.x_label,
self.ui.x_min,
self.ui.x_max,
self.ui.x_log,
self.ui.x_grid,
self.ui.y_label,
self.ui.y_min,
self.ui.y_max,
self.ui.y_log,
self.ui.y_grid,
]:
property_name = widget.objectName()
value = WidgetIO.get_value(widget)
setattr(self.target_widget, property_name, value)

View File

@ -6,67 +6,131 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>427</width> <width>486</width>
<height>270</height> <height>300</height>
</rect> </rect>
</property> </property>
<property name="minimumSize">
<size>
<width>0</width>
<height>250</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>278</height>
</size>
</property>
<property name="windowTitle"> <property name="windowTitle">
<string>Form</string> <string>Form</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="plot_title_label">
<property name="text">
<string>Plot Title</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="plot_title"/>
</item>
</layout>
</item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Inner Axes</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="ToggleSwitch" name="inner_axes"/>
</item>
<item row="1" column="2">
<widget class="QLabel" name="label_outer_axes"> <widget class="QLabel" name="label_outer_axes">
<property name="text"> <property name="text">
<string>Outer Axes</string> <string>Outer Axes</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="1" column="3">
<widget class="ToggleSwitch" name="outer_axes">
<property name="checked" stdset="0">
<bool>false</bool>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QGroupBox" name="x_axis_box">
<property name="title">
<string>X Axis</string>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<item row="5" column="0">
<widget class="QLabel" name="x_grid_label">
<property name="text">
<string>Grid</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="ToggleSwitch" name="x_log">
<property name="checked" stdset="0">
<bool>false</bool>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QDoubleSpinBox" name="x_max">
<property name="alignment">
<set>Qt::AlignmentFlag::AlignCenter</set>
</property>
<property name="minimum">
<double>-9999.000000000000000</double>
</property>
<property name="maximum">
<double>9999.000000000000000</double>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="x_max_label">
<property name="text">
<string>Max</string>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="ToggleSwitch" name="x_grid">
<property name="checked" stdset="0">
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QDoubleSpinBox" name="x_min">
<property name="alignment">
<set>Qt::AlignmentFlag::AlignCenter</set>
</property>
<property name="minimum">
<double>-9999.000000000000000</double>
</property>
<property name="maximum">
<double>9999.000000000000000</double>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="x_scale_label">
<property name="text">
<string>Log</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QLabel" name="x_min_label">
<property name="text">
<string>Min</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="x_label_label">
<property name="text">
<string>Label</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLineEdit" name="x_label"/>
</item>
</layout>
</widget>
</item>
<item row="2" column="2" colspan="2">
<widget class="QGroupBox" name="y_axis_box"> <widget class="QGroupBox" name="y_axis_box">
<property name="title"> <property name="title">
<string>Y Axis</string> <string>Y Axis</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout_5"> <layout class="QGridLayout" name="gridLayout_5">
<item row="3" column="2">
<widget class="QComboBox" name="y_scale">
<item>
<property name="text">
<string>linear</string>
</property>
</item>
<item>
<property name="text">
<string>log</string>
</property>
</item>
</widget>
</item>
<item row="2" column="2"> <item row="2" column="2">
<widget class="QDoubleSpinBox" name="y_max"> <widget class="QDoubleSpinBox" name="y_max">
<property name="alignment"> <property name="alignment">
@ -106,7 +170,7 @@
<item row="3" column="0"> <item row="3" column="0">
<widget class="QLabel" name="y_scale_label"> <widget class="QLabel" name="y_scale_label">
<property name="text"> <property name="text">
<string>Scale</string> <string>Log</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -124,13 +188,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="2">
<widget class="QCheckBox" name="y_grid">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="4" column="0"> <item row="4" column="0">
<widget class="QLabel" name="y_grid_label"> <widget class="QLabel" name="y_grid_label">
<property name="text"> <property name="text">
@ -138,109 +195,36 @@
</property> </property>
</widget> </widget>
</item> </item>
</layout>
</widget>
</item>
<item row="2" column="0">
<widget class="QGroupBox" name="x_axis_box">
<property name="title">
<string>X Axis</string>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<item row="3" column="0">
<widget class="QLabel" name="x_scale_label">
<property name="text">
<string>Scale</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QDoubleSpinBox" name="x_min">
<property name="alignment">
<set>Qt::AlignmentFlag::AlignCenter</set>
</property>
<property name="minimum">
<double>-9999.000000000000000</double>
</property>
<property name="maximum">
<double>9999.000000000000000</double>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QLabel" name="x_min_label">
<property name="text">
<string>Min</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QDoubleSpinBox" name="x_max">
<property name="alignment">
<set>Qt::AlignmentFlag::AlignCenter</set>
</property>
<property name="minimum">
<double>-9999.000000000000000</double>
</property>
<property name="maximum">
<double>9999.000000000000000</double>
</property>
</widget>
</item>
<item row="3" column="2"> <item row="3" column="2">
<widget class="QComboBox" name="x_scale"> <widget class="ToggleSwitch" name="y_log">
<item> <property name="checked" stdset="0">
<property name="text"> <bool>false</bool>
<string>linear</string>
</property>
</item>
<item>
<property name="text">
<string>log</string>
</property>
</item>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="x_max_label">
<property name="text">
<string>Max</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLineEdit" name="x_label"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="x_label_label">
<property name="text">
<string>Label</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="2"> <item row="4" column="2">
<widget class="QCheckBox" name="x_grid"> <widget class="ToggleSwitch" name="y_grid">
<property name="text"> <property name="checked" stdset="0">
<string/> <bool>false</bool>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="x_grid_label">
<property name="text">
<string>Grid</string>
</property> </property>
</widget> </widget>
</item> </item>
</layout> </layout>
</widget> </widget>
</item> </item>
<item row="1" column="1"> <item row="0" column="0" colspan="4">
<widget class="ToggleSwitch" name="switch_outer_axes"> <layout class="QHBoxLayout" name="horizontalLayout">
<property name="checked" stdset="0"> <item>
<bool>false</bool> <widget class="QLabel" name="plot_title_label">
</property> <property name="text">
</widget> <string>Plot Title</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="title"/>
</item>
</layout>
</item> </item>
</layout> </layout>
</widget> </widget>