From 2c6db345d39bc04e7e5a5e436f4b081252b4e43a Mon Sep 17 00:00:00 2001 From: David Perl Date: Mon, 21 Jul 2025 16:26:21 +0200 Subject: [PATCH] feat(devicebrowser): show enabled and readonly status --- bec_widgets/utils/compact_popup.py | 3 +- .../services/device_browser/device_browser.py | 6 ++-- .../device_browser/device_item/device_item.py | 28 +++++++++++++++++-- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/bec_widgets/utils/compact_popup.py b/bec_widgets/utils/compact_popup.py index cb5203b8..c7b0ac0f 100644 --- a/bec_widgets/utils/compact_popup.py +++ b/bec_widgets/utils/compact_popup.py @@ -1,5 +1,6 @@ import time from types import SimpleNamespace +from typing import Literal from bec_qthemes import material_icon from qtpy.QtCore import Property, Qt, Signal @@ -39,7 +40,7 @@ class LedLabel(QLabel): self.setState("default") self.setFixedSize(20, 20) - def setState(self, state: str): + def setState(self, state: Literal["success", "default", "warning", "emergency"]): match state: case "success": r, g, b, a = self.palette.success.getRgb() diff --git a/bec_widgets/widgets/services/device_browser/device_browser.py b/bec_widgets/widgets/services/device_browser/device_browser.py index 55a06668..06fb68ca 100644 --- a/bec_widgets/widgets/services/device_browser/device_browser.py +++ b/bec_widgets/widgets/services/device_browser/device_browser.py @@ -125,10 +125,8 @@ class DeviceBrowser(BECWidget, QWidget): action (str): The action that triggered the event. content (dict): The content of the config update. """ - if action in ["add", "remove", "reload"]: - self.devices_changed.emit() - if action in ["update", "reload"]: - self.device_update.emit(action, content) + self.devices_changed.emit() + self.device_update.emit(action, content) def init_device_list(self): self.dev_list.clear() diff --git a/bec_widgets/widgets/services/device_browser/device_item/device_item.py b/bec_widgets/widgets/services/device_browser/device_item/device_item.py index def709eb..44d08850 100644 --- a/bec_widgets/widgets/services/device_browser/device_item/device_item.py +++ b/bec_widgets/widgets/services/device_browser/device_item/device_item.py @@ -10,8 +10,17 @@ from bec_lib.messages import ConfigAction from bec_qthemes import material_icon from qtpy.QtCore import QMimeData, QSize, Qt, QThreadPool, Signal from qtpy.QtGui import QDrag -from qtpy.QtWidgets import QApplication, QHBoxLayout, QTabWidget, QToolButton, QVBoxLayout, QWidget +from qtpy.QtWidgets import ( + QApplication, + QHBoxLayout, + QLabel, + QTabWidget, + QToolButton, + QVBoxLayout, + QWidget, +) +from bec_widgets.utils.compact_popup import LedLabel from bec_widgets.utils.error_popups import SafeSlot from bec_widgets.utils.expandable_frame import ExpandableGroupFrame from bec_widgets.widgets.services.device_browser.device_item.config_communicator import ( @@ -56,6 +65,10 @@ class DeviceItem(ExpandableGroupFrame): self._expanded_first_time = False self._data = None self.device = device + self._deleting = False + + self._ro_pixmap = material_icon(icon_name="keyboard_off", size=(15, 15)) + self._we_pixmap = material_icon(icon_name="keyboard", size=(15, 15)) self._layout = QHBoxLayout() self._layout.setContentsMargins(0, 0, 0, 0) @@ -78,6 +91,7 @@ class DeviceItem(ExpandableGroupFrame): self.set_layout(self._layout) self.adjustSize() + self._reload_config() def _create_title_layout(self, title: str, icon: str): super()._create_title_layout(title, icon) @@ -92,6 +106,11 @@ class DeviceItem(ExpandableGroupFrame): self._title_layout.insertWidget(self._title_layout.count() - 1, self.delete_button) self.delete_button.clicked.connect(self._delete_device) + self.enabled_led = LedLabel() + self._title_layout.insertWidget(1, self.enabled_led) + self.readonly_label = QLabel() + self._title_layout.insertWidget(2, self.readonly_label) + @SafeSlot() def _create_edit_dialog(self): dialog = DeviceConfigDialog( @@ -106,6 +125,7 @@ class DeviceItem(ExpandableGroupFrame): @SafeSlot() def _delete_device(self): + self._deleting = True self.expanded = False deleter = CommunicateConfigAction(self._config_helper, self.device, None, "remove") deleter.signals.error.connect(self._deletion_error) @@ -147,7 +167,7 @@ class DeviceItem(ExpandableGroupFrame): @SafeSlot(str, dict) def config_update(self, action: ConfigAction, content: dict) -> None: - if self.device in content: + if (self.device in content or action == "reload") and not self._deleting: self._reload_config() @SafeSlot(popup_error=True) @@ -158,6 +178,10 @@ class DeviceItem(ExpandableGroupFrame): """Set the displayed information from a device config dict, which must conform to the bec_lib.atlas_models.Device config model.""" self._data = DeviceConfigModel.model_validate(config_dict) + self.enabled_led.setState("success" if self._data.enabled else "emergency") + self.enabled_led.setToolTip("enabled" if self._data.enabled else "disabled") + self.readonly_label.setPixmap(self._ro_pixmap if self._data.readOnly else self._we_pixmap) + self.readonly_label.setToolTip("read only" if self._data.readOnly else "writing enabled") if self._expanded_first_time: self.form.set_data(self._data)