1
0
mirror of https://github.com/bec-project/bec_widgets.git synced 2025-12-30 10:41:18 +01:00

feat: add shared selection signal util

This commit is contained in:
2025-09-02 18:25:37 +02:00
committed by wyzula-jan
parent 7676e863b2
commit be812322b0
6 changed files with 62 additions and 10 deletions

View File

@@ -9,7 +9,7 @@ from qtpy.QtWidgets import QListWidget, QListWidgetItem, QWidget
from bec_widgets.utils.error_popups import SafeSlot
from bec_widgets.utils.expandable_frame import ExpandableGroupFrame
from bec_widgets.widgets.control.device_manager.components.available_device_resources._util import (
from bec_widgets.widgets.control.device_manager.components._util import (
SORT_KEY_ROLE,
SortableQListWidgetItem,
)

View File

@@ -1,7 +1,10 @@
from typing import Any, Callable, Generator, Iterable, TypeVar
from PySide6.QtCore import QObject, Signal
from qtpy.QtWidgets import QListWidgetItem
from bec_widgets.widgets.control.device_manager.components.constants import SORT_KEY_ROLE
_T = TypeVar("_T")
_RT = TypeVar("_RT")
@@ -14,9 +17,6 @@ def yield_only_passing(fn: Callable[[_T], _RT], vals: Iterable[_T]) -> Generator
pass
SORT_KEY_ROLE = 117
class SortableQListWidgetItem(QListWidgetItem):
"""Store a sorting string key with .setData(SORT_KEY_ROLE, key) to be able to sort a list with \
custom widgets and this item."""
@@ -34,3 +34,7 @@ class SortableQListWidgetItem(QListWidgetItem):
) is None:
return False
return self_key.lower() < other_key.lower()
class SharedSelectionSignal(QObject):
proc = Signal(str)

View File

@@ -1,11 +1,14 @@
from textwrap import dedent
from typing import NamedTuple
from uuid import uuid4
from bec_qthemes import material_icon
from qtpy.QtCore import QSize
from qtpy.QtCore import QItemSelection, QSize
from qtpy.QtWidgets import QFrame, QHBoxLayout, QLabel, QListWidgetItem, QVBoxLayout, QWidget
from bec_widgets.utils.error_popups import SafeSlot
from bec_widgets.utils.expandable_frame import ExpandableGroupFrame
from bec_widgets.widgets.control.device_manager.components._util import SharedSelectionSignal
from bec_widgets.widgets.control.device_manager.components.available_device_resources.available_device_group_ui import (
Ui_AvailableDeviceGroup,
)
@@ -108,10 +111,21 @@ class _DeviceEntry(NamedTuple):
class AvailableDeviceGroup(ExpandableGroupFrame, Ui_AvailableDeviceGroup):
def __init__(
self, parent=None, name: str = "TagGroupTitle", data: set[HashableDevice] = set(), **kwargs
self,
parent=None,
name: str = "TagGroupTitle",
data: set[HashableDevice] = set(),
shared_selection_signal=SharedSelectionSignal(),
**kwargs,
):
super().__init__(parent=parent, **kwargs)
self.setupUi(self)
self._shared_selection_signal = shared_selection_signal
self._shared_selection_uuid = str(uuid4())
self._shared_selection_signal.proc.connect(self._handle_shared_selection_signal)
self.device_list.selectionModel().selectionChanged.connect(self._on_selection_changed)
self.title_text = name # type: ignore
self._mime_data = []
self._devices: dict[str, _DeviceEntry] = {}
@@ -165,6 +179,15 @@ class AvailableDeviceGroup(ExpandableGroupFrame, Ui_AvailableDeviceGroup):
self.device_list.sizeHintForRow(0) * self.device_list.count() + 50,
)
@SafeSlot(QItemSelection, QItemSelection)
def _on_selection_changed(self, selected: QItemSelection, deselected: QItemSelection) -> None:
self._shared_selection_signal.proc.emit(self._shared_selection_uuid)
@SafeSlot(str)
def _handle_shared_selection_signal(self, uuid: str):
if uuid != self._shared_selection_uuid:
self.device_list.clearSelection()
def resizeEvent(self, event):
super().resizeEvent(event)
self.setMinimumHeight(self.sizeHint().height())

View File

@@ -1,11 +1,14 @@
from random import randint
from typing import Any, Iterable
from uuid import uuid4
from PySide6.QtCore import QItemSelection
from qtpy.QtWidgets import QWidget
from bec_widgets.utils.bec_widget import BECWidget
from bec_widgets.utils.error_popups import SafeSlot
from bec_widgets.widgets.control.device_manager.components.available_device_resources._util import (
from bec_widgets.widgets.control.device_manager.components._util import (
SharedSelectionSignal,
yield_only_passing,
)
from bec_widgets.widgets.control.device_manager.components.available_device_resources.available_device_resources_ui import (
@@ -19,10 +22,16 @@ from bec_widgets.widgets.control.device_manager.components.constants import CONF
class AvailableDeviceResources(BECWidget, QWidget, Ui_availableDeviceResources):
def __init__(self, parent=None, **kwargs):
def __init__(self, parent=None, shared_selection_signal=SharedSelectionSignal(), **kwargs):
super().__init__(parent=parent, **kwargs)
self.setupUi(self)
self._backend = get_backend()
self._shared_selection_signal = shared_selection_signal
self._shared_selection_uuid = str(uuid4())
self._shared_selection_signal.proc.connect(self._handle_shared_selection_signal)
self.device_groups_list.selectionModel().selectionChanged.connect(
self._on_selection_changed
)
self.grouping_selector.addItem("deviceTags")
self.grouping_selector.addItems(self._backend.allowed_sort_keys)
self._grouping_selection_changed("deviceTags")
@@ -39,7 +48,12 @@ class AvailableDeviceResources(BECWidget, QWidget, Ui_availableDeviceResources):
def _add_device_group(self, device_group: str, devices: set[HashableDevice]):
item, widget = self.device_groups_list.add_item(
device_group, self.device_groups_list, device_group, devices, expanded=False
device_group,
self.device_groups_list,
device_group,
devices,
shared_selection_signal=self._shared_selection_signal,
expanded=False,
)
item.setData(CONFIG_DATA_ROLE, widget.create_mime_data())
@@ -57,6 +71,15 @@ class AvailableDeviceResources(BECWidget, QWidget, Ui_availableDeviceResources):
for list_item, device_group_widget in self.device_groups_list.item_widget_pairs():
list_item.setSizeHint(device_group_widget.sizeHint())
@SafeSlot(QItemSelection, QItemSelection)
def _on_selection_changed(self, selected: QItemSelection, deselected: QItemSelection) -> None:
self._shared_selection_signal.proc.emit(self._shared_selection_uuid)
@SafeSlot(str)
def _handle_shared_selection_signal(self, uuid: str):
if uuid != self._shared_selection_uuid:
self.device_groups_list.clearSelection()
@SafeSlot(dict)
def update_devices_state_name_outside(self, configs: dict):
self.update_devices_state([{"name": k, **v} for k, v in configs.items()])

View File

@@ -27,7 +27,6 @@ from bec_widgets.widgets.control.device_manager.components.constants import (
class _ListOfDeviceGroups(ListOfExpandableFrames[AvailableDeviceGroup]):
def mimeTypes(self):
return [MIME_DEVICE_CONFIG]

View File

@@ -2,4 +2,7 @@ from typing import Final
# Denotes a MIME type for JSON-encoded list of device config dictionaries
MIME_DEVICE_CONFIG: Final[str] = "application/x-bec_device_config"
# Custom user roles
SORT_KEY_ROLE: Final[int] = 117
CONFIG_DATA_ROLE: Final[int] = 118