mirror of
https://github.com/bec-project/bec_widgets.git
synced 2026-03-04 16:02:51 +01:00
fix(image): combobox for device selection is repopulated with config update
This commit is contained in:
@@ -124,6 +124,9 @@ class Image(ImageBase):
|
||||
self.async_update = False
|
||||
self.bec_dispatcher.connect_slot(self.on_scan_status, MessageEndpoints.scan_status())
|
||||
self.bec_dispatcher.connect_slot(self.on_scan_progress, MessageEndpoints.scan_progress())
|
||||
self.bec_dispatcher.connect_slot(
|
||||
self._populate_signals, MessageEndpoints.device_config_update()
|
||||
)
|
||||
|
||||
##################################
|
||||
### Toolbar Initialization
|
||||
@@ -189,15 +192,21 @@ class Image(ImageBase):
|
||||
Has to be done with QTimer.singleShot to ensure the UI is fully initialized, needed for testing.
|
||||
"""
|
||||
self._populate_signals()
|
||||
self._reverse_device_items()
|
||||
self.device_combo_box.setCurrentText("") # set again default to empty string
|
||||
|
||||
def _populate_signals(self) -> None:
|
||||
@SafeSlot(dict, dict)
|
||||
def _populate_signals(self, data: dict | None = None, meta: dict | None = None) -> None:
|
||||
"""
|
||||
Populate the device combo box with preview-signal devices in the
|
||||
format '<device>_<signal>' and store the tuple(device, signal) in
|
||||
the item's userData for later use.
|
||||
(Re)populate the device combo box with preview/async signals,
|
||||
matching the initial setup logic.
|
||||
"""
|
||||
self.device_combo_box.blockSignals(True)
|
||||
self.device_combo_box.clear()
|
||||
# Rebuild base device list via the combobox' own filtering logic
|
||||
self.device_combo_box.update_devices_from_filters()
|
||||
base_count = self.device_combo_box.count()
|
||||
# Place an empty default entry between base devices and signal entries
|
||||
self.device_combo_box.insertItem(base_count, "", None)
|
||||
|
||||
preview_signals = self.client.device_manager.get_bec_signals("PreviewSignal")
|
||||
async_signals = self.client.device_manager.get_bec_signals("AsyncSignal")
|
||||
all_signals = preview_signals + async_signals
|
||||
@@ -209,6 +218,8 @@ class Image(ImageBase):
|
||||
continue
|
||||
label = signal_config.get("obj_name", f"{device}_{signal}")
|
||||
self.device_combo_box.addItem(label, (device, signal, signal_config))
|
||||
self.device_combo_box.setCurrentText("")
|
||||
self.device_combo_box.blockSignals(False)
|
||||
|
||||
def _reverse_device_items(self) -> None:
|
||||
"""
|
||||
|
||||
@@ -730,21 +730,32 @@ def test_monitor_selection_populate_signals(qtbot, mocked_client, monkeypatch):
|
||||
|
||||
monkeypatch.setattr(view.client, "device_manager", _FakeDM())
|
||||
|
||||
initial_count = view.device_combo_box.count()
|
||||
|
||||
view._populate_signals()
|
||||
|
||||
# PreviewSignal + AsyncSignal entries were added
|
||||
assert view.device_combo_box.count() == initial_count + 3
|
||||
# Base devices first, then empty separator, then signal entries
|
||||
signal_texts = []
|
||||
separator_seen = False
|
||||
for i in range(view.device_combo_box.count()):
|
||||
data = view.device_combo_box.itemData(i)
|
||||
text = view.device_combo_box.itemText(i)
|
||||
if data is None and text == "":
|
||||
separator_seen = True
|
||||
continue
|
||||
if separator_seen is False:
|
||||
# base device entries
|
||||
continue
|
||||
# After separator we expect signal tuples
|
||||
assert isinstance(data, tuple)
|
||||
signal_texts.append(text)
|
||||
|
||||
# The first newly added item should carry tuple userData describing the device/signal
|
||||
data = view.device_combo_box.itemData(initial_count)
|
||||
assert isinstance(data, tuple) and data[0] == "eiger"
|
||||
texts = [
|
||||
view.device_combo_box.itemText(i)
|
||||
for i in range(initial_count, view.device_combo_box.count())
|
||||
]
|
||||
assert "async_device_img_async" in texts
|
||||
assert {"eiger_img", "eiger_img2", "async_device_img_async"}.issubset(set(signal_texts))
|
||||
first_signal_idx = next(
|
||||
i
|
||||
for i in range(view.device_combo_box.count())
|
||||
if isinstance(view.device_combo_box.itemData(i), tuple)
|
||||
)
|
||||
data = view.device_combo_box.itemData(first_signal_idx)
|
||||
assert isinstance(data, tuple) and data[0] in ["eiger", "eiger2", "async_device"]
|
||||
|
||||
|
||||
def test_monitor_selection_adjust_and_connect(qtbot, mocked_client, monkeypatch):
|
||||
@@ -774,9 +785,13 @@ def test_monitor_selection_adjust_and_connect(qtbot, mocked_client, monkeypatch)
|
||||
# Execute the method under test
|
||||
view._adjust_and_connect()
|
||||
|
||||
# Expect exactly two items: preview label followed by the empty default
|
||||
assert combo.count() == 2
|
||||
# Because of the reversal, the preview label comes first
|
||||
assert combo.itemText(0) == "eiger_img"
|
||||
# Base devices should appear first, then empty separator, then signals
|
||||
sep_idx = next(
|
||||
i for i in range(combo.count()) if combo.itemData(i) is None and combo.itemText(i) == ""
|
||||
)
|
||||
first_signal_idx = sep_idx + 1
|
||||
assert isinstance(combo.itemData(first_signal_idx), tuple)
|
||||
assert combo.itemText(first_signal_idx) == "eiger_img"
|
||||
assert combo.itemText(sep_idx) == ""
|
||||
# Current selection remains empty
|
||||
assert combo.currentText() == ""
|
||||
|
||||
Reference in New Issue
Block a user