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

refactor(toolbar): generalizations of the ToolBarAction

This commit is contained in:
2024-07-19 18:12:28 +02:00
parent a3dff7decc
commit ad112d1f08
18 changed files with 112 additions and 212 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

View File

Before

Width:  |  Height:  |  Size: 341 B

After

Width:  |  Height:  |  Size: 341 B

View File

Before

Width:  |  Height:  |  Size: 392 B

After

Width:  |  Height:  |  Size: 392 B

View File

@ -1,12 +1,35 @@
# pylint: disable=no-name-in-module
import os
from abc import ABC, abstractmethod
from collections import defaultdict
# pylint: disable=no-name-in-module
from qtpy.QtCore import QSize
from qtpy.QtWidgets import QToolBar, QToolButton, QWidget
from qtpy.QtGui import QAction, QIcon
from qtpy.QtWidgets import QHBoxLayout, QLabel, QToolBar, QToolButton, QWidget
import bec_widgets
MODULE_PATH = os.path.dirname(bec_widgets.__file__)
class ToolBarAction(ABC):
"""
Abstract base class for toolbar actions.
Args:
icon_path (str, optional): The name of the icon file from `assets/toolbar_icons`. Defaults to None.
tooltip (bool, optional): The tooltip for the action. Defaults to None.
checkable (bool, optional): Whether the action is checkable. Defaults to False.
"""
def __init__(self, icon_path: str = None, tooltip: str = None, checkable: bool = False):
self.icon_path = (
os.path.join(MODULE_PATH, "assets", "toolbar_icons", icon_path) if icon_path else None
)
self.tooltip = tooltip
self.checkable = checkable
self.action = None
@abstractmethod
def add_to_toolbar(self, toolbar: QToolBar, target: QWidget):
"""Adds an action or widget to a toolbar.
@ -26,6 +49,55 @@ class SeparatorAction(ToolBarAction):
toolbar.addWidget(self.separator)
class IconAction(ToolBarAction):
"""
Action with an icon for the toolbar.
Args:
icon_path (str): The path to the icon file.
tooltip (str): The tooltip for the action.
checkable (bool, optional): Whether the action is checkable. Defaults to False.
"""
def __init__(self, icon_path: str = None, tooltip: str = None, checkable: bool = False):
super().__init__(icon_path, tooltip, checkable)
def add_to_toolbar(self, toolbar: QToolBar, target: QWidget):
icon = QIcon()
icon.addFile(self.icon_path, size=QSize(20, 20))
self.action = QAction(icon, self.tooltip, target)
self.action.setCheckable(self.checkable)
toolbar.addAction(self.action)
class DeviceSelectionAction(ToolBarAction):
"""
Action for selecting a device in a combobox.
Args:
label (str): The label for the combobox.
device_combobox (DeviceComboBox): The combobox for selecting the device.
"""
def __init__(self, label: str, device_combobox):
super().__init__()
self.label = label
self.device_combobox = device_combobox
self.device_combobox.currentIndexChanged.connect(lambda: self.set_combobox_style("#ffa700"))
def add_to_toolbar(self, toolbar, target):
widget = QWidget()
layout = QHBoxLayout(widget)
label = QLabel(f"{self.label}")
layout.addWidget(label)
layout.addWidget(self.device_combobox)
toolbar.addWidget(widget)
def set_combobox_style(self, color: str):
self.device_combobox.setStyleSheet(f"QComboBox {{ background-color: {color}; }}")
class ModularToolBar(QToolBar):
"""Modular toolbar with optional automatic initialization.
Args:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

View File

@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48px" viewBox="0 0 24 24" width="48px" fill="#FFFFFF">
<path d="M0 0h24v24H0V0z" fill="none"/>
<path d="M19.43 12.98c.04-.32.07-.64.07-.98 0-.34-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.09-.16-.26-.25-.44-.25-.06 0-.12.01-.17.03l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.06-.02-.12-.03-.18-.03-.17 0-.34.09-.43.25l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98 0 .33.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.09.16.26.25.44.25.06 0 .12-.01.17-.03l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.06.02.12.03.18.03.17 0 .34-.09.43-.25l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zm-1.98-1.71c.04.31.05.52.05.73 0 .21-.02.43-.05.73l-.14 1.13.89.7 1.08.84-.7 1.21-1.27-.51-1.04-.42-.9.68c-.43.32-.84.56-1.25.73l-1.06.43-.16 1.13-.2 1.35h-1.4l-.19-1.35-.16-1.13-1.06-.43c-.43-.18-.83-.41-1.23-.71l-.91-.7-1.06.43-1.27.51-.7-1.21 1.08-.84.89-.7-.14-1.13c-.03-.31-.05-.54-.05-.74s.02-.43.05-.73l.14-1.13-.89-.7-1.08-.84.7-1.21 1.27.51 1.04.42.9-.68c.43-.32.84-.56 1.25-.73l1.06-.43.16-1.13.2-1.35h1.39l.19 1.35.16 1.13 1.06.43c.43.18.83.41 1.23.71l.91.7 1.06-.43 1.27-.51.7 1.21-1.07.85-.89.7.14 1.13zM12 8c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 6c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -3,6 +3,7 @@ import os
from qtpy.QtDesigner import QDesignerCustomWidgetInterface
from qtpy.QtGui import QIcon
import bec_widgets
from bec_widgets.widgets.motor_map.motor_map_widget import BECMotorMapWidget
DOM_XML = """
@ -12,6 +13,8 @@ DOM_XML = """
</ui>
"""
MODULE_PATH = os.path.dirname(bec_widgets.__file__)
class BECMotorMapWidgetPlugin(QDesignerCustomWidgetInterface): # pragma: no cover
def __init__(self):
@ -29,8 +32,7 @@ class BECMotorMapWidgetPlugin(QDesignerCustomWidgetInterface): # pragma: no cov
return "BEC Plots"
def icon(self):
current_path = os.path.dirname(__file__)
icon_path = os.path.join(current_path, "assets", "motor_map.png")
icon_path = os.path.join(MODULE_PATH, "assets", "designer_icons", "motor_map.png")
return QIcon(icon_path)
def includeFile(self):

View File

@ -1,59 +0,0 @@
import os
from qtpy.QtCore import QSize
from qtpy.QtGui import QAction, QIcon
from qtpy.QtWidgets import QHBoxLayout, QLabel, QWidget
from bec_widgets.qt_utils.toolbar import ToolBarAction
from bec_widgets.widgets.device_combobox.device_combobox import DeviceComboBox
class DeviceSelectionAction(ToolBarAction):
def __init__(self, label: str):
self.label = label
self.device_combobox = DeviceComboBox(device_filter="Positioner")
self.device_combobox.currentIndexChanged.connect(lambda: self.set_combobox_style("#ffa700"))
def add_to_toolbar(self, toolbar, target):
widget = QWidget()
layout = QHBoxLayout(widget)
label = QLabel(f"{self.label}")
layout.addWidget(label)
layout.addWidget(self.device_combobox)
toolbar.addWidget(widget)
def set_combobox_style(self, color: str):
self.device_combobox.setStyleSheet(f"QComboBox {{ background-color: {color}; }}")
class ConnectAction(ToolBarAction):
def add_to_toolbar(self, toolbar, target):
current_path = os.path.dirname(__file__)
parent_path = os.path.dirname(current_path)
icon = QIcon()
icon.addFile(os.path.join(parent_path, "assets", "connection.svg"), size=QSize(20, 20))
self.action = QAction(icon, "Connect Motors", target)
toolbar.addAction(self.action)
class ResetHistoryAction(ToolBarAction):
def add_to_toolbar(self, toolbar, target):
current_path = os.path.dirname(__file__)
parent_path = os.path.dirname(current_path)
icon = QIcon()
icon.addFile(os.path.join(parent_path, "assets", "history.svg"), size=QSize(20, 20))
self.action = QAction(icon, "Reset Trace History", target)
toolbar.addAction(self.action)
class SettingsAction(ToolBarAction):
def add_to_toolbar(self, toolbar, target):
current_path = os.path.dirname(__file__)
parent_path = os.path.dirname(current_path)
icon = QIcon()
icon.addFile(os.path.join(parent_path, "assets", "settings.svg"), size=QSize(20, 20))
self.action = QAction(icon, "Open Configuration Dialog", target)
toolbar.addAction(self.action)

View File

@ -5,17 +5,12 @@ import sys
from qtpy.QtWidgets import QVBoxLayout, QWidget
from bec_widgets.qt_utils.settings_dialog import SettingsDialog
from bec_widgets.qt_utils.toolbar import ModularToolBar
from bec_widgets.qt_utils.toolbar import DeviceSelectionAction, IconAction, ModularToolBar
from bec_widgets.utils.bec_widget import BECWidget
from bec_widgets.widgets.device_combobox.device_combobox import DeviceComboBox
from bec_widgets.widgets.figure import BECFigure
from bec_widgets.widgets.figure.plots.motor_map.motor_map import MotorMapConfig
from bec_widgets.widgets.motor_map.motor_map_dialog.motor_map_settings import MotorMapSettings
from bec_widgets.widgets.motor_map.motor_map_dialog.motor_map_toolbar import (
ConnectAction,
DeviceSelectionAction,
ResetHistoryAction,
SettingsAction,
)
class BECMotorMapWidget(BECWidget, QWidget):
@ -53,11 +48,15 @@ class BECMotorMapWidget(BECWidget, QWidget):
self.fig = BECFigure()
self.toolbar = ModularToolBar(
actions={
"motor_x": DeviceSelectionAction("Motor X:"),
"motor_y": DeviceSelectionAction("Motor Y:"),
"connect": ConnectAction(),
"history": ResetHistoryAction(),
"config": SettingsAction(),
"motor_x": DeviceSelectionAction(
"Motor X:", DeviceComboBox(device_filter="Positioner")
),
"motor_y": DeviceSelectionAction(
"Motor Y:", DeviceComboBox(device_filter="Positioner")
),
"connect": IconAction(icon_path="connection.svg", tooltip="Connect Motors"),
"history": IconAction(icon_path="history.svg", tooltip="Reset Trace History"),
"config": IconAction(icon_path="settings.svg", tooltip="Open Configuration Dialog"),
},
target_widget=self,
)

View File

@ -1,117 +0,0 @@
import os
from qtpy.QtCore import QSize
from qtpy.QtGui import QAction, QIcon
import bec_widgets
from bec_widgets.qt_utils.toolbar import ToolBarAction
MODULE_PATH = os.path.dirname(bec_widgets.__file__)
class SaveAction(ToolBarAction):
def add_to_toolbar(self, toolbar, target):
icon = QIcon()
icon.addFile(
os.path.join(MODULE_PATH, "assets", "toolbar_icons", "save.svg"), size=QSize(20, 20)
)
self.action = QAction(icon, "Open Export Dialog", target)
toolbar.addAction(self.action)
class MatplotlibAction(ToolBarAction):
def add_to_toolbar(self, toolbar, target):
icon = QIcon()
icon.addFile(
os.path.join(MODULE_PATH, "assets", "toolbar_icons", "photo_library.svg"),
size=QSize(20, 20),
)
self.action = QAction(icon, "Open Matplotlib Plot", target)
toolbar.addAction(self.action)
class DragModeAction(ToolBarAction):
def add_to_toolbar(self, toolbar, target):
icon = QIcon()
icon.addFile(
os.path.join(MODULE_PATH, "assets", "toolbar_icons", "drag_pan_mode.svg"),
size=QSize(20, 20),
)
self.action = QAction(icon, "Drag Mouse Mode", target)
self.action.setCheckable(True)
toolbar.addAction(self.action)
class RectangeModeAction(ToolBarAction):
def add_to_toolbar(self, toolbar, target):
icon = QIcon()
icon.addFile(
os.path.join(MODULE_PATH, "assets", "toolbar_icons", "rectangle_mode.svg"),
size=QSize(20, 20),
)
self.action = QAction(icon, "Rectangle Zoom Mode", target)
self.action.setCheckable(True)
toolbar.addAction(self.action)
class AutoRangeAction(ToolBarAction):
def add_to_toolbar(self, toolbar, target):
icon = QIcon()
icon.addFile(
os.path.join(MODULE_PATH, "assets", "toolbar_icons", "auto_range.svg"),
size=QSize(20, 20),
)
self.action = QAction(icon, "Autorange Plot", target)
toolbar.addAction(self.action)
class CurveAction(ToolBarAction):
def add_to_toolbar(self, toolbar, target):
icon = QIcon()
icon.addFile(
os.path.join(MODULE_PATH, "assets", "toolbar_icons", "line_axis.svg"),
size=QSize(20, 20),
)
self.action = QAction(icon, "Open Curves Configuration", target)
toolbar.addAction(self.action)
class FitParamsAction(ToolBarAction):
def add_to_toolbar(self, toolbar, target):
icon = QIcon()
icon.addFile(
os.path.join(MODULE_PATH, "assets", "toolbar_icons", "fitting_parameters.svg"),
size=QSize(20, 20),
)
self.action = QAction(icon, "Open Fitting Parameters", target)
toolbar.addAction(self.action)
class SettingsAction(ToolBarAction):
def add_to_toolbar(self, toolbar, target):
icon = QIcon()
icon.addFile(
os.path.join(MODULE_PATH, "assets", "toolbar_icons", "settings.svg"), size=QSize(20, 20)
)
self.action = QAction(icon, "Open Configuration Dialog", target)
toolbar.addAction(self.action)
class ImportAction(ToolBarAction):
def add_to_toolbar(self, toolbar, target):
icon = QIcon()
icon.addFile(
os.path.join(MODULE_PATH, "assets", "toolbar_icons", "import.svg"), size=QSize(20, 20)
)
self.action = QAction(icon, "Import Configuration from YAML", target)
toolbar.addAction(self.action)
class ExportAction(ToolBarAction):
def add_to_toolbar(self, toolbar, target):
icon = QIcon()
icon.addFile(
os.path.join(MODULE_PATH, "assets", "toolbar_icons", "export.svg"), size=QSize(20, 20)
)
self.action = QAction(icon, "Export Current Configuration to YAML", target)
toolbar.addAction(self.action)

View File

@ -5,22 +5,20 @@ from typing import Literal
import numpy as np
import pyqtgraph as pg
from qtpy.QtCore import Slot
from qtpy.QtWidgets import QVBoxLayout, QWidget
from bec_widgets.qt_utils.error_popups import SafeSlot, WarningPopupUtility
from bec_widgets.qt_utils.settings_dialog import SettingsDialog
from bec_widgets.qt_utils.toolbar import ModularToolBar, SeparatorAction
from bec_widgets.qt_utils.toolbar import IconAction, ModularToolBar, SeparatorAction
from bec_widgets.utils.bec_widget import BECWidget
from bec_widgets.widgets.figure import BECFigure
from bec_widgets.widgets.figure.plots.axis_settings import AxisSettings
from bec_widgets.widgets.figure.plots.waveform.waveform import Waveform1DConfig
from bec_widgets.widgets.figure.plots.waveform.waveform_curve import BECCurve
from bec_widgets.widgets.waveform.waveform_toolbar.curve_dialog.curve_dialog import CurveSettings
from bec_widgets.widgets.waveform.waveform_toolbar.dap_summary_dialog.dap_summary_dialog import (
from bec_widgets.widgets.waveform.waveform_popups.curve_dialog.curve_dialog import CurveSettings
from bec_widgets.widgets.waveform.waveform_popups.dap_summary_dialog.dap_summary_dialog import (
FitSummaryWidget,
)
from bec_widgets.widgets.waveform.waveform_toolbar.waveform_toolbar import *
try:
import pandas as pd
@ -76,19 +74,28 @@ class BECWaveformWidget(BECWidget, QWidget):
self.fig = BECFigure()
self.toolbar = ModularToolBar(
actions={
"save": SaveAction(),
"matplotlib": MatplotlibAction(),
"save": IconAction(icon_path="save.svg", tooltip="Open Export Dialog"),
"matplotlib": IconAction(
icon_path="photo_library.svg", tooltip="Open Matplotlib Plot"
),
"separator_1": SeparatorAction(),
"drag_mode": DragModeAction(),
"rectangle_mode": RectangeModeAction(),
"auto_range": AutoRangeAction(),
"drag_mode": IconAction(
icon_path="drag_pan_mode.svg", tooltip="Drag Mouse Mode", checkable=True
),
"rectangle_mode": IconAction(
icon_path="rectangle_mode.svg", tooltip="Rectangle Zoom Mode", checkable=True
),
"auto_range": IconAction(icon_path="auto_range.svg", tooltip="Autorange Plot"),
"separator_2": SeparatorAction(),
"curves": CurveAction(),
"fit_params": FitParamsAction(),
"axis_settings": SettingsAction(),
# "separator_3": SeparatorAction(),
# "import": ImportAction(),
# "export": ExportAction(),
"curves": IconAction(
icon_path="line_axis.svg", tooltip="Open Curves Configuration"
),
"fit_params": IconAction(
icon_path="fitting_parameters.svg", tooltip="Open Fitting Parameters"
),
"axis_settings": IconAction(
icon_path="settings.svg", tooltip="Open Configuration Dialog"
),
},
target_widget=self,
)