mirror of
https://github.com/bec-project/bec_widgets.git
synced 2025-07-14 11:41:49 +02:00
feat(device_combobox): DeviceInputBase and DeviceComboBox added
This commit is contained in:
1
bec_widgets/widgets/device_inputs/__init__.py
Normal file
1
bec_widgets/widgets/device_inputs/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
from .device_combobox.device_combobox import DeviceComboBox
|
@ -0,0 +1,88 @@
|
|||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
from qtpy.QtWidgets import QComboBox
|
||||||
|
|
||||||
|
from bec_widgets.widgets.device_inputs.device_input_base import DeviceInputBase, DeviceInputConfig
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from bec_widgets.widgets.device_inputs.device_input_base import DeviceInputConfig
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceComboBox(DeviceInputBase, QComboBox):
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
parent=None,
|
||||||
|
client=None,
|
||||||
|
config: DeviceInputConfig = None,
|
||||||
|
gui_id: str | None = None,
|
||||||
|
device_filter: str = None,
|
||||||
|
default_device: str = None,
|
||||||
|
):
|
||||||
|
super().__init__(
|
||||||
|
client=client,
|
||||||
|
config=config,
|
||||||
|
gui_id=gui_id,
|
||||||
|
device_filter=device_filter,
|
||||||
|
default_device=default_device,
|
||||||
|
)
|
||||||
|
QComboBox.__init__(self, parent=parent)
|
||||||
|
|
||||||
|
self.populate_combobox()
|
||||||
|
self._set_defaults()
|
||||||
|
|
||||||
|
def _set_defaults(self):
|
||||||
|
"""Set the default device and device filter."""
|
||||||
|
if self.config.default_device is not None:
|
||||||
|
self.set_default_device(self.config.default_device)
|
||||||
|
if self.config.device_filter is not None:
|
||||||
|
self.set_device_filter(self.config.device_filter)
|
||||||
|
|
||||||
|
def set_device_filter(self, device_filter: str):
|
||||||
|
"""
|
||||||
|
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.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
object: Device object.
|
||||||
|
"""
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__": # pragma: no cover
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from qtpy.QtWidgets import QApplication
|
||||||
|
|
||||||
|
app = QApplication(sys.argv)
|
||||||
|
w = DeviceComboBox(default_device="samx")
|
||||||
|
w.show()
|
||||||
|
sys.exit(app.exec_())
|
130
bec_widgets/widgets/device_inputs/device_input_base.py
Normal file
130
bec_widgets/widgets/device_inputs/device_input_base.py
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from bec_widgets.utils import BECConnector, ConnectionConfig
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceInputConfig(ConnectionConfig):
|
||||||
|
device_filter: str | list[str] | None = None
|
||||||
|
default_device: str | None = None
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceInputBase(BECConnector):
|
||||||
|
"""
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
parent=None,
|
||||||
|
client=None,
|
||||||
|
config=None,
|
||||||
|
gui_id=None,
|
||||||
|
device_filter: str = None,
|
||||||
|
default_device: str = None,
|
||||||
|
):
|
||||||
|
if config is None:
|
||||||
|
config = DeviceInputConfig(widget_class=self.__class__.__name__)
|
||||||
|
else:
|
||||||
|
if isinstance(config, dict):
|
||||||
|
config = DeviceInputConfig(**config)
|
||||||
|
self.config = config
|
||||||
|
super().__init__(client=client, config=config, gui_id=gui_id)
|
||||||
|
|
||||||
|
self.get_bec_shortcuts()
|
||||||
|
self.config.device_filter = device_filter
|
||||||
|
self.config.default_device = default_device
|
||||||
|
self._devices = []
|
||||||
|
|
||||||
|
@property
|
||||||
|
def devices(self) -> list[str]:
|
||||||
|
"""
|
||||||
|
Get the list of devices.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list[str]: List of devices.
|
||||||
|
"""
|
||||||
|
return self._devices
|
||||||
|
|
||||||
|
@devices.setter
|
||||||
|
def devices(self, value: list[str]):
|
||||||
|
"""
|
||||||
|
Set the list of devices.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
value: List of devices.
|
||||||
|
"""
|
||||||
|
self._devices = value
|
||||||
|
|
||||||
|
def set_device_filter(self, device_filter: str | list[str]):
|
||||||
|
"""
|
||||||
|
Set the device filter.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
device_filter(str): Device filter, name of the device class.
|
||||||
|
"""
|
||||||
|
self.validate_device_filter(device_filter)
|
||||||
|
self.config.device_filter = device_filter
|
||||||
|
|
||||||
|
def set_default_device(self, default_device: str):
|
||||||
|
"""
|
||||||
|
Set the default device.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
default_device(str): Default device name.
|
||||||
|
"""
|
||||||
|
if default_device not in self.get_device_list(self.config.device_filter):
|
||||||
|
raise ValueError(f"Default device {default_device} is not in the device list.")
|
||||||
|
self.config.default_device = default_device
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
filter(str|None): Class name filter to apply on the device list.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
devices(list[str]): List of device names.
|
||||||
|
"""
|
||||||
|
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
|
||||||
|
|
||||||
|
def get_available_filters(self):
|
||||||
|
"""
|
||||||
|
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.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
device(str): Device to validate.
|
||||||
|
"""
|
||||||
|
if device not in self.get_device_list():
|
||||||
|
raise ValueError(f"Device {device} is not valid.")
|
Reference in New Issue
Block a user