From 0350833f36e0a7cadce4173f9b1d1fbfdf985375 Mon Sep 17 00:00:00 2001 From: appel_c Date: Tue, 8 Oct 2024 15:31:02 +0200 Subject: [PATCH] feat: add filter i/o utility class --- bec_widgets/cli/client.py | 56 +++ bec_widgets/test_utils/__init__.py | 0 bec_widgets/test_utils/client_mocks.py | 225 +++++++++++ bec_widgets/utils/filter_io.py | 156 +++++++ .../widgets/base_classes/device_input_base.py | 381 +++++++++++++++--- .../base_classes/device_signal_input_base.py | 277 +++++++++++++ .../dap_combo_box/dap_combo_box_plugin.py | 2 +- .../device_combo_box_plugin.py | 2 +- .../device_combobox/device_combobox.py | 109 ++--- .../device_line_edit/device_line_edit.py | 158 ++++---- .../device_line_edit_plugin.py | 2 +- bec_widgets/widgets/image/image_widget.py | 3 +- .../widgets/motor_map/motor_map_widget.py | 6 +- .../widgets/positioner_box/positioner_box.py | 5 +- .../widgets/scan_control/scan_group_box.py | 2 +- .../widgets/signal_combobox/__init__.py | 0 .../register_signal_combobox.py | 15 + .../signal_combobox/signal_combobox.py | 90 +++++ .../signal_combobox/signal_combobox.pyproject | 1 + .../signal_combobox/signal_combobox_plugin.py | 54 +++ .../widgets/signal_line_edit/__init__.py | 0 .../register_signal_line_edit.py | 15 + .../signal_line_edit/signal_line_edit.py | 114 ++++++ .../signal_line_edit.pyproject | 1 + .../signal_line_edit_plugin.py | 54 +++ .../widget_screenshots/device_inputs.png | Bin 4608 -> 32455 bytes .../widget_screenshots/signal_inputs.png | Bin 0 -> 64702 bytes .../device_input/QProperties_DeviceInput.png | Bin 0 -> 64935 bytes .../user/widgets/device_input/device_input.md | 39 +- .../user/widgets/signal_input/signal_input.md | 114 ++++++ .../signal_input/signal_input_qproperties.png | Bin 0 -> 34607 bytes docs/user/widgets/widgets.md | 8 + tests/unit_tests/client_mocks.py | 140 +------ tests/unit_tests/test_bec_image_widget.py | 5 +- tests/unit_tests/test_client_utils.py | 3 +- tests/unit_tests/test_device_input_base.py | 108 +++-- tests/unit_tests/test_device_input_widgets.py | 26 +- tests/unit_tests/test_device_signal_input.py | 103 +++++ tests/unit_tests/test_filter_io.py | 45 +++ tests/unit_tests/test_motor_map_widget.py | 19 +- 40 files changed, 1951 insertions(+), 387 deletions(-) create mode 100644 bec_widgets/test_utils/__init__.py create mode 100644 bec_widgets/test_utils/client_mocks.py create mode 100644 bec_widgets/utils/filter_io.py create mode 100644 bec_widgets/widgets/base_classes/device_signal_input_base.py create mode 100644 bec_widgets/widgets/signal_combobox/__init__.py create mode 100644 bec_widgets/widgets/signal_combobox/register_signal_combobox.py create mode 100644 bec_widgets/widgets/signal_combobox/signal_combobox.py create mode 100644 bec_widgets/widgets/signal_combobox/signal_combobox.pyproject create mode 100644 bec_widgets/widgets/signal_combobox/signal_combobox_plugin.py create mode 100644 bec_widgets/widgets/signal_line_edit/__init__.py create mode 100644 bec_widgets/widgets/signal_line_edit/register_signal_line_edit.py create mode 100644 bec_widgets/widgets/signal_line_edit/signal_line_edit.py create mode 100644 bec_widgets/widgets/signal_line_edit/signal_line_edit.pyproject create mode 100644 bec_widgets/widgets/signal_line_edit/signal_line_edit_plugin.py create mode 100644 docs/assets/widget_screenshots/signal_inputs.png create mode 100644 docs/user/widgets/device_input/QProperties_DeviceInput.png create mode 100644 docs/user/widgets/signal_input/signal_input.md create mode 100644 docs/user/widgets/signal_input/signal_input_qproperties.png create mode 100644 tests/unit_tests/test_device_signal_input.py create mode 100644 tests/unit_tests/test_filter_io.py diff --git a/bec_widgets/cli/client.py b/bec_widgets/cli/client.py index f198d0b3..9388aca7 100644 --- a/bec_widgets/cli/client.py +++ b/bec_widgets/cli/client.py @@ -38,6 +38,8 @@ class Widgets(str, enum.Enum): ResumeButton = "ResumeButton" RingProgressBar = "RingProgressBar" ScanControl = "ScanControl" + SignalComboBox = "SignalComboBox" + SignalLineEdit = "SignalLineEdit" StopButton = "StopButton" TextBox = "TextBox" VSCodeEditor = "VSCodeEditor" @@ -2591,6 +2593,24 @@ class DeviceLineEdit(RPCBase): """ +class DeviceSignalInputBase(RPCBase): + @property + @rpc_call + def _config_dict(self) -> "dict": + """ + Get the configuration of the widget. + + Returns: + dict: The configuration of the widget. + """ + + @rpc_call + def _get_all_rpc(self) -> "dict": + """ + Get all registered RPC objects. + """ + + class LMFitDialog(RPCBase): @property @rpc_call @@ -3003,6 +3023,42 @@ class ScanControl(RPCBase): """ +class SignalComboBox(RPCBase): + @property + @rpc_call + def _config_dict(self) -> "dict": + """ + Get the configuration of the widget. + + Returns: + dict: The configuration of the widget. + """ + + @rpc_call + def _get_all_rpc(self) -> "dict": + """ + Get all registered RPC objects. + """ + + +class SignalLineEdit(RPCBase): + @property + @rpc_call + def _config_dict(self) -> "dict": + """ + Get the configuration of the widget. + + Returns: + dict: The configuration of the widget. + """ + + @rpc_call + def _get_all_rpc(self) -> "dict": + """ + Get all registered RPC objects. + """ + + class StopButton(RPCBase): @property @rpc_call diff --git a/bec_widgets/test_utils/__init__.py b/bec_widgets/test_utils/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/bec_widgets/test_utils/client_mocks.py b/bec_widgets/test_utils/client_mocks.py new file mode 100644 index 00000000..7c2fa571 --- /dev/null +++ b/bec_widgets/test_utils/client_mocks.py @@ -0,0 +1,225 @@ +from unittest.mock import MagicMock + +from bec_lib.client import BECClient +from bec_lib.device import Device as BECDevice +from bec_lib.device import Positioner as BECPositioner +from bec_lib.device import ReadoutPriority +from bec_lib.devicemanager import DeviceContainer +from bec_lib.redis_connector import RedisConnector + + +class FakeDevice(BECDevice): + """Fake minimal positioner class for testing.""" + + def __init__(self, name, enabled=True, readout_priority=ReadoutPriority.MONITORED): + super().__init__(name=name) + self._enabled = enabled + self.signals = {self.name: {"value": 1.0}} + self.description = {self.name: {"source": self.name, "dtype": "number", "shape": []}} + self._readout_priority = readout_priority + self._config = { + "readoutPriority": "baseline", + "deviceClass": "ophyd.Device", + "deviceConfig": {}, + "deviceTags": ["user device"], + "enabled": enabled, + "readOnly": False, + "name": self.name, + } + + @property + def readout_priority(self): + return self._readout_priority + + @readout_priority.setter + def readout_priority(self, value): + self._readout_priority = value + + @property + def limits(self) -> tuple[float, float]: + return self._limits + + @limits.setter + def limits(self, value: tuple[float, float]): + self._limits = value + + def __contains__(self, item): + return item == self.name + + @property + def _hints(self): + return [self.name] + + def set_value(self, fake_value: float = 1.0) -> None: + """ + Setup fake value for device readout + Args: + fake_value(float): Desired fake value + """ + self.signals[self.name]["value"] = fake_value + + def describe(self) -> dict: + """ + Get the description of the device + Returns: + dict: Description of the device + """ + return self.description + + +class FakePositioner(BECPositioner): + + def __init__( + self, + name, + enabled=True, + limits=None, + read_value=1.0, + readout_priority=ReadoutPriority.MONITORED, + ): + super().__init__(name=name) + # self.limits = limits if limits is not None else [0.0, 0.0] + self.read_value = read_value + self._enabled = enabled + self._limits = limits + self._readout_priority = readout_priority + self.signals = {self.name: {"value": 1.0}} + self.description = {self.name: {"source": self.name, "dtype": "number", "shape": []}} + self._config = { + "readoutPriority": "baseline", + "deviceClass": "ophyd_devices.SimPositioner", + "deviceConfig": {"delay": 1, "tolerance": 0.01, "update_frequency": 400}, + "deviceTags": ["user motors"], + "enabled": enabled, + "readOnly": False, + "name": self.name, + } + self._info = { + "signals": { + "readback": {"kind_str": "5"}, # hinted + "setpoint": {"kind_str": "1"}, # normal + "velocity": {"kind_str": "2"}, # config + } + } + + @property + def readout_priority(self): + return self._readout_priority + + @readout_priority.setter + def readout_priority(self, value): + self._readout_priority = value + + @property + def enabled(self) -> bool: + return self._enabled + + @enabled.setter + def enabled(self, value: bool): + self._enabled = value + + @property + def limits(self) -> tuple[float, float]: + return self._limits + + @limits.setter + def limits(self, value: tuple[float, float]): + self._limits = value + + def __contains__(self, item): + return item == self.name + + @property + def _hints(self): + return [self.name] + + def set_value(self, fake_value: float = 1.0) -> None: + """ + Setup fake value for device readout + Args: + fake_value(float): Desired fake value + """ + self.signals[self.name]["value"] = fake_value + + def describe(self) -> dict: + """ + Get the description of the device + Returns: + dict: Description of the device + """ + return self.description + + @property + def precision(self): + return 3 + + def set_read_value(self, value): + self.read_value = value + + def read(self): + return { + self.name: {"value": self.read_value}, + f"{self.name}_setpoint": {"value": self.read_value}, + f"{self.name}_motor_is_moving": {"value": 0}, + } + + def set_limits(self, limits): + self.limits = limits + + def move(self, value, relative=False): + """Simulates moving the device to a new position.""" + if relative: + self.read_value += value + else: + self.read_value = value + # Respect the limits + self.read_value = max(min(self.read_value, self.limits[1]), self.limits[0]) + + @property + def readback(self): + return MagicMock(get=MagicMock(return_value=self.read_value)) + + +class Positioner(FakePositioner): + """just placeholder for testing embedded isinstance check in DeviceCombobox""" + + def __init__(self, name="test", limits=None, read_value=1.0): + super().__init__(name, limits, read_value) + + +class Device(FakeDevice): + """just placeholder for testing embedded isinstance check in DeviceCombobox""" + + def __init__(self, name, enabled=True): + super().__init__(name, enabled) + + +class DMMock: + def __init__(self): + self.devices = DeviceContainer() + self.enabled_devices = [device for device in self.devices if device.enabled] + + def add_devives(self, devices: list): + for device in devices: + self.devices[device.name] = device + + +DEVICES = [ + FakePositioner("samx", limits=[-10, 10], read_value=2.0), + FakePositioner("samy", limits=[-5, 5], read_value=3.0), + FakePositioner("samz", limits=[-8, 8], read_value=4.0), + FakePositioner("aptrx", limits=None, read_value=4.0), + FakePositioner("aptry", limits=None, read_value=5.0), + FakeDevice("gauss_bpm"), + FakeDevice("gauss_adc1"), + FakeDevice("gauss_adc2"), + FakeDevice("gauss_adc3"), + FakeDevice("bpm4i"), + FakeDevice("bpm3a"), + FakeDevice("bpm3i"), + FakeDevice("eiger"), + FakeDevice("waveform1d"), + FakeDevice("async_device", readout_priority=ReadoutPriority.ASYNC), + Positioner("test", limits=[-10, 10], read_value=2.0), + Device("test_device"), +] diff --git a/bec_widgets/utils/filter_io.py b/bec_widgets/utils/filter_io.py new file mode 100644 index 00000000..248c1d7f --- /dev/null +++ b/bec_widgets/utils/filter_io.py @@ -0,0 +1,156 @@ +"""Module for handling filter I/O operations in BEC Widgets for input fields. +These operations include filtering device/signal names and/or device types. +""" + +from abc import ABC, abstractmethod + +from bec_lib.logger import bec_logger +from qtpy.QtCore import QStringListModel +from qtpy.QtWidgets import QComboBox, QCompleter, QLineEdit + +logger = bec_logger.logger + + +class WidgetFilterHandler(ABC): + """Abstract base class for widget filter handlers""" + + @abstractmethod + def set_selection(self, widget, selection: list) -> None: + """Set the filtered_selection for the widget + + Args: + selection (list): Filtered selection of items + """ + + @abstractmethod + def check_input(self, widget, text: str) -> bool: + """Check if the input text is in the filtered selection + + Args: + widget: Widget instance + text (str): Input text + + Returns: + bool: True if the input text is in the filtered selection + """ + + +class LineEditFilterHandler(WidgetFilterHandler): + """Handler for QLineEdit widget""" + + def set_selection(self, widget: QLineEdit, selection: list) -> None: + """Set the selection for the widget to the completer model + + Args: + widget (QLineEdit): The QLineEdit widget + selection (list): Filtered selection of items + """ + if not isinstance(widget.completer, QCompleter): + completer = QCompleter(widget) + widget.setCompleter(completer) + widget.completer.setModel(QStringListModel(selection, widget)) + + def check_input(self, widget: QLineEdit, text: str) -> bool: + """Check if the input text is in the filtered selection + + Args: + widget (QLineEdit): The QLineEdit widget + text (str): Input text + + Returns: + bool: True if the input text is in the filtered selection + """ + model = widget.completer.model() + model_data = [model.data(model.index(i)) for i in range(model.rowCount())] + return text in model_data + + +class ComboBoxFilterHandler(WidgetFilterHandler): + """Handler for QComboBox widget""" + + def set_selection(self, widget: QComboBox, selection: list) -> None: + """Set the selection for the widget to the completer model + + Args: + widget (QComboBox): The QComboBox widget + selection (list): Filtered selection of items + """ + widget.clear() + widget.addItems(selection) + + def check_input(self, widget: QComboBox, text: str) -> bool: + """Check if the input text is in the filtered selection + + Args: + widget (QComboBox): The QComboBox widget + text (str): Input text + + Returns: + bool: True if the input text is in the filtered selection + """ + return text in [widget.itemText(i) for i in range(widget.count())] + + +class FilterIO: + """Public interface to set filters for input widgets. + It supports the list of widgets stored in class attribute _handlers. + """ + + _handlers = {QLineEdit: LineEditFilterHandler, QComboBox: ComboBoxFilterHandler} + + @staticmethod + def set_selection(widget, selection: list, ignore_errors=False): + """ + Retrieve value from the widget instance. + + Args: + widget: Widget instance. + selection(list): List of filtered selection items. + ignore_errors(bool, optional): Whether to ignore if no handler is found. + """ + handler_class = FilterIO._find_handler(widget) + if handler_class: + return handler_class().set_selection(widget=widget, selection=selection) + if not ignore_errors: + raise ValueError( + f"No matching handler for widget type: {type(widget)} in handler list {FilterIO._handlers}" + ) + return None + + @staticmethod + def check_input(widget, text: str, ignore_errors=False): + """ + Check if the input text is in the filtered selection. + + Args: + widget: Widget instance. + text(str): Input text. + ignore_errors(bool, optional): Whether to ignore if no handler is found. + + Returns: + bool: True if the input text is in the filtered selection. + """ + handler_class = FilterIO._find_handler(widget) + if handler_class: + return handler_class().check_input(widget=widget, text=text) + if not ignore_errors: + raise ValueError( + f"No matching handler for widget type: {type(widget)} in handler list {FilterIO._handlers}" + ) + return None + + @staticmethod + def _find_handler(widget): + """ + Find the appropriate handler for the widget by checking its base classes. + + Args: + widget: Widget instance. + + Returns: + handler_class: The handler class if found, otherwise None. + """ + for base in type(widget).__mro__: + if base in FilterIO._handlers: + return FilterIO._handlers[base] + return None diff --git a/bec_widgets/widgets/base_classes/device_input_base.py b/bec_widgets/widgets/base_classes/device_input_base.py index b1822f39..9df3b1a2 100644 --- a/bec_widgets/widgets/base_classes/device_input_base.py +++ b/bec_widgets/widgets/base_classes/device_input_base.py @@ -1,22 +1,65 @@ from __future__ import annotations +import enum + +from bec_lib.device import ComputedSignal, Device, Positioner, ReadoutPriority, Signal +from bec_lib.logger import bec_logger +from qtpy.QtCore import Property, Slot +from typeguard import typechecked + from bec_widgets.utils import ConnectionConfig from bec_widgets.utils.bec_widget import BECWidget +from bec_widgets.utils.filter_io import FilterIO +from bec_widgets.utils.widget_io import WidgetIO + +logger = bec_logger.logger + + +class BECDeviceFilter(enum.Enum): + """Filter for the device classes.""" + + DEVICE = "Device" + POSITIONER = "Positioner" + SIGNAL = "Signal" + COMPUTED_SIGNAL = "ComputedSignal" class DeviceInputConfig(ConnectionConfig): - device_filter: str | list[str] | None = None + device_filter: list[BECDeviceFilter] | None = None + readout_filter: list[ReadoutPriority] | None = None + devices: list[str] | None = None default: str | None = None arg_name: str | None = None class DeviceInputBase(BECWidget): """ - Mixin class for device input widgets. This class provides methods to get the device list and device object based - on the current text of the widget. + Mixin base class for device input widgets. + It allows to filter devices from BEC based on + device class and readout priority. """ - def __init__(self, client=None, config=None, gui_id=None): + _device_handler = { + BECDeviceFilter.DEVICE: Device, + BECDeviceFilter.POSITIONER: Positioner, + BECDeviceFilter.SIGNAL: Signal, + BECDeviceFilter.COMPUTED_SIGNAL: ComputedSignal, + } + + _filter_handler = { + BECDeviceFilter.DEVICE: "include_device", + BECDeviceFilter.POSITIONER: "include_positioner", + BECDeviceFilter.SIGNAL: "include_signal", + BECDeviceFilter.COMPUTED_SIGNAL: "include_computed_signal", + ReadoutPriority.MONITORED: "readout_monitored", + ReadoutPriority.BASELINE: "readout_baseline", + ReadoutPriority.ASYNC: "readout_async", + ReadoutPriority.CONTINUOUS: "readout_continuous", + ReadoutPriority.ON_REQUEST: "readout_on_request", + } + + def __init__(self, client=None, config=None, gui_id: str = None): + if config is None: config = DeviceInputConfig(widget_class=self.__class__.__name__) else: @@ -24,15 +67,192 @@ class DeviceInputBase(BECWidget): config = DeviceInputConfig(**config) self.config = config super().__init__(client=client, config=config, gui_id=gui_id) - self.get_bec_shortcuts() - self._device_filter = None + self._device_filter = [] + self._readout_filter = [] self._devices = [] + ### QtSlots ### + + @Slot(str) + def set_device(self, device: str): + """ + Set the device. + + Args: + device (str): Default name. + """ + if self.validate_device(device, raise_on_false=True) is True: + WidgetIO.set_value(widget=self, value=device) + self.config.default = device + else: + logger.warning(f"Device {device} is not in the filtered selection.") + + @Slot() + def update_devices_from_filters(self): + """Update the devices based on the current filter selection + in self.device_filter and self.readout_filter.""" + self.config.device_filter = self.device_filter + self.config.readout_filter = self.readout_filter + all_dev = self.dev.enabled_devices + # Filter based on device class + devs = [dev for dev in all_dev if self._check_device_filter(dev)] + # Filter based on readout priority + devs = [dev for dev in devs if self._check_readout_filter(dev)] + self.devices = [device.name for device in devs] + + @Slot(list) + def set_available_devices(self, devices: list[str]): + """ + Set the devices. If a device in the list is not valid, it will not be considered. + + Args: + devices (list[str]): List of devices. + """ + valid_dev = [] + all_dev_names = [dev.name for dev in self.dev.enabled_devices] + for device in devices: + if device not in all_dev_names: + continue + valid_dev.append(device) + self.devices = valid_dev + + ### QtProperties ### + + @Property(str) + def default(self): + """Get the default device name. If set through this property, it will update only if the device is within the filtered selection.""" + return self.config.default + + @default.setter + def default(self, value: str): + if self.validate_device(value, raise_on_false=False) is False: + return + self.set_device(value) + + @Property(bool) + def include_device(self): + """Include devices in filters.""" + return BECDeviceFilter.DEVICE in self.device_filter + + @include_device.setter + def include_device(self, value: bool): + if value is True and BECDeviceFilter.DEVICE not in self.device_filter: + self._device_filter.append(BECDeviceFilter.DEVICE) + if value is False and BECDeviceFilter.DEVICE in self.device_filter: + self._device_filter.remove(BECDeviceFilter.DEVICE) + self.update_devices_from_filters() + + @Property(bool) + def include_positioner(self): + """Include devices of type Positioner in filters.""" + return BECDeviceFilter.POSITIONER in self.device_filter + + @include_positioner.setter + def include_positioner(self, value: bool): + if value is True and BECDeviceFilter.POSITIONER not in self.device_filter: + self._device_filter.append(BECDeviceFilter.POSITIONER) + if value is False and BECDeviceFilter.POSITIONER in self.device_filter: + self._device_filter.remove(BECDeviceFilter.POSITIONER) + self.update_devices_from_filters() + + @Property(bool) + def include_signal(self): + """Include devices of type Signal in filters.""" + return BECDeviceFilter.SIGNAL in self.device_filter + + @include_signal.setter + def include_signal(self, value: bool): + if value is True and BECDeviceFilter.SIGNAL not in self.device_filter: + self._device_filter.append(BECDeviceFilter.SIGNAL) + if value is False and BECDeviceFilter.SIGNAL in self.device_filter: + self._device_filter.remove(BECDeviceFilter.SIGNAL) + self.update_devices_from_filters() + + @Property(bool) + def include_computed_signal(self): + """Include devices of type ComputedSignal in filters.""" + return BECDeviceFilter.COMPUTED_SIGNAL in self.device_filter + + @include_computed_signal.setter + def include_computed_signal(self, value: bool): + if value is True and BECDeviceFilter.COMPUTED_SIGNAL not in self.device_filter: + self._device_filter.append(BECDeviceFilter.COMPUTED_SIGNAL) + if value is False and BECDeviceFilter.COMPUTED_SIGNAL in self.device_filter: + self._device_filter.remove(BECDeviceFilter.COMPUTED_SIGNAL) + self.update_devices_from_filters() + + @Property(bool) + def readout_monitored(self): + """Include devices with readout priority Monitored in filters.""" + return ReadoutPriority.MONITORED in self.readout_filter + + @readout_monitored.setter + def readout_monitored(self, value: bool): + if value is True and ReadoutPriority.MONITORED not in self.readout_filter: + self._readout_filter.append(ReadoutPriority.MONITORED) + if value is False and ReadoutPriority.MONITORED in self.readout_filter: + self._readout_filter.remove(ReadoutPriority.MONITORED) + self.update_devices_from_filters() + + @Property(bool) + def readout_baseline(self): + """Include devices with readout priority Baseline in filters.""" + return ReadoutPriority.BASELINE in self.readout_filter + + @readout_baseline.setter + def readout_baseline(self, value: bool): + if value is True and ReadoutPriority.BASELINE not in self.readout_filter: + self._readout_filter.append(ReadoutPriority.BASELINE) + if value is False and ReadoutPriority.BASELINE in self.readout_filter: + self._readout_filter.remove(ReadoutPriority.BASELINE) + self.update_devices_from_filters() + + @Property(bool) + def readout_async(self): + """Include devices with readout priority Async in filters.""" + return ReadoutPriority.ASYNC in self.readout_filter + + @readout_async.setter + def readout_async(self, value: bool): + if value is True and ReadoutPriority.ASYNC not in self.readout_filter: + self._readout_filter.append(ReadoutPriority.ASYNC) + if value is False and ReadoutPriority.ASYNC in self.readout_filter: + self._readout_filter.remove(ReadoutPriority.ASYNC) + self.update_devices_from_filters() + + @Property(bool) + def readout_continuous(self): + """Include devices with readout priority continuous in filters.""" + return ReadoutPriority.CONTINUOUS in self.readout_filter + + @readout_continuous.setter + def readout_continuous(self, value: bool): + if value is True and ReadoutPriority.CONTINUOUS not in self.readout_filter: + self._readout_filter.append(ReadoutPriority.CONTINUOUS) + if value is False and ReadoutPriority.CONTINUOUS in self.readout_filter: + self._readout_filter.remove(ReadoutPriority.CONTINUOUS) + self.update_devices_from_filters() + + @Property(bool) + def readout_on_request(self): + """Include devices with readout priority OnRequest in filters.""" + return ReadoutPriority.ON_REQUEST in self.readout_filter + + @readout_on_request.setter + def readout_on_request(self, value: bool): + if value is True and ReadoutPriority.ON_REQUEST not in self.readout_filter: + self._readout_filter.append(ReadoutPriority.ON_REQUEST) + if value is False and ReadoutPriority.ON_REQUEST in self.readout_filter: + self._readout_filter.remove(ReadoutPriority.ON_REQUEST) + self.update_devices_from_filters() + + ### Python Methods and Properties ### + @property def devices(self) -> list[str]: """ - Get the list of devices. + Get the list of devices for the applied filters. Returns: list[str]: List of devices. @@ -41,83 +261,116 @@ class DeviceInputBase(BECWidget): @devices.setter def devices(self, value: list[str]): - """ - Set the list of devices. - - Args: - value: List of devices. - """ self._devices = value + self.config.devices = value + FilterIO.set_selection(widget=self, selection=value) - def set_device_filter(self, device_filter: str | list[str]): + @property + def device_filter(self) -> list[object]: + """Get the list of filters to apply on the devices.""" + return self._device_filter + + @property + def readout_filter(self) -> list[str]: + """Get the list of filters to apply on the devices""" + return self._readout_filter + + def get_available_filters(self) -> list: + """Get the available filters.""" + return [entry for entry in BECDeviceFilter] + + def get_readout_priority_filters(self) -> list: + """Get the available readout priority filters.""" + return [entry for entry in ReadoutPriority] + + @typechecked + def set_device_filter( + self, filter_selection: str | BECDeviceFilter | list[str] | list[BECDeviceFilter] + ): """ - Set the device filter. + Set the device filter. If None is passed, no filters are applied and all devices included. Args: - device_filter(str): Device filter, name of the device class. + filter_selection (str | list[str]): Device filters. It is recommended to make an enum for the filters. """ - self.validate_device_filter(device_filter) - self.config.device_filter = device_filter - self._device_filter = device_filter + filters = None + if isinstance(filter_selection, list): + filters = [self._filter_handler.get(entry) for entry in filter_selection] + if isinstance(filter_selection, str) or isinstance(filter_selection, BECDeviceFilter): + filters = [self._filter_handler.get(filter_selection)] + if filters is None or any([entry is None for entry in filters]): + raise ValueError(f"Device filter {filter_selection} is not in the device list.") + for entry in filters: + setattr(self, entry, True) - def set_default_device(self, default_device: str): + @typechecked + def set_readout_priority_filter( + self, filter_selection: str | ReadoutPriority | list[str] | list[ReadoutPriority] + ): """ - Set the default device. + Set the readout priority filter. If None is passed, all filters are included. Args: - default_device(str): Default device name. + filter_selection (str | list[str]): Readout priority filters. """ - self.validate_device(default_device) - self.config.default = default_device + filters = None + if isinstance(filter_selection, list): + filters = [self._filter_handler.get(entry) for entry in filter_selection] + if isinstance(filter_selection, str) or isinstance(filter_selection, ReadoutPriority): + filters = [self._filter_handler.get(filter_selection)] + if filters is None or any([entry is None for entry in filters]): + raise ValueError( + f"Readout priority filter {filter_selection} is not in the readout priority list." + ) + for entry in filters: + setattr(self, entry, True) - def get_device_list(self, filter: str | list[str] | None = None) -> list[str]: - """ - Get the list of device names based on the filter of current BEC client. + def _check_device_filter(self, device: Device | Signal | ComputedSignal | Positioner) -> bool: + """If filters are defined, return True. Else return if the device complies to all active filters. Args: - filter(str|None): Class name filter to apply on the device list. + device(Device | Signal | ComputedSignal | Positioner): Device object. + """ + if len(self.device_filter) == 0: + return True + return all(isinstance(device, self._device_handler[entry]) for entry in self.device_filter) + + def _check_readout_filter(self, device: Device | Signal | ComputedSignal | Positioner) -> bool: + """If filters are defined, return True. Else return if the device complies to all active filters. + + Args: + device(Device | Signal | ComputedSignal | Positioner): Device object. + """ + if len(self.readout_filter) == 0: + return True + return device.readout_priority in self.readout_filter + + def get_device_object(self, device: str) -> object: + """ + Get the device object based on the device name. + + Args: + device(str): Device name. Returns: - devices(list[str]): List of device names. + object: Device object, can be device of type Device, Positioner, Signal or ComputedSignal. """ - all_devices = self.dev.enabled_devices - if filter is not None: - self.validate_device_filter(filter) - if isinstance(filter, str): - filter = [filter] - devices = [device.name for device in all_devices if device.__class__.__name__ in filter] - else: - devices = [device.name for device in all_devices] - return devices + self.validate_device(device) + dev = getattr(self.dev, device.lower(), None) + if dev is None: + raise ValueError( + f"Device {device} is not found in devicemanager {self.dev} as enabled device." + ) + return dev - def get_available_filters(self): + def validate_device(self, device: str, raise_on_false: bool = False) -> bool: """ - Get the available device classes which can be used as filters. - """ - all_devices = self.dev.enabled_devices - filters = {device.__class__.__name__ for device in all_devices} - return filters - - def validate_device_filter(self, filter: str | list[str]) -> None: - """ - Validate the device filter if the class name is present in the current BEC instance. - - Args: - filter(str|list[str]): Class name to use as a device filter. - """ - if isinstance(filter, str): - filter = [filter] - available_filters = self.get_available_filters() - for f in filter: - if f not in available_filters: - raise ValueError(f"Device filter {f} is not valid.") - - def validate_device(self, device: str) -> None: - """ - Validate the device if it is present in current BEC instance. + Validate the device if it is present in the filtered device selection. Args: device(str): Device to validate. """ - if device not in self.get_device_list(self.config.device_filter): - raise ValueError(f"Device {device} is not valid.") + if device in self.devices: + return True + if raise_on_false is True: + raise ValueError(f"Device {device} is not in filtered selection.") diff --git a/bec_widgets/widgets/base_classes/device_signal_input_base.py b/bec_widgets/widgets/base_classes/device_signal_input_base.py new file mode 100644 index 00000000..28253e9a --- /dev/null +++ b/bec_widgets/widgets/base_classes/device_signal_input_base.py @@ -0,0 +1,277 @@ +import enum + +from bec_lib.logger import bec_logger +from qtpy.QtCore import Property, Slot + +from bec_widgets.utils import ConnectionConfig +from bec_widgets.utils.bec_widget import BECWidget +from bec_widgets.utils.filter_io import FilterIO +from bec_widgets.utils.widget_io import WidgetIO + +logger = bec_logger.logger + + +class BECSignalFilter(str, enum.Enum): + """Filter for the device signals.""" + + HINTED = "5" + NORMAL = "1" + CONFIG = "2" + + +class DeviceSignalInputBaseConfig(ConnectionConfig): + """Configuration class for DeviceSignalInputBase.""" + + signal_filter: str | list[str] | None = None + default: str | None = None + arg_name: str | None = None + device: str | None = None + signals: list[str] | None = None + + +class DeviceSignalInputBase(BECWidget): + """ + Mixin base class for device signal input widgets. + Mixin class for device signal input widgets. This class provides methods to get the device signal list and device + signal object based on the current text of the widget. + """ + + _filter_handler = { + BECSignalFilter.HINTED: "include_hinted_signals", + BECSignalFilter.NORMAL: "include_normal_signals", + BECSignalFilter.CONFIG: "include_config_signals", + } + + def __init__(self, client=None, config=None, gui_id: str = None): + if config is None: + config = DeviceSignalInputBaseConfig(widget_class=self.__class__.__name__) + else: + if isinstance(config, dict): + config = DeviceSignalInputBaseConfig(**config) + self.config = config + super().__init__(client=client, config=config, gui_id=gui_id) + + self._device = None + self.get_bec_shortcuts() + self._signal_filter = [] + self._signals = [] + self._hinted_signals = [] + self._normal_signals = [] + self._config_signals = [] + + ### Qt Slots ### + + @Slot(str) + def set_signal(self, signal: str): + """ + Set the signal. + + Args: + signal (str): signal name. + """ + if self.validate_signal(signal, raise_on_false=False) is True: + WidgetIO.set_value(widget=self, value=signal) + self.config.default = signal + else: + logger.warning( + f"Signal {signal} not found for device {self.device} and filtered selection {self.signal_filter}." + ) + + @Slot(str) + def set_device(self, device: str | None): + """ + Set the device. + + Args: + device(str): device name. + """ + if device is None: + self._device = None + if self.validate_device(device, raise_on_false=False) is True: + self._device = device + self.update_signals_from_filters() + else: + logger.warning(f"Device {device} not found in device_manager.") + + @Slot() + def update_signals_from_filters(self): + """Update the filters for the device signals based on list in self.signal_filter. + In addition, store the hinted, normal and config signals in separate lists to allow + customisation within QLineEdit.""" + self.config.signal_filter = self.signal_filter + # pylint: disable=protected-access + self._hinted_signals = [] + self._normal_signals = [] + self._config_signals = [] + if self._device is None: + return + device = self.get_device_object(self._device) + device_info = device._info["signals"] + if BECSignalFilter.HINTED in self.signal_filter or len(self.signal_filter) == 0: + hinted_signals = [ + signal + for signal, signal_info in device_info.items() + if (signal_info.get("kind_str", None) == BECSignalFilter.HINTED) + ] + self._hinted_signals = hinted_signals + if BECSignalFilter.NORMAL in self.signal_filter or len(self.signal_filter) == 0: + normal_signals = [ + signal + for signal, signal_info in device_info.items() + if (signal_info.get("kind_str", None) == BECSignalFilter.NORMAL) + ] + self._normal_signals = normal_signals + if BECSignalFilter.CONFIG in self.signal_filter or len(self.signal_filter) == 0: + config_signals = [ + signal + for signal, signal_info in device_info.items() + if (signal_info.get("kind_str", None) == BECSignalFilter.CONFIG) + ] + self._config_signals = config_signals + self._signals = self._hinted_signals + self._normal_signals + self._config_signals + FilterIO.set_selection(widget=self, selection=self.signals) + + ### Qt Properties ### + + @Property(str) + def device(self) -> str: + """Get the selected device.""" + if self._device is None: + return "" + return self._device + + @device.setter + def device(self, value: str): + """Set the device and update the filters, only allow devices present in the devicemanager.""" + if self.validate_device(value) is False: + return + self._device = value + self.config.device = value + self.update_signals_from_filters() + + @Property(bool) + def include_hinted_signals(self): + """Include hinted signals in filters.""" + return BECSignalFilter.HINTED in self.signal_filter + + @include_hinted_signals.setter + def include_hinted_signals(self, value: bool): + if value: + self._signal_filter.append(BECSignalFilter.HINTED) + else: + self._signal_filter.remove(BECSignalFilter.HINTED) + self.update_signals_from_filters() + + @Property(bool) + def include_normal_signals(self): + """Include normal signals in filters.""" + return BECSignalFilter.NORMAL in self.signal_filter + + @include_normal_signals.setter + def include_normal_signals(self, value: bool): + if value: + self._signal_filter.append(BECSignalFilter.NORMAL) + else: + self._signal_filter.remove(BECSignalFilter.NORMAL) + self.update_signals_from_filters() + + @Property(bool) + def include_config_signals(self): + """Include config signals in filters.""" + return BECSignalFilter.CONFIG in self.signal_filter + + @include_config_signals.setter + def include_config_signals(self, value: bool): + if value: + self._signal_filter.append(BECSignalFilter.CONFIG) + else: + self._signal_filter.remove(BECSignalFilter.CONFIG) + self.update_signals_from_filters() + + ### Properties and Methods ### + + @property + def signals(self) -> list[str]: + """ + Get the list of device signals for the applied filters. + + Returns: + list[str]: List of device signals. + """ + return self._signals + + @signals.setter + def signals(self, value: list[str]): + self._signals = value + self.config.signals = value + FilterIO.set_selection(widget=self, selection=value) + + @property + def signal_filter(self) -> list[str]: + """Get the list of filters to apply on the device signals.""" + return self._signal_filter + + def get_available_filters(self) -> list[str]: + """Get the available filters.""" + return [entry for entry in self._filter_handler] + + def set_filter(self, filter_selection: str | list[str]): + """ + Set the device filter. If None, all devices are included. + + Args: + filter_selection (str | list[str]): Device filters from BECDeviceFilter and BECReadoutPriority. + """ + filters = None + if isinstance(filter_selection, list): + filters = [self._filter_handler.get(entry) for entry in filter_selection] + if isinstance(filter_selection, str): + filters = [self._filter_handler.get(filter_selection)] + if filters is None: + return + for entry in filters: + setattr(self, entry, True) + + def get_device_object(self, device: str) -> object: + """ + Get the device object based on the device name. + + Args: + device(str): Device name. + + Returns: + object: Device object, can be device of type Device, Positioner, Signal or ComputedSignal. + """ + self.validate_device(device) + dev = getattr(self.dev, device.lower(), None) + if dev is None: + raise ValueError(f"Device {device} is not found in devicemanager {self.dev}.") + return dev + + def validate_device(self, device: str, raise_on_false: bool = False) -> bool: + """ + Validate the device if it is present in current BEC instance. + + Args: + device(str): Device to validate. + """ + if device in self.dev: + return True + if raise_on_false is True: + raise ValueError(f"Device {device} not found in devicemanager.") + return False + + def validate_signal(self, signal: str, raise_on_false: bool = False) -> bool: + """ + Validate the signal if it is present in the device signals. + + Args: + signal(str): Signal to validate. + """ + if signal in self.signals: + return True + if raise_on_false is True: + raise ValueError( + f"Signal {signal} not found for device {self.device} and filtered selection {self.signal_filter}." + ) + return False diff --git a/bec_widgets/widgets/dap_combo_box/dap_combo_box_plugin.py b/bec_widgets/widgets/dap_combo_box/dap_combo_box_plugin.py index 30ea3898..657330f1 100644 --- a/bec_widgets/widgets/dap_combo_box/dap_combo_box_plugin.py +++ b/bec_widgets/widgets/dap_combo_box/dap_combo_box_plugin.py @@ -27,7 +27,7 @@ class DapComboBoxPlugin(QDesignerCustomWidgetInterface): # pragma: no cover return DOM_XML def group(self): - return "BEC Selection Widgets" + return "BEC Input Widgets" def icon(self): return designer_material_icon(DapComboBox.ICON_NAME) diff --git a/bec_widgets/widgets/device_combobox/device_combo_box_plugin.py b/bec_widgets/widgets/device_combobox/device_combo_box_plugin.py index 7907696d..c13ee1c1 100644 --- a/bec_widgets/widgets/device_combobox/device_combo_box_plugin.py +++ b/bec_widgets/widgets/device_combobox/device_combo_box_plugin.py @@ -31,7 +31,7 @@ class DeviceComboBoxPlugin(QDesignerCustomWidgetInterface): # pragma: no cover return DOM_XML def group(self): - return "Device Control" + return "BEC Input Widgets" def icon(self): return designer_material_icon(DeviceComboBox.ICON_NAME) diff --git a/bec_widgets/widgets/device_combobox/device_combobox.py b/bec_widgets/widgets/device_combobox/device_combobox.py index 39d4775c..06eb4e3e 100644 --- a/bec_widgets/widgets/device_combobox/device_combobox.py +++ b/bec_widgets/widgets/device_combobox/device_combobox.py @@ -1,23 +1,25 @@ -from typing import TYPE_CHECKING +from bec_lib.device import ReadoutPriority +from qtpy.QtCore import QSize +from qtpy.QtWidgets import QComboBox, QSizePolicy -from qtpy.QtWidgets import QComboBox - -from bec_widgets.widgets.base_classes.device_input_base import DeviceInputBase, DeviceInputConfig - -if TYPE_CHECKING: - from bec_widgets.widgets.base_classes.device_input_base import DeviceInputConfig +from bec_widgets.utils.colors import get_accent_colors +from bec_widgets.widgets.base_classes.device_input_base import ( + BECDeviceFilter, + DeviceInputBase, + DeviceInputConfig, +) class DeviceComboBox(DeviceInputBase, QComboBox): """ - Line edit widget for device input with autocomplete for device names. + Combobox widget for device input with autocomplete for device names. Args: parent: Parent widget. client: BEC client object. config: Device input configuration. gui_id: GUI ID. - device_filter: Device filter, name of the device class. + device_filter: Device filter, name of the device class from BECDeviceFilter and BECReadoutPriority. Check DeviceInputBase for more details. default: Default device name. arg_name: Argument name, can be used for the other widgets which has to call some other function in bec using correct argument names. """ @@ -30,57 +32,68 @@ class DeviceComboBox(DeviceInputBase, QComboBox): client=None, config: DeviceInputConfig = None, gui_id: str | None = None, - device_filter: str | None = None, + device_filter: BECDeviceFilter | list[BECDeviceFilter] | None = None, + readout_priority_filter: ( + str | ReadoutPriority | list[str] | list[ReadoutPriority] | None + ) = None, + device_list: list[str] | None = None, default: str | None = None, arg_name: str | None = None, ): super().__init__(client=client, config=config, gui_id=gui_id) QComboBox.__init__(self, parent=parent) - self.setMinimumSize(125, 26) - self.populate_combobox() - if arg_name is not None: self.config.arg_name = arg_name + self.arg_name = arg_name + self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) + self.setMinimumSize(QSize(100, 0)) + self._is_valid_input = False + self._accent_colors = get_accent_colors() + # Set readout priority filter and device filter. + # If value is set directly in init, this overrules value from the config + readout_priority_filter = ( + readout_priority_filter + if readout_priority_filter is not None + else self.config.readout_filter + ) + if readout_priority_filter is not None: + self.set_readout_priority_filter(readout_priority_filter) + device_filter = device_filter if device_filter is not None else self.config.device_filter if device_filter is not None: self.set_device_filter(device_filter) + device_list = device_list if device_list is not None else self.config.devices + if device_list is not None: + self.set_available_devices(device_list) + else: + self.update_devices_from_filters() + default = default if default is not None else self.config.default if default is not None: - self.set_default_device(default) + self.set_device(default) - def set_device_filter(self, device_filter: str): + def get_current_device(self) -> object: """ - Set the device filter. - - Args: - device_filter(str): Device filter, name of the device class. - """ - super().set_device_filter(device_filter) - self.populate_combobox() - - def set_default_device(self, default_device: str): - """ - Set the default device. - - Args: - default_device(str): Default device name. - """ - super().set_default_device(default_device) - self.setCurrentText(default_device) - - def populate_combobox(self): - """Populate the combobox with the devices.""" - self.devices = self.get_device_list(self.config.device_filter) - self.clear() - self.addItems(self.devices) - - def get_device(self) -> object: - """ - Get the selected device object. + Get the current device object based on the current value. Returns: - object: Device object. + object: Device object, can be device of type Device, Positioner, Signal or ComputedSignal. """ - device_name = self.currentText() - device_obj = getattr(self.dev, device_name.lower(), None) - if device_obj is None: - raise ValueError(f"Device {device_name} is not found.") - return device_obj + dev_name = self.currentText() + return self.get_device_object(dev_name) + + +if __name__ == "__main__": # pragma: no cover + # pylint: disable=import-outside-toplevel + from qtpy.QtWidgets import QApplication, QVBoxLayout, QWidget + + from bec_widgets.utils.colors import set_theme + + app = QApplication([]) + set_theme("dark") + widget = QWidget() + widget.setFixedSize(200, 200) + layout = QVBoxLayout() + widget.setLayout(layout) + combo = DeviceComboBox() + layout.addWidget(combo) + widget.show() + app.exec_() diff --git a/bec_widgets/widgets/device_line_edit/device_line_edit.py b/bec_widgets/widgets/device_line_edit/device_line_edit.py index f9f4ec97..420f50f1 100644 --- a/bec_widgets/widgets/device_line_edit/device_line_edit.py +++ b/bec_widgets/widgets/device_line_edit/device_line_edit.py @@ -1,13 +1,14 @@ -from typing import TYPE_CHECKING - -from qtpy.QtCore import QSize, Signal, Slot +from bec_lib.device import ReadoutPriority +from qtpy.QtCore import QSize +from qtpy.QtGui import QPainter, QPaintEvent, QPen from qtpy.QtWidgets import QCompleter, QLineEdit, QSizePolicy -from bec_widgets.utils.bec_widget import BECWidget -from bec_widgets.widgets.base_classes.device_input_base import DeviceInputBase, DeviceInputConfig - -if TYPE_CHECKING: - from bec_widgets.widgets.base_classes.device_input_base import DeviceInputConfig +from bec_widgets.utils.colors import get_accent_colors +from bec_widgets.widgets.base_classes.device_input_base import ( + BECDeviceFilter, + DeviceInputBase, + DeviceInputConfig, +) class DeviceLineEdit(DeviceInputBase, QLineEdit): @@ -19,7 +20,7 @@ class DeviceLineEdit(DeviceInputBase, QLineEdit): client: BEC client object. config: Device input configuration. gui_id: GUI ID. - device_filter: Device filter, name of the device class. + device_filter: Device filter, name of the device class from BECDeviceFilter and ReadoutPriority. Check DeviceInputBase for more details. default: Default device name. arg_name: Argument name, can be used for the other widgets which has to call some other function in bec using correct argument names. """ @@ -34,80 +35,99 @@ class DeviceLineEdit(DeviceInputBase, QLineEdit): client=None, config: DeviceInputConfig = None, gui_id: str | None = None, - device_filter: str | list[str] | None = None, + device_filter: BECDeviceFilter | list[BECDeviceFilter] | None = None, + readout_priority_filter: ( + str | ReadoutPriority | list[str] | list[ReadoutPriority] | None + ) = None, + device_list: list[str] | None = None, default: str | None = None, arg_name: str | None = None, ): super().__init__(client=client, config=config, gui_id=gui_id) QLineEdit.__init__(self, parent=parent) - + self._is_valid_input = False self.completer = QCompleter(self) self.setCompleter(self.completer) - self.populate_completer() - if arg_name is not None: self.config.arg_name = arg_name self.arg_name = arg_name - if device_filter is not None: - self.set_device_filter(device_filter) - if default is not None: - self.set_default_device(default) - self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) self.setMinimumSize(QSize(100, 0)) + self._accent_colors = get_accent_colors() + # Set readout priority filter and device filter. + # If value is set directly in init, this overrules value from the config + readout_priority_filter = ( + readout_priority_filter + if readout_priority_filter is not None + else self.config.readout_filter + ) + if readout_priority_filter is not None: + self.set_readout_priority_filter(readout_priority_filter) + device_filter = device_filter if device_filter is not None else self.config.device_filter + if device_filter is not None: + self.set_device_filter(device_filter) + device_list = device_list if device_list is not None else self.config.devices + if device_list is not None: + self.set_available_devices(device_list) + else: + self.update_devices_from_filters() + default = default if default is not None else self.config.default + if default is not None: + self.set_device(default) + self.textChanged.connect(self.check_validity) - self.editingFinished.connect(self.emit_device_selected) - - @Slot() - def emit_device_selected(self): + def get_current_device(self) -> object: """ - Editing finished, let's see which device is selected and emit signal - """ - device_name = self.text().lower() - device_obj = getattr(self.dev, device_name, None) - if device_obj is not None: - self.device_selected.emit(device_name) - - def set_device_filter(self, device_filter: str | list[str]): - """ - Set the device filter. - - Args: - device_filter (str | list[str]): Device filter, name of the device class. - """ - super().set_device_filter(device_filter) - self.populate_completer() - - def set_default_device(self, default_device: str): - """ - Set the default device. - - Args: - default_device (str): Default device name. - """ - super().set_default_device(default_device) - self.setText(default_device) - - def populate_completer(self): - """Populate the completer with the devices.""" - self.devices = self.get_device_list(self.config.device_filter) - self.completer.setModel(self.create_completer_model(self.devices)) - - def create_completer_model(self, devices: list[str]): - """Create a model for the completer.""" - from qtpy.QtCore import QStringListModel - - return QStringListModel(devices, self) - - def get_device(self) -> object: - """ - Get the selected device object. + Get the current device object based on the current value. Returns: - object: Device object. + object: Device object, can be device of type Device, Positioner, Signal or ComputedSignal. """ - device_name = self.text() - device_obj = getattr(self.dev, device_name.lower(), None) - if device_obj is None: - raise ValueError(f"Device {device_name} is not found.") - return device_obj + dev_name = self.text() + return self.get_device_object(dev_name) + + def paintEvent(self, event: QPaintEvent) -> None: + """Extend the paint event to set the border color based on the validity of the input. + + Args: + event (PySide6.QtGui.QPaintEvent) : Paint event. + """ + super().paintEvent(event) + painter = QPainter(self) + pen = QPen() + pen.setWidth(2) + + if self._is_valid_input is False and self.isEnabled() is True: + pen.setColor(self._accent_colors.emergency) + painter.setPen(pen) + painter.drawRect(self.rect().adjusted(1, 1, -1, -1)) + + def check_validity(self, input_text: str) -> None: + """ + Check if the current value is a valid device name. + """ + if self.validate_device(input_text) is True: + self._is_valid_input = True + self.device_selected.emit(input_text.lower()) + else: + self._is_valid_input = False + self.update() + + +if __name__ == "__main__": # pragma: no cover + # pylint: disable=import-outside-toplevel + from qtpy.QtWidgets import QApplication, QVBoxLayout, QWidget + + from bec_widgets.utils.colors import set_theme + + app = QApplication([]) + set_theme("dark") + widget = QWidget() + widget.setFixedSize(200, 200) + layout = QVBoxLayout() + widget.setLayout(layout) + line_edit = DeviceLineEdit() + line_edit.include_positioner = True + layout.addWidget(line_edit) + widget.show() + app.exec_() diff --git a/bec_widgets/widgets/device_line_edit/device_line_edit_plugin.py b/bec_widgets/widgets/device_line_edit/device_line_edit_plugin.py index bef28852..617d0d2b 100644 --- a/bec_widgets/widgets/device_line_edit/device_line_edit_plugin.py +++ b/bec_widgets/widgets/device_line_edit/device_line_edit_plugin.py @@ -31,7 +31,7 @@ class DeviceLineEditPlugin(QDesignerCustomWidgetInterface): # pragma: no cover return DOM_XML def group(self): - return "Device Control" + return "BEC Input Widgets" def icon(self): return designer_material_icon(DeviceLineEdit.ICON_NAME) diff --git a/bec_widgets/widgets/image/image_widget.py b/bec_widgets/widgets/image/image_widget.py index b94f3601..97376604 100644 --- a/bec_widgets/widgets/image/image_widget.py +++ b/bec_widgets/widgets/image/image_widget.py @@ -16,6 +16,7 @@ from bec_widgets.qt_utils.toolbar import ( WidgetAction, ) from bec_widgets.utils.bec_widget import BECWidget +from bec_widgets.widgets.base_classes.device_input_base import BECDeviceFilter from bec_widgets.widgets.device_combobox.device_combobox import DeviceComboBox from bec_widgets.widgets.figure import BECFigure from bec_widgets.widgets.figure.plots.axis_settings import AxisSettings @@ -69,7 +70,7 @@ class BECImageWidget(BECWidget, QWidget): self.toolbar = ModularToolBar( actions={ "monitor": DeviceSelectionAction( - "Monitor:", DeviceComboBox(device_filter="Device") + "Monitor:", DeviceComboBox(device_filter=BECDeviceFilter.DEVICE) ), "monitor_type": WidgetAction(widget=self.dim_combo_box), "connect": MaterialIconAction(icon_name="link", tooltip="Connect Device"), diff --git a/bec_widgets/widgets/motor_map/motor_map_widget.py b/bec_widgets/widgets/motor_map/motor_map_widget.py index 8f67e06d..0b3deb50 100644 --- a/bec_widgets/widgets/motor_map/motor_map_widget.py +++ b/bec_widgets/widgets/motor_map/motor_map_widget.py @@ -2,11 +2,13 @@ from __future__ import annotations import sys +from bec_lib.device import ReadoutPriority from qtpy.QtWidgets import QVBoxLayout, QWidget from bec_widgets.qt_utils.settings_dialog import SettingsDialog from bec_widgets.qt_utils.toolbar import DeviceSelectionAction, MaterialIconAction, ModularToolBar from bec_widgets.utils.bec_widget import BECWidget +from bec_widgets.widgets.base_classes.device_input_base import BECDeviceFilter 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 @@ -50,10 +52,10 @@ class BECMotorMapWidget(BECWidget, QWidget): self.toolbar = ModularToolBar( actions={ "motor_x": DeviceSelectionAction( - "Motor X:", DeviceComboBox(device_filter="Positioner") + "Motor X:", DeviceComboBox(device_filter=[BECDeviceFilter.POSITIONER]) ), "motor_y": DeviceSelectionAction( - "Motor Y:", DeviceComboBox(device_filter="Positioner") + "Motor Y:", DeviceComboBox(device_filter=[BECDeviceFilter.POSITIONER]) ), "connect": MaterialIconAction(icon_name="link", tooltip="Connect Motors"), "history": MaterialIconAction(icon_name="history", tooltip="Reset Trace History"), diff --git a/bec_widgets/widgets/positioner_box/positioner_box.py b/bec_widgets/widgets/positioner_box/positioner_box.py index 889d17b4..43c6ec1d 100644 --- a/bec_widgets/widgets/positioner_box/positioner_box.py +++ b/bec_widgets/widgets/positioner_box/positioner_box.py @@ -18,6 +18,7 @@ from bec_widgets.qt_utils.compact_popup import CompactPopupWidget from bec_widgets.utils import UILoader from bec_widgets.utils.bec_widget import BECWidget from bec_widgets.utils.colors import get_accent_colors, set_theme +from bec_widgets.widgets.base_classes.device_input_base import BECDeviceFilter from bec_widgets.widgets.device_line_edit.device_line_edit import DeviceLineEdit logger = bec_logger.logger @@ -97,7 +98,9 @@ class PositionerBox(BECWidget, CompactPopupWidget): self._dialog = QDialog(self) self._dialog.setWindowTitle("Positioner Selection") layout = QVBoxLayout() - line_edit = DeviceLineEdit(self, client=self.client, device_filter="Positioner") + line_edit = DeviceLineEdit( + self, client=self.client, device_filter=[BECDeviceFilter.POSITIONER] + ) line_edit.textChanged.connect(self.set_positioner) layout.addWidget(line_edit) close_button = QPushButton("Close") diff --git a/bec_widgets/widgets/scan_control/scan_group_box.py b/bec_widgets/widgets/scan_control/scan_group_box.py index b04ad737..2a369ca6 100644 --- a/bec_widgets/widgets/scan_control/scan_group_box.py +++ b/bec_widgets/widgets/scan_control/scan_group_box.py @@ -306,7 +306,7 @@ class ScanGroupBox(QGroupBox): try: # In case that the bundle size changes widget = self.layout.itemAtPosition(i, j).widget() if isinstance(widget, DeviceLineEdit) and device_object: - value = widget.get_device() + value = widget.get_current_device() else: value = WidgetIO.get_value(widget) args.append(value) diff --git a/bec_widgets/widgets/signal_combobox/__init__.py b/bec_widgets/widgets/signal_combobox/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/bec_widgets/widgets/signal_combobox/register_signal_combobox.py b/bec_widgets/widgets/signal_combobox/register_signal_combobox.py new file mode 100644 index 00000000..d48c477e --- /dev/null +++ b/bec_widgets/widgets/signal_combobox/register_signal_combobox.py @@ -0,0 +1,15 @@ +def main(): # pragma: no cover + from qtpy import PYSIDE6 + + if not PYSIDE6: + print("PYSIDE6 is not available in the environment. Cannot patch designer.") + return + from PySide6.QtDesigner import QPyDesignerCustomWidgetCollection + + from bec_widgets.widgets.signal_combobox.signal_combobox_plugin import SignalComboBoxPlugin + + QPyDesignerCustomWidgetCollection.addCustomWidget(SignalComboBoxPlugin()) + + +if __name__ == "__main__": # pragma: no cover + main() diff --git a/bec_widgets/widgets/signal_combobox/signal_combobox.py b/bec_widgets/widgets/signal_combobox/signal_combobox.py new file mode 100644 index 00000000..27459b65 --- /dev/null +++ b/bec_widgets/widgets/signal_combobox/signal_combobox.py @@ -0,0 +1,90 @@ +from qtpy.QtCore import QSize +from qtpy.QtWidgets import QComboBox, QSizePolicy + +from bec_widgets.utils.filter_io import ComboBoxFilterHandler, FilterIO +from bec_widgets.widgets.base_classes.device_signal_input_base import DeviceSignalInputBase + + +class SignalComboBox(DeviceSignalInputBase, QComboBox): + """ + Line edit widget for device input with autocomplete for device names. + + Args: + parent: Parent widget. + client: BEC client object. + config: Device input configuration. + gui_id: GUI ID. + device_filter: Device filter, name of the device class from BECDeviceFilter and BECReadoutPriority. Check DeviceInputBase for more details. + default: Default device name. + arg_name: Argument name, can be used for the other widgets which has to call some other function in bec using correct argument names. + """ + + ICON_NAME = "list_alt" + + def __init__( + self, + parent=None, + client=None, + config: DeviceSignalInputBase = None, + gui_id: str | None = None, + device: str | None = None, + signal_filter: str | list[str] | None = None, + default: str | None = None, + arg_name: str | None = None, + ): + super().__init__(client=client, config=config, gui_id=gui_id) + QComboBox.__init__(self, parent=parent) + if arg_name is not None: + self.config.arg_name = arg_name + self.arg_name = arg_name + if default is not None: + self.set_device(default) + + self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) + self.setMinimumSize(QSize(100, 0)) + signal_filter = signal_filter if not None else self.config.signal_filter + if signal_filter is not None: + self.set_filter(signal_filter) + device = device if not None else self.config.device + if device is not None: + self.set_device(device) + default = default if not None else self.config.default + if default is not None: + self.set_signal(default) + + def update_signals_from_filters(self): + """Update the filters for the combobox""" + super().update_signals_from_filters() + # pylint: disable=protected-access + if FilterIO._find_handler(self) is ComboBoxFilterHandler: + if len(self._config_signals) > 0: + self.insertItem( + len(self._hinted_signals) + len(self._normal_signals), "Config Signals" + ) + self.model().item(len(self._hinted_signals) + len(self._normal_signals)).setEnabled( + False + ) + if len(self._normal_signals) > 0: + self.insertItem(len(self._hinted_signals), "Normal Signals") + self.model().item(len(self._hinted_signals)).setEnabled(False) + if len(self._hinted_signals) > 0: + self.insertItem(0, "Hinted Signals") + self.model().item(0).setEnabled(False) + + +if __name__ == "__main__": # pragma: no cover + # pylint: disable=import-outside-toplevel + from qtpy.QtWidgets import QApplication, QVBoxLayout, QWidget + + from bec_widgets.utils.colors import set_theme + + app = QApplication([]) + set_theme("dark") + widget = QWidget() + widget.setFixedSize(200, 200) + layout = QVBoxLayout() + widget.setLayout(layout) + box = SignalComboBox(device="samx") + layout.addWidget(box) + widget.show() + app.exec_() diff --git a/bec_widgets/widgets/signal_combobox/signal_combobox.pyproject b/bec_widgets/widgets/signal_combobox/signal_combobox.pyproject new file mode 100644 index 00000000..200f7e21 --- /dev/null +++ b/bec_widgets/widgets/signal_combobox/signal_combobox.pyproject @@ -0,0 +1 @@ +{'files': ['signal_combobox.py']} \ No newline at end of file diff --git a/bec_widgets/widgets/signal_combobox/signal_combobox_plugin.py b/bec_widgets/widgets/signal_combobox/signal_combobox_plugin.py new file mode 100644 index 00000000..d7bc9085 --- /dev/null +++ b/bec_widgets/widgets/signal_combobox/signal_combobox_plugin.py @@ -0,0 +1,54 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +from qtpy.QtDesigner import QDesignerCustomWidgetInterface + +from bec_widgets.utils.bec_designer import designer_material_icon +from bec_widgets.widgets.signal_combobox.signal_combobox import SignalComboBox + +DOM_XML = """ + + + + +""" + + +class SignalComboBoxPlugin(QDesignerCustomWidgetInterface): # pragma: no cover + def __init__(self): + super().__init__() + self._form_editor = None + + def createWidget(self, parent): + t = SignalComboBox(parent) + return t + + def domXml(self): + return DOM_XML + + def group(self): + return "BEC Input Widgets" + + def icon(self): + return designer_material_icon(SignalComboBox.ICON_NAME) + + def includeFile(self): + return "signal_combobox" + + def initialize(self, form_editor): + self._form_editor = form_editor + + def isContainer(self): + return False + + def isInitialized(self): + return self._form_editor is not None + + def name(self): + return "SignalComboBox" + + def toolTip(self): + return "" + + def whatsThis(self): + return self.toolTip() diff --git a/bec_widgets/widgets/signal_line_edit/__init__.py b/bec_widgets/widgets/signal_line_edit/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/bec_widgets/widgets/signal_line_edit/register_signal_line_edit.py b/bec_widgets/widgets/signal_line_edit/register_signal_line_edit.py new file mode 100644 index 00000000..3824cbbf --- /dev/null +++ b/bec_widgets/widgets/signal_line_edit/register_signal_line_edit.py @@ -0,0 +1,15 @@ +def main(): # pragma: no cover + from qtpy import PYSIDE6 + + if not PYSIDE6: + print("PYSIDE6 is not available in the environment. Cannot patch designer.") + return + from PySide6.QtDesigner import QPyDesignerCustomWidgetCollection + + from bec_widgets.widgets.signal_line_edit.signal_line_edit_plugin import SignalLineEditPlugin + + QPyDesignerCustomWidgetCollection.addCustomWidget(SignalLineEditPlugin()) + + +if __name__ == "__main__": # pragma: no cover + main() diff --git a/bec_widgets/widgets/signal_line_edit/signal_line_edit.py b/bec_widgets/widgets/signal_line_edit/signal_line_edit.py new file mode 100644 index 00000000..e2441ab9 --- /dev/null +++ b/bec_widgets/widgets/signal_line_edit/signal_line_edit.py @@ -0,0 +1,114 @@ +from qtpy.QtCore import QSize, Slot +from qtpy.QtGui import QPainter, QPaintEvent, QPen +from qtpy.QtWidgets import QCompleter, QLineEdit, QSizePolicy + +from bec_widgets.utils.colors import get_accent_colors +from bec_widgets.widgets.base_classes.device_signal_input_base import DeviceSignalInputBase + + +class SignalLineEdit(DeviceSignalInputBase, QLineEdit): + """ + Line edit widget for device input with autocomplete for device names. + + Args: + parent: Parent widget. + client: BEC client object. + config: Device input configuration. + gui_id: GUI ID. + device_filter: Device filter, name of the device class from BECDeviceFilter and BECReadoutPriority. Check DeviceInputBase for more details. + default: Default device name. + arg_name: Argument name, can be used for the other widgets which has to call some other function in bec using correct argument names. + """ + + ICON_NAME = "vital_signs" + + def __init__( + self, + parent=None, + client=None, + config: DeviceSignalInputBase = None, + gui_id: str | None = None, + device: str | None = None, + signal_filter: str | list[str] | None = None, + default: str | None = None, + arg_name: str | None = None, + ): + super().__init__(client=client, config=config, gui_id=gui_id) + QLineEdit.__init__(self, parent=parent) + self._is_valid_input = False + self._accent_colors = get_accent_colors() + self.completer = QCompleter(self) + self.setCompleter(self.completer) + if arg_name is not None: + self.config.arg_name = arg_name + self.arg_name = arg_name + if default is not None: + self.set_device(default) + + self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) + self.setMinimumSize(QSize(100, 0)) + signal_filter = signal_filter if not None else self.config.signal_filter + if signal_filter is not None: + self.set_filter(signal_filter) + device = device if not None else self.config.device + if device is not None: + self.set_device(device) + default = default if not None else self.config.default + if default is not None: + self.set_signal(default) + self.textChanged.connect(self.check_validity) + + def get_current_device(self) -> object: + """ + Get the current device object based on the current value. + + Returns: + object: Device object, can be device of type Device, Positioner, Signal or ComputedSignal. + """ + dev_name = self.text() + return self.get_device_object(dev_name) + + def paintEvent(self, event: QPaintEvent) -> None: + """Extend the paint event to set the border color based on the validity of the input. + + Args: + event (PySide6.QtGui.QPaintEvent) : Paint event. + """ + super().paintEvent(event) + painter = QPainter(self) + pen = QPen() + pen.setWidth(2) + + if self._is_valid_input is False and self.isEnabled() is True: + pen.setColor(self._accent_colors.emergency) + painter.setPen(pen) + painter.drawRect(self.rect().adjusted(1, 1, -1, -1)) + + @Slot(str) + def check_validity(self, input_text: str) -> None: + """ + Check if the current value is a valid device name. + """ + # i + if self.validate_signal(input_text) is True: + self._is_valid_input = True + else: + self._is_valid_input = False + self.update() + + +if __name__ == "__main__": # pragma: no cover + # pylint: disable=import-outside-toplevel + from qtpy.QtWidgets import QApplication, QVBoxLayout, QWidget + + from bec_widgets.utils.colors import set_theme + + app = QApplication([]) + set_theme("dark") + widget = QWidget() + widget.setFixedSize(200, 200) + layout = QVBoxLayout() + widget.setLayout(layout) + layout.addWidget(SignalLineEdit(device="samx")) + widget.show() + app.exec_() diff --git a/bec_widgets/widgets/signal_line_edit/signal_line_edit.pyproject b/bec_widgets/widgets/signal_line_edit/signal_line_edit.pyproject new file mode 100644 index 00000000..3cab6643 --- /dev/null +++ b/bec_widgets/widgets/signal_line_edit/signal_line_edit.pyproject @@ -0,0 +1 @@ +{'files': ['signal_line_edit.py']} \ No newline at end of file diff --git a/bec_widgets/widgets/signal_line_edit/signal_line_edit_plugin.py b/bec_widgets/widgets/signal_line_edit/signal_line_edit_plugin.py new file mode 100644 index 00000000..517f4e1b --- /dev/null +++ b/bec_widgets/widgets/signal_line_edit/signal_line_edit_plugin.py @@ -0,0 +1,54 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +from qtpy.QtDesigner import QDesignerCustomWidgetInterface + +from bec_widgets.utils.bec_designer import designer_material_icon +from bec_widgets.widgets.signal_line_edit.signal_line_edit import SignalLineEdit + +DOM_XML = """ + + + + +""" + + +class SignalLineEditPlugin(QDesignerCustomWidgetInterface): # pragma: no cover + def __init__(self): + super().__init__() + self._form_editor = None + + def createWidget(self, parent): + t = SignalLineEdit(parent) + return t + + def domXml(self): + return DOM_XML + + def group(self): + return "BEC Input Widgets" + + def icon(self): + return designer_material_icon(SignalLineEdit.ICON_NAME) + + def includeFile(self): + return "signal_line_edit" + + def initialize(self, form_editor): + self._form_editor = form_editor + + def isContainer(self): + return False + + def isInitialized(self): + return self._form_editor is not None + + def name(self): + return "SignalLineEdit" + + def toolTip(self): + return "" + + def whatsThis(self): + return self.toolTip() diff --git a/docs/assets/widget_screenshots/device_inputs.png b/docs/assets/widget_screenshots/device_inputs.png index d66321e2e2e34e48f957dd902b47de02d54814d1..64469d871f296ff543ab0772598d8bf9a8d2ecee 100644 GIT binary patch literal 32455 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 F{|`F2l*Rx6 literal 4608 zcmeHKcT`hbvkx­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 Ct~R~^ literal 0 HcmV?d00001 diff --git a/docs/user/widgets/device_input/device_input.md b/docs/user/widgets/device_input/device_input.md index 0c159c9c..e18ef14d 100644 --- a/docs/user/widgets/device_input/device_input.md +++ b/docs/user/widgets/device_input/device_input.md @@ -13,9 +13,11 @@ The `DeviceLineEdit` widget provides a line edit interface with autocomplete fun The `DeviceComboBox` widget offers a dropdown interface for device selection, providing a more visual way to browse through available devices. ## Key Features: -- **Device Filtering**: Both widgets allow users to filter devices by their class names, ensuring that only relevant devices are shown. +- **Device Filtering**: Both widgets allow users to filter devices by device type and readout priority, ensuring that only relevant devices are shown. - **Default Device Setting**: Users can set a default device to be pre-selected when the widget is initialized. +- **Set Device Selection**: Both widgets allow users to set the available devices to be displayed independent of the applied filters. - **Real-Time Autocomplete (LineEdit)**: The `DeviceLineEdit` widget supports real-time autocomplete, helping users find devices faster. +- **Real-Time Input Validation (LineEdit)**: User input is validated in real-time with a red border around the `DeviceLineEdit` indicating an invalid input. - **Dropdown Selection (ComboBox)**: The `DeviceComboBox` widget displays devices in a dropdown list, making selection straightforward. - **QtDesigner Integration**: Both widgets can be added as custom widgets in `QtDesigner` or instantiated directly in code. @@ -28,11 +30,15 @@ Both `DeviceLineEdit` and `DeviceComboBox` can be integrated within a GUI applic ## Example 1 - Creating a DeviceLineEdit in Code -In this example, we demonstrate how to create a `DeviceLineEdit` widget in code and customize its behavior. +In this example, we demonstrate how to create a `DeviceLineEdit` widget in code and customize its behavior. +We filter down to Positioners with readout_priority Baseline. +Note, if we do not specify a device_filter or readout_filter, all enabled devices will be included. ```python from qtpy.QtWidgets import QApplication, QVBoxLayout, QWidget -from bec_widgets.widgets.device_line_edit import DeviceLineEdit +from bec_widgets.widgets.device_line_edit.device_line_edit import DeviceLineEdit +from bec_lib.device import ReadoutPriority +from bec_widgets.widgets.base_classes.device_input_base import BECDeviceFilter class MyGui(QWidget): def __init__(self): @@ -40,7 +46,7 @@ class MyGui(QWidget): self.setLayout(QVBoxLayout(self)) # Initialize the layout for the widget # Create and add the DeviceLineEdit to the layout - self.device_line_edit = DeviceLineEdit(device_filter="Motor") + self.device_line_edit = DeviceLineEdit(device_filter=BECDeviceFilter.POSITIONER, readout_priority_filter=ReadoutPriority.BASELINE) self.layout().addWidget(self.device_line_edit) # Example of how this custom GUI might be used: @@ -56,7 +62,9 @@ Similarly, here is an example of creating a `DeviceComboBox` widget in code and ```python from qtpy.QtWidgets import QApplication, QVBoxLayout, QWidget -from bec_widgets.widgets.device_combo_box import DeviceComboBox +from bec_widgets.widgets.device_combobox.device_combobox import DeviceComboBox +from bec_lib.device import ReadoutPriority +from bec_widgets.widgets.base_classes.device_input_base import BECDeviceFilter class MyGui(QWidget): def __init__(self): @@ -64,8 +72,8 @@ class MyGui(QWidget): self.setLayout(QVBoxLayout(self)) # Initialize the layout for the widget # Create and add the DeviceComboBox to the layout - self.device_combo_box = DeviceComboBox(device_filter="Motor") - self.layout().addWidget(self.device_combo_box) + self.device_combobox = DeviceComboBox(device_filter=BECDeviceFilter.POSITIONER, readout_priority_filter=ReadoutPriority.BASELINE) + self.layout().addWidget(self.device_combobox) # Example of how this custom GUI might be used: app = QApplication([]) @@ -80,11 +88,24 @@ Both `DeviceLineEdit` and `DeviceComboBox` allow you to set a default device tha ```python # Set default device for DeviceLineEdit -self.device_line_edit.set_default_device("motor1") +self.device_line_edit.set_device("motor1") # Set default device for DeviceComboBox -self.device_combo_box.set_default_device("motor2") +self.device_combo_box.set_device("motor2") + +# Set the available devices to be displayed independent of the applied filters +self.device_combo_box.set_available_devices(["motor1", "motor2", "motor3"]) ``` +```` +````{tab} BEC Designer +Both widgets are also available as plugins for the BEC Designer. We have included Qt properties for both widgets, allowing customization of filtering and default device settings directly from the designer. In addition to the common signals and slots for `DeviceLineEdit` and `DeviceComboBox`, the following slots are available: +- `set_device(str)` to set the default device +- `update_devices()` to refresh the devices list + +The following Qt properties are also included: +```{figure} ./QProperties_DeviceInput.png +``` + ```` ````{tab} API - ComboBox diff --git a/docs/user/widgets/signal_input/signal_input.md b/docs/user/widgets/signal_input/signal_input.md new file mode 100644 index 00000000..70e9dab2 --- /dev/null +++ b/docs/user/widgets/signal_input/signal_input.md @@ -0,0 +1,114 @@ +(user.widgets.signal_input)= + +# Signal Input Widgets + +````{tab} Overview +The `Signal Input Widgets` consist of two primary widgets: `SignalLineEdit` and `SignalComboBox`. Both widgets are designed to facilitate the selection of the available signals for a selected device within the current BEC session. These widgets allow users to filter, search, and select signals dynamically. The widgets can either be integrated into a GUI through direct code instantiation or by using `QtDesigner`. + +## SignalLineEdit +The `SignalLineEdit` widget provides a line edit interface with autocomplete functionality for the available of signals associated with the selected device. This widget is ideal for users who prefer to type in the signal name directly. If no device is selected, the autocomplete will be empty. In addition, the widget will display a red border around the line edit if the input signal is invalid. + +## SignalComboBox +The `SignalComboBox` widget offers a dropdown interface for choosing a signal from the available signals of a device. It will further categorise the signals according to its `kind`: `hinted`, `normal` and `config`. For more information about `kind`, please check the [ophyd documentation](https://nsls-ii.github.io/ophyd/signals.html#kind). This widget is ideal for users who prefer to select signals from a list. + +## Key Features: +- **Signal Filtering**: Both widgets allow users to filter devices by signal types(`kind`). No selected filter will show all signals. +- **Real-Time Autocomplete (LineEdit)**: The `SignalLineEdit` widget supports real-time autocomplete, helping users find devices faster. +- **Real-Time Input Validation (LineEdit)**: User input is validated in real-time with a red border around the `SignalLineEdit` indicating an invalid input. +- **Dropdown Selection (SignalComboBox)**: The `SignalComboBox` widget displays the sorted signals of the device +- **QtDesigner Integration**: Both widgets can be added as custom widgets in `QtDesigner` or instantiated directly in code. + +```` + +````{tab} Examples + +Both `SignalLineEdit` and `SignalComboBox` can be integrated within a GUI application through direct code instantiation or by using `QtDesigner`. Below are examples demonstrating how to create and use these widgets. + + +## Example 1 - Creating a SignalLineEdit in Code + +In this example, we demonstrate how to create a `SignalLineEdit` widget in code and customize its behavior. +We will select `samx`, which is a motor in the BEC simulation device config, and filter the signals to `normal` and `hinted`. +Note, not specifying signal_filter will include all signals. + +```python +from qtpy.QtWidgets import QApplication, QVBoxLayout, QWidget +from bec_widgets.widgets.signal_line_edit.signal_line_edit import SignalLineEdit +from bec_widgets.widgets.base_classes.device_signal_input_base import BECSignalFilter + +class MyGui(QWidget): + def __init__(self): + super().__init__() + self.setLayout(QVBoxLayout(self)) # Initialize the layout for the widget + + # Create and add the DeviceLineEdit to the layout + self.signal_line_edit = SignalLineEdit(device="samx", signal_filter=[BECSignalFilter.NORMAL, BECSignalFilter.HINTED]) + self.layout().addWidget(self.signal_line_edit) + +# Example of how this custom GUI might be used: +app = QApplication([]) +my_gui = MyGui() +my_gui.show() +app.exec_() +``` + +## Example 2 - Creating a DeviceComboBox in Code + +Similarly, here is an example of creating a `DeviceComboBox` widget in code and customizing its behavior. + +```python +from qtpy.QtWidgets import QApplication, QVBoxLayout, QWidget +from bec_widgets.widgets.signal_combobox.signal_combobox import SignalComboBox +from bec_widgets.widgets.base_classes.device_signal_input_base import BECSignalFilter + +class MyGui(QWidget): + def __init__(self): + super().__init__() + self.setLayout(QVBoxLayout(self)) # Initialize the layout for the widget + + # Create and add the DeviceLineEdit to the layout + self.signal_combobox = SignalComboBox(device="samx", signal_filter=[BECSignalFilter.NORMAL, BECSignalFilter.HINTED]) + self.layout().addWidget(self.signal_combobox) + +# Example of how this custom GUI might be used: +app = QApplication([]) +my_gui = MyGui() +my_gui.show() +app.exec_() +``` + +## Example 3 - Setting Default Device + +Both `SignalLineEdit` and `SignalComboBox` allow you to set a default device that will be selected when the widget is initialized. + +```python +# Set default device for DeviceLineEdit +self.signal_line_edit.set_device("motor1") + +# Set default device for DeviceComboBox +self.signal_combobox.set_device("motor2") +``` +```` +````{tab} BEC Designer +Both widgets are also available as plugins for the BEC Designer. We have included Qt properties for both widgets, allowing customization of filtering and default device settings directly from the designer. In addition to the common signals and slots for `SignalLineEdit` and `SignalComboBox`, the following slots are available: +- `set_device(str)` to set the default device +- `set_signal(str)` to set the default signal +- `update_signals_from_filters()` to refresh the devices list based on the current filters + +The following Qt properties are also included: +```{figure} ./signal_input_qproperties.png +``` + +```` + +````{tab} API - ComboBox +```{eval-rst} +.. include:: /api_reference/_autosummary/bec_widgets.cli.client.SignalComboBox.rst +``` +```` + +````{tab} API - LineEdit +```{eval-rst} +.. include:: /api_reference/_autosummary/bec_widgets.cli.client.SignalLineEdit.rst +``` +```` diff --git a/docs/user/widgets/signal_input/signal_input_qproperties.png b/docs/user/widgets/signal_input/signal_input_qproperties.png new file mode 100644 index 0000000000000000000000000000000000000000..ae86d8e7a8022e0e0c93c951be27503c94fc2248 GIT binary patch literal 34607 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 None: - """ - Setup fake value for device readout - Args: - fake_value(float): Desired fake value - """ - self.signals[self.name]["value"] = fake_value - - def describe(self) -> dict: - """ - Get the description of the device - Returns: - dict: Description of the device - """ - return self.description - - -class FakePositioner(FakeDevice): - def __init__( - self, - name, - enabled=True, - limits=None, - read_value=1.0, - readout_priority=ReadoutPriority.MONITORED, - ): - super().__init__(name, enabled, readout_priority) - self.limits = limits if limits is not None else [0, 0] - self.read_value = read_value - self.name = name - - @property - def precision(self): - return 3 - - def set_read_value(self, value): - self.read_value = value - - def read(self): - return { - self.name: {"value": self.read_value}, - f"{self.name}_setpoint": {"value": self.read_value}, - f"{self.name}_motor_is_moving": {"value": 0}, - } - - def set_limits(self, limits): - self.limits = limits - - def move(self, value, relative=False): - """Simulates moving the device to a new position.""" - if relative: - self.read_value += value - else: - self.read_value = value - # Respect the limits - self.read_value = max(min(self.read_value, self.limits[1]), self.limits[0]) - - @property - def readback(self): - return MagicMock(get=MagicMock(return_value=self.read_value)) - - -class Positioner(FakePositioner): - """just placeholder for testing embedded isinstance check in DeviceCombobox""" - - def __init__(self, name="test", limits=None, read_value=1.0): - super().__init__(name, limits, read_value) - - -class Device(FakeDevice): - """just placeholder for testing embedded isinstance check in DeviceCombobox""" - - def __init__(self, name, enabled=True): - super().__init__(name, enabled) - - -class DMMock: - def __init__(self): - self.devices = DeviceContainer() - - def add_devives(self, devices: list): - for device in devices: - self.devices[device.name] = device - - -DEVICES = [ - FakePositioner("samx", limits=[-10, 10], read_value=2.0), - FakePositioner("samy", limits=[-5, 5], read_value=3.0), - FakePositioner("samz", limits=[-8, 8], read_value=4.0), - FakePositioner("aptrx", limits=None, read_value=4.0), - FakePositioner("aptry", limits=None, read_value=5.0), - FakeDevice("gauss_bpm"), - FakeDevice("gauss_adc1"), - FakeDevice("gauss_adc2"), - FakeDevice("gauss_adc3"), - FakeDevice("bpm4i"), - FakeDevice("bpm3a"), - FakeDevice("bpm3i"), - FakeDevice("eiger"), - FakeDevice("waveform1d"), - FakeDevice("async_device", readout_priority=ReadoutPriority.ASYNC), - Positioner("test", limits=[-10, 10], read_value=2.0), - Device("test_device"), -] +from bec_widgets.test_utils.client_mocks import DEVICES, DMMock, FakePositioner, Positioner def fake_redis_server(host, port): diff --git a/tests/unit_tests/test_bec_image_widget.py b/tests/unit_tests/test_bec_image_widget.py index eff7c587..194c42e1 100644 --- a/tests/unit_tests/test_bec_image_widget.py +++ b/tests/unit_tests/test_bec_image_widget.py @@ -3,6 +3,7 @@ from unittest.mock import MagicMock, patch import pyqtgraph as pg import pytest +from bec_widgets.widgets.base_classes.device_input_base import BECDeviceFilter from bec_widgets.widgets.image.image_widget import BECImageWidget from .client_mocks import mocked_client @@ -11,7 +12,6 @@ from .client_mocks import mocked_client @pytest.fixture def image_widget(qtbot, mocked_client): widget = BECImageWidget(client=mocked_client()) - widget.toolbar.widgets["monitor"].device_combobox.set_device_filter("FakeDevice") qtbot.addWidget(widget) qtbot.waitExposed(widget) yield widget @@ -32,7 +32,8 @@ def test_image_widget_init(image_widget): assert image_widget._image is not None assert ( - image_widget.toolbar.widgets["monitor"].device_combobox.config.device_filter == "FakeDevice" + BECDeviceFilter.DEVICE + in image_widget.toolbar.widgets["monitor"].device_combobox.config.device_filter ) assert image_widget.toolbar.widgets["drag_mode"].action.isChecked() == True assert image_widget.toolbar.widgets["rectangle_mode"].action.isChecked() == False diff --git a/tests/unit_tests/test_client_utils.py b/tests/unit_tests/test_client_utils.py index 10ad3c2c..29999887 100644 --- a/tests/unit_tests/test_client_utils.py +++ b/tests/unit_tests/test_client_utils.py @@ -4,8 +4,7 @@ import pytest from bec_widgets.cli.client import BECFigure from bec_widgets.cli.client_utils import BECGuiClientMixin, _start_plot_process - -from .client_mocks import FakeDevice +from bec_widgets.test_utils.client_mocks import FakeDevice @pytest.fixture diff --git a/tests/unit_tests/test_device_input_base.py b/tests/unit_tests/test_device_input_base.py index 70ccfc69..a8652e01 100644 --- a/tests/unit_tests/test_device_input_base.py +++ b/tests/unit_tests/test_device_input_base.py @@ -1,13 +1,21 @@ -import pytest -from qtpy.QtWidgets import QWidget +from unittest import mock -from bec_widgets.widgets.base_classes.device_input_base import DeviceInputBase +import pytest +from bec_lib.device import ReadoutPriority +from qtpy.QtWidgets import QWidget +from typeguard import TypeCheckError + +from bec_widgets.test_utils.client_mocks import FakePositioner +from bec_widgets.widgets.base_classes.device_input_base import BECDeviceFilter, DeviceInputBase from .client_mocks import mocked_client +from .conftest import create_widget # DeviceInputBase is meant to be mixed in a QWidget class DeviceInputWidget(DeviceInputBase, QWidget): + """Thin wrapper around DeviceInputBase to make it a QWidget""" + def __init__(self, parent=None, client=None, config=None, gui_id=None): super().__init__(client=client, config=config, gui_id=gui_id) QWidget.__init__(self, parent=parent) @@ -15,13 +23,15 @@ class DeviceInputWidget(DeviceInputBase, QWidget): @pytest.fixture def device_input_base(qtbot, mocked_client): - widget = DeviceInputWidget(client=mocked_client) - qtbot.addWidget(widget) - qtbot.waitExposed(widget) - yield widget + """Fixture with mocked FilterIO and WidgetIO""" + with mock.patch("bec_widgets.utils.filter_io.FilterIO.set_selection"): + with mock.patch("bec_widgets.utils.widget_io.WidgetIO.set_value"): + widget = create_widget(qtbot=qtbot, widget=DeviceInputWidget, client=mocked_client) + yield widget def test_device_input_base_init(device_input_base): + """Test init""" assert device_input_base is not None assert device_input_base.client is not None assert isinstance(device_input_base, DeviceInputBase) @@ -32,45 +42,95 @@ def test_device_input_base_init(device_input_base): def test_device_input_base_init_with_config(mocked_client): + """Test init with Config""" config = { "widget_class": "DeviceInputWidget", "gui_id": "test_gui_id", - "device_filter": "FakePositioner", + "device_filter": [BECDeviceFilter.POSITIONER], "default": "samx", } widget = DeviceInputWidget(client=mocked_client, config=config) assert widget.config.gui_id == "test_gui_id" - assert widget.config.device_filter == "FakePositioner" + assert widget.config.device_filter == [BECDeviceFilter.POSITIONER] assert widget.config.default == "samx" def test_device_input_base_set_device_filter(device_input_base): - device_input_base.set_device_filter("FakePositioner") - assert device_input_base.config.device_filter == "FakePositioner" + """Test device filter setter.""" + device_input_base.set_device_filter(BECDeviceFilter.POSITIONER) + assert device_input_base.config.device_filter == [BECDeviceFilter.POSITIONER] def test_device_input_base_set_device_filter_error(device_input_base): + """Test set_device_filter with Noneexisting class""" with pytest.raises(ValueError) as excinfo: device_input_base.set_device_filter("NonExistingClass") assert "Device filter NonExistingClass is not in the device list." in str(excinfo.value) def test_device_input_base_set_default_device(device_input_base): - device_input_base.set_default_device("samx") + """Test setting the default device. Also tests the update_devices method.""" + with pytest.raises(ValueError) as excinfo: + device_input_base.set_device("samx") + assert "Device samx is not in filtered selection." in str(excinfo.value) + device_input_base.set_device_filter(BECDeviceFilter.POSITIONER) + device_input_base.set_readout_priority_filter(ReadoutPriority.MONITORED) + device_input_base.set_device("samx") assert device_input_base.config.default == "samx" -def test_device_input_base_set_default_device_error(device_input_base): - with pytest.raises(ValueError) as excinfo: - device_input_base.set_default_device("NonExistingDevice") - assert "Default device NonExistingDevice is not in the device list." in str(excinfo.value) - - -def test_device_input_base_get_device_list(device_input_base): - devices = device_input_base.get_device_list("FakePositioner") - assert devices == ["samx", "samy", "samz", "aptrx", "aptry"] - - def test_device_input_base_get_filters(device_input_base): + """Test getting the available filters.""" filters = device_input_base.get_available_filters() - assert filters == {"FakePositioner", "FakeDevice", "Positioner", "Device"} + selection = [ + BECDeviceFilter.POSITIONER, + BECDeviceFilter.DEVICE, + BECDeviceFilter.COMPUTED_SIGNAL, + BECDeviceFilter.SIGNAL, + ] + [ + ReadoutPriority.MONITORED, + ReadoutPriority.BASELINE, + ReadoutPriority.ASYNC, + ReadoutPriority.ON_REQUEST, + ] + assert [entry for entry in filters if entry in selection] + + +def test_device_input_base_properties(device_input_base): + """Test setting the properties of the device input base.""" + assert device_input_base.device_filter == [] + device_input_base.include_device = True + assert device_input_base.device_filter == [BECDeviceFilter.DEVICE] + device_input_base.include_positioner = True + assert device_input_base.device_filter == [BECDeviceFilter.DEVICE, BECDeviceFilter.POSITIONER] + device_input_base.include_computed_signal = True + assert device_input_base.device_filter == [ + BECDeviceFilter.DEVICE, + BECDeviceFilter.POSITIONER, + BECDeviceFilter.COMPUTED_SIGNAL, + ] + device_input_base.include_signal = True + assert device_input_base.device_filter == [ + BECDeviceFilter.DEVICE, + BECDeviceFilter.POSITIONER, + BECDeviceFilter.COMPUTED_SIGNAL, + BECDeviceFilter.SIGNAL, + ] + assert device_input_base.readout_filter == [] + device_input_base.readout_async = True + assert device_input_base.readout_filter == [ReadoutPriority.ASYNC] + device_input_base.readout_baseline = True + assert device_input_base.readout_filter == [ReadoutPriority.ASYNC, ReadoutPriority.BASELINE] + device_input_base.readout_monitored = True + assert device_input_base.readout_filter == [ + ReadoutPriority.ASYNC, + ReadoutPriority.BASELINE, + ReadoutPriority.MONITORED, + ] + device_input_base.readout_on_request = True + assert device_input_base.readout_filter == [ + ReadoutPriority.ASYNC, + ReadoutPriority.BASELINE, + ReadoutPriority.MONITORED, + ReadoutPriority.ON_REQUEST, + ] diff --git a/tests/unit_tests/test_device_input_widgets.py b/tests/unit_tests/test_device_input_widgets.py index 3b7a0f00..59faaaf5 100644 --- a/tests/unit_tests/test_device_input_widgets.py +++ b/tests/unit_tests/test_device_input_widgets.py @@ -1,5 +1,7 @@ import pytest +from bec_lib.device import ReadoutPriority +from bec_widgets.widgets.base_classes.device_input_base import BECDeviceFilter from bec_widgets.widgets.device_combobox.device_combobox import DeviceComboBox from bec_widgets.widgets.device_line_edit.device_line_edit import DeviceLineEdit @@ -19,7 +21,7 @@ def device_input_combobox_with_config(qtbot, mocked_client): config = { "widget_class": "DeviceComboBox", "gui_id": "test_gui_id", - "device_filter": "FakePositioner", + "device_filter": [BECDeviceFilter.POSITIONER], "default": "samx", "arg_name": "test_arg_name", } @@ -34,7 +36,7 @@ def device_input_combobox_with_kwargs(qtbot, mocked_client): widget = DeviceComboBox( client=mocked_client, gui_id="test_gui_id", - device_filter="FakePositioner", + device_filter=[BECDeviceFilter.POSITIONER], default="samx", arg_name="test_arg_name", ) @@ -48,7 +50,6 @@ def test_device_input_combobox_init(device_input_combobox): assert device_input_combobox.client is not None assert isinstance(device_input_combobox, DeviceComboBox) assert device_input_combobox.config.widget_class == "DeviceComboBox" - assert device_input_combobox.config.device_filter is None assert device_input_combobox.config.default is None assert device_input_combobox.devices == [ "samx", @@ -73,14 +74,14 @@ def test_device_input_combobox_init(device_input_combobox): def test_device_input_combobox_init_with_config(device_input_combobox_with_config): assert device_input_combobox_with_config.config.gui_id == "test_gui_id" - assert device_input_combobox_with_config.config.device_filter == "FakePositioner" + assert device_input_combobox_with_config.config.device_filter == [BECDeviceFilter.POSITIONER] assert device_input_combobox_with_config.config.default == "samx" assert device_input_combobox_with_config.config.arg_name == "test_arg_name" def test_device_input_combobox_init_with_kwargs(device_input_combobox_with_kwargs): assert device_input_combobox_with_kwargs.config.gui_id == "test_gui_id" - assert device_input_combobox_with_kwargs.config.device_filter == "FakePositioner" + assert device_input_combobox_with_kwargs.config.device_filter == [BECDeviceFilter.POSITIONER] assert device_input_combobox_with_kwargs.config.default == "samx" assert device_input_combobox_with_kwargs.config.arg_name == "test_arg_name" @@ -88,7 +89,7 @@ def test_device_input_combobox_init_with_kwargs(device_input_combobox_with_kwarg def test_get_device_from_input_combobox_init(device_input_combobox): device_input_combobox.setCurrentIndex(0) device_text = device_input_combobox.currentText() - current_device = device_input_combobox.get_device() + current_device = device_input_combobox.get_current_device() assert current_device.name == device_text @@ -106,7 +107,7 @@ def device_input_line_edit_with_config(qtbot, mocked_client): config = { "widget_class": "DeviceLineEdit", "gui_id": "test_gui_id", - "device_filter": "FakePositioner", + "device_filter": [BECDeviceFilter.POSITIONER], "default": "samx", "arg_name": "test_arg_name", } @@ -121,7 +122,7 @@ def device_input_line_edit_with_kwargs(qtbot, mocked_client): widget = DeviceLineEdit( client=mocked_client, gui_id="test_gui_id", - device_filter="FakePositioner", + device_filter=[BECDeviceFilter.POSITIONER], default="samx", arg_name="test_arg_name", ) @@ -135,7 +136,8 @@ def test_device_input_line_edit_init(device_input_line_edit): assert device_input_line_edit.client is not None assert isinstance(device_input_line_edit, DeviceLineEdit) assert device_input_line_edit.config.widget_class == "DeviceLineEdit" - assert device_input_line_edit.config.device_filter is None + assert device_input_line_edit.config.device_filter == [] + assert device_input_line_edit.config.readout_filter == [] assert device_input_line_edit.config.default is None assert device_input_line_edit.devices == [ "samx", @@ -160,14 +162,14 @@ def test_device_input_line_edit_init(device_input_line_edit): def test_device_input_line_edit_init_with_config(device_input_line_edit_with_config): assert device_input_line_edit_with_config.config.gui_id == "test_gui_id" - assert device_input_line_edit_with_config.config.device_filter == "FakePositioner" + assert device_input_line_edit_with_config.config.device_filter == [BECDeviceFilter.POSITIONER] assert device_input_line_edit_with_config.config.default == "samx" assert device_input_line_edit_with_config.config.arg_name == "test_arg_name" def test_device_input_line_edit_init_with_kwargs(device_input_line_edit_with_kwargs): assert device_input_line_edit_with_kwargs.config.gui_id == "test_gui_id" - assert device_input_line_edit_with_kwargs.config.device_filter == "FakePositioner" + assert device_input_line_edit_with_kwargs.config.device_filter == [BECDeviceFilter.POSITIONER] assert device_input_line_edit_with_kwargs.config.default == "samx" assert device_input_line_edit_with_kwargs.config.arg_name == "test_arg_name" @@ -175,6 +177,6 @@ def test_device_input_line_edit_init_with_kwargs(device_input_line_edit_with_kwa def test_get_device_from_input_line_edit_init(device_input_line_edit): device_input_line_edit.setText("samx") device_text = device_input_line_edit.text() - current_device = device_input_line_edit.get_device() + current_device = device_input_line_edit.get_current_device() assert current_device.name == device_text diff --git a/tests/unit_tests/test_device_signal_input.py b/tests/unit_tests/test_device_signal_input.py new file mode 100644 index 00000000..ce404f8f --- /dev/null +++ b/tests/unit_tests/test_device_signal_input.py @@ -0,0 +1,103 @@ +from unittest import mock + +import pytest +from qtpy.QtWidgets import QWidget + +from bec_widgets.widgets.base_classes.device_signal_input_base import ( + BECSignalFilter, + DeviceSignalInputBase, +) +from bec_widgets.widgets.signal_combobox.signal_combobox import SignalComboBox +from bec_widgets.widgets.signal_line_edit.signal_line_edit import SignalLineEdit + +from .client_mocks import mocked_client +from .conftest import create_widget + + +class DeviceInputWidget(DeviceSignalInputBase, QWidget): + """Thin wrapper around DeviceInputBase to make it a QWidget""" + + def __init__(self, parent=None, client=None, config=None, gui_id=None): + super().__init__(client=client, config=config, gui_id=gui_id) + QWidget.__init__(self, parent=parent) + + +@pytest.fixture +def device_signal_base(qtbot, mocked_client): + """Fixture with mocked FilterIO and WidgetIO""" + with mock.patch("bec_widgets.utils.filter_io.FilterIO.set_selection"): + with mock.patch("bec_widgets.utils.widget_io.WidgetIO.set_value"): + widget = create_widget(qtbot=qtbot, widget=DeviceInputWidget, client=mocked_client) + yield widget + + +@pytest.fixture +def device_signal_combobox(qtbot, mocked_client): + """Fixture with mocked FilterIO and WidgetIO""" + widget = create_widget(qtbot=qtbot, widget=SignalComboBox, client=mocked_client) + yield widget + + +@pytest.fixture +def device_signal_line_edit(qtbot, mocked_client): + """Fixture with mocked FilterIO and WidgetIO""" + widget = create_widget(qtbot=qtbot, widget=SignalLineEdit, client=mocked_client) + yield widget + + +def test_device_signal_base_init(device_signal_base): + """Test if the DeviceSignalInputBase is initialized correctly""" + assert device_signal_base._device is None + assert device_signal_base._signal_filter == [] + assert device_signal_base._signals == [] + assert device_signal_base._hinted_signals == [] + assert device_signal_base._normal_signals == [] + assert device_signal_base._config_signals == [] + + +def test_device_signal_qproperties(device_signal_base): + """Test if the DeviceSignalInputBase has the correct QProperties""" + device_signal_base.include_config_signals = True + assert device_signal_base._signal_filter == [BECSignalFilter.CONFIG] + device_signal_base.include_normal_signals = True + assert device_signal_base._signal_filter == [BECSignalFilter.CONFIG, BECSignalFilter.NORMAL] + device_signal_base.include_hinted_signals = True + assert device_signal_base._signal_filter == [ + BECSignalFilter.CONFIG, + BECSignalFilter.NORMAL, + BECSignalFilter.HINTED, + ] + + +def test_device_signal_set_device(device_signal_base): + """Test if the set_device method works correctly""" + device_signal_base.include_hinted_signals = True + device_signal_base.set_device("samx") + assert device_signal_base.device == "samx" + assert device_signal_base.signals == ["readback"] + device_signal_base.include_normal_signals = True + assert device_signal_base.signals == ["readback", "setpoint"] + device_signal_base.include_config_signals = True + assert device_signal_base.signals == ["readback", "setpoint", "velocity"] + + +def test_signal_combobox(device_signal_combobox): + """Test the signal_combobox""" + device_signal_combobox._signals == [] + device_signal_combobox.include_normal_signals = True + device_signal_combobox.include_hinted_signals = True + device_signal_combobox.include_config_signals = True + device_signal_combobox.signals == [] + device_signal_combobox.set_device("samx") + device_signal_combobox.signals == ["readback", "setpoint", "velocity"] + + +def test_signal_lineeidt(device_signal_line_edit): + """Test the signal_combobox""" + device_signal_line_edit._signals == [] + device_signal_line_edit.include_normal_signals = True + device_signal_line_edit.include_hinted_signals = True + device_signal_line_edit.include_config_signals = True + device_signal_line_edit.signals == [] + device_signal_line_edit.set_device("samx") + device_signal_line_edit.signals == ["readback", "setpoint", "velocity"] diff --git a/tests/unit_tests/test_filter_io.py b/tests/unit_tests/test_filter_io.py new file mode 100644 index 00000000..f5a67332 --- /dev/null +++ b/tests/unit_tests/test_filter_io.py @@ -0,0 +1,45 @@ +import pytest + +from bec_widgets.utils.filter_io import FilterIO +from bec_widgets.widgets.dap_combo_box.dap_combo_box import DapComboBox +from bec_widgets.widgets.device_line_edit.device_line_edit import DeviceLineEdit + +from .client_mocks import mocked_client +from .conftest import create_widget + + +@pytest.fixture(scope="function") +def dap_mock(qtbot, mocked_client): + """Fixture for QLineEdit widget""" + models = ["GaussianModel", "LorentzModel", "SineModel"] + mocked_client.dap._available_dap_plugins.keys.return_value = models + widget = create_widget(qtbot, DapComboBox, client=mocked_client) + return widget + + +@pytest.fixture(scope="function") +def line_edit_mock(qtbot, mocked_client): + """Fixture for QLineEdit widget""" + widget = create_widget(qtbot, DeviceLineEdit, client=mocked_client) + return widget + + +def test_set_selection_combo_box(dap_mock): + """Test set selection for QComboBox using DapComboBox""" + assert dap_mock.fit_model_combobox.count() == 3 + FilterIO.set_selection(dap_mock.fit_model_combobox, selection=["testA", "testB"]) + assert dap_mock.fit_model_combobox.count() == 2 + assert FilterIO.check_input(widget=dap_mock.fit_model_combobox, text="testA") is True + + +def test_set_selection_line_edit(line_edit_mock): + """Test set selection for QComboBox using DapComboBox""" + FilterIO.set_selection(line_edit_mock, selection=["testA", "testB"]) + assert line_edit_mock.completer.model().rowCount() == 2 + model = line_edit_mock.completer.model() + model_data = [model.data(model.index(i)) for i in range(model.rowCount())] + assert model_data == ["testA", "testB"] + assert FilterIO.check_input(widget=line_edit_mock, text="testA") is True + FilterIO.set_selection(line_edit_mock, selection=["testC"]) + assert FilterIO.check_input(widget=line_edit_mock, text="testA") is False + assert FilterIO.check_input(widget=line_edit_mock, text="testC") is True diff --git a/tests/unit_tests/test_motor_map_widget.py b/tests/unit_tests/test_motor_map_widget.py index 0b149ca2..51b19838 100644 --- a/tests/unit_tests/test_motor_map_widget.py +++ b/tests/unit_tests/test_motor_map_widget.py @@ -2,6 +2,7 @@ from unittest.mock import MagicMock, patch import pytest +from bec_widgets.widgets.base_classes.device_input_base import BECDeviceFilter from bec_widgets.widgets.motor_map.motor_map_dialog.motor_map_settings import MotorMapSettings from bec_widgets.widgets.motor_map.motor_map_widget import BECMotorMapWidget @@ -11,8 +12,8 @@ from .client_mocks import mocked_client @pytest.fixture def motor_map_widget(qtbot, mocked_client): widget = BECMotorMapWidget(client=mocked_client()) - widget.toolbar.widgets["motor_x"].device_combobox.set_device_filter("FakePositioner") - widget.toolbar.widgets["motor_y"].device_combobox.set_device_filter("FakePositioner") + widget.toolbar.widgets["motor_x"].device_combobox.set_device_filter(BECDeviceFilter.POSITIONER) + widget.toolbar.widgets["motor_y"].device_combobox.set_device_filter(BECDeviceFilter.POSITIONER) qtbot.addWidget(widget) qtbot.waitExposed(widget) yield widget @@ -35,14 +36,12 @@ def test_motor_map_widget_init(motor_map_widget): assert motor_map_widget.toolbar.widgets["connect"].action.isEnabled() == True assert motor_map_widget.toolbar.widgets["config"].action.isEnabled() == False assert motor_map_widget.toolbar.widgets["history"].action.isEnabled() == False - assert ( - motor_map_widget.toolbar.widgets["motor_x"].device_combobox.config.device_filter - == "FakePositioner" - ) - assert ( - motor_map_widget.toolbar.widgets["motor_y"].device_combobox.config.device_filter - == "FakePositioner" - ) + assert motor_map_widget.toolbar.widgets["motor_x"].device_combobox.config.device_filter == [ + BECDeviceFilter.POSITIONER + ] + assert motor_map_widget.toolbar.widgets["motor_y"].device_combobox.config.device_filter == [ + BECDeviceFilter.POSITIONER + ] assert motor_map_widget.map.motor_x is None assert motor_map_widget.map.motor_y is None