refactor(toolbar): generalizations of the ToolBarAction
BIN
bec_widgets/assets/designer_icons/motor_map.png
Normal file
After Width: | Height: | Size: 7.1 KiB |
Before Width: | Height: | Size: 341 B After Width: | Height: | Size: 341 B |
Before Width: | Height: | Size: 392 B After Width: | Height: | Size: 392 B |
@ -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:
|
||||
|
Before Width: | Height: | Size: 9.5 KiB |
@ -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 |
@ -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):
|
||||
|
@ -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)
|
@ -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,
|
||||
)
|
||||
|
@ -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)
|
@ -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,
|
||||
)
|
||||
|