mirror of
https://github.com/bec-project/bec_widgets.git
synced 2025-07-13 11:11:49 +02:00
fix: (#612) fix additional MD form
makes sure the form is validated on any changes of the additional metadata table model so that they are propagated to the scan control widget even when nothing is entered in the standard form
This commit is contained in:
@ -53,6 +53,7 @@ class DictBackedTableModel(QAbstractTableModel):
|
||||
if value in self._disallowed_keys or value in self._other_keys(index.row()):
|
||||
return False
|
||||
self._data[index.row()][index.column()] = str(value)
|
||||
self.dataChanged.emit(index, index)
|
||||
return True
|
||||
return False
|
||||
|
||||
@ -109,6 +110,7 @@ class DictBackedTableModel(QAbstractTableModel):
|
||||
|
||||
class DictBackedTable(QWidget):
|
||||
delete_rows = Signal(list)
|
||||
data_updated = Signal()
|
||||
|
||||
def __init__(self, initial_data: list[list[str]]):
|
||||
"""Widget which uses a DictBackedTableModel to display an editable table
|
||||
@ -141,6 +143,11 @@ class DictBackedTable(QWidget):
|
||||
self._add_button.clicked.connect(self._table_model.add_row)
|
||||
self._remove_button.clicked.connect(self.delete_selected_rows)
|
||||
self.delete_rows.connect(self._table_model.delete_rows)
|
||||
self._table_model.dataChanged.connect(self._emit_data_updated)
|
||||
|
||||
def _emit_data_updated(self, *args, **kwargs):
|
||||
"""Just to swallow the args"""
|
||||
self.data_updated.emit()
|
||||
|
||||
def delete_selected_rows(self):
|
||||
"""Delete rows which are part of the selection model"""
|
||||
|
@ -43,6 +43,7 @@ class ScanMetadata(PydanticModelForm):
|
||||
self._additional_metadata = DictBackedTable(initial_extras or [])
|
||||
self._scan_name = scan_name or ""
|
||||
self._md_schema = get_metadata_schema_for_scan(self._scan_name)
|
||||
self._additional_metadata.data_updated.connect(self.validate_form)
|
||||
|
||||
super().__init__(parent=parent, metadata_model=self._md_schema, client=client, **kwargs)
|
||||
|
||||
|
@ -1,9 +1,11 @@
|
||||
# pylint: disable = no-name-in-module,missing-class-docstring, missing-module-docstring
|
||||
from unittest.mock import MagicMock
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
from bec_lib.endpoints import MessageEndpoints
|
||||
from bec_lib.messages import AvailableResourceMessage, ScanQueueHistoryMessage, ScanQueueMessage
|
||||
from qtpy.QtCore import QModelIndex, QPoint, Qt
|
||||
|
||||
from bec_widgets.utils.forms_from_types.items import StrMetadataField
|
||||
from bec_widgets.utils.widget_io import WidgetIO
|
||||
@ -540,6 +542,29 @@ def test_get_scan_parameters_from_redis(scan_control, mocked_client):
|
||||
assert kwargs == {"steps": 10, "relative": False, "exp_time": 2.0, "burst_at_each_point": 1}
|
||||
|
||||
|
||||
TEST_MD = {"sample_name": "Test Sample", "test key 1": "test value 1", "test key 2": "test value 2"}
|
||||
TEST_TABLE_ENTRY = [["test key 1", "test value 1"], ["test key 2", "test value 2"]]
|
||||
|
||||
|
||||
def test_scan_metadata_is_updated_even_without_default_form_changes(
|
||||
scan_control: ScanControl, qtbot
|
||||
):
|
||||
assert scan_control._metadata_form._scan_name == "line_scan"
|
||||
scan_control.comboBox_scan_selection.setCurrentText("grid_scan")
|
||||
assert scan_control._metadata_form._scan_name == "grid_scan"
|
||||
scan_control._metadata_form._additional_metadata._add_button.click()
|
||||
qtbot.wait(100)
|
||||
table_model = scan_control._metadata_form._additional_metadata._table_model
|
||||
model_key = table_model.index(0, 0, QModelIndex())
|
||||
table_model.setData(model_key, "test key 1", Qt.EditRole)
|
||||
model_value = model_key.siblingAtColumn(1)
|
||||
table_model.setData(model_value, "test value 1", Qt.EditRole)
|
||||
assert scan_control._metadata_form._additional_metadata.dump_dict() == {
|
||||
"test key 1": "test value 1"
|
||||
}
|
||||
assert scan_control._scan_metadata == {"sample_name": "", "test key 1": "test value 1"}
|
||||
|
||||
|
||||
def test_scan_metadata_is_connected(scan_control):
|
||||
assert scan_control._metadata_form._scan_name == "line_scan"
|
||||
scan_control.comboBox_scan_selection.setCurrentText("grid_scan")
|
||||
@ -548,16 +573,28 @@ def test_scan_metadata_is_connected(scan_control):
|
||||
assert isinstance(sample_name, StrMetadataField)
|
||||
sample_name._main_widget.setText("Test Sample")
|
||||
|
||||
scan_control._metadata_form._additional_metadata._table_model._data = [
|
||||
["test key 1", "test value 1"],
|
||||
["test key 2", "test value 2"],
|
||||
]
|
||||
scan_control._metadata_form._additional_metadata._table_model._data = TEST_TABLE_ENTRY
|
||||
scan_control._metadata_form.validate_form()
|
||||
assert scan_control._scan_metadata == {
|
||||
"sample_name": "Test Sample",
|
||||
"test key 1": "test value 1",
|
||||
"test key 2": "test value 2",
|
||||
}
|
||||
assert scan_control._scan_metadata == TEST_MD
|
||||
|
||||
|
||||
def test_scan_metadata_is_passed_to_scan_function(scan_control: ScanControl):
|
||||
scan_control.comboBox_scan_selection.setCurrentText("grid_scan")
|
||||
|
||||
sample_name = scan_control._metadata_form._form_grid.layout().itemAtPosition(0, 1).widget()
|
||||
sample_name._main_widget.setText("Test Sample")
|
||||
scan_control._metadata_form._additional_metadata._table_model._data = TEST_TABLE_ENTRY
|
||||
scan_control._metadata_form.validate_form()
|
||||
|
||||
assert scan_control._scan_metadata == TEST_MD
|
||||
|
||||
scans = SimpleNamespace(grid_scan=MagicMock())
|
||||
with (
|
||||
patch.object(scan_control, "scans", scans),
|
||||
patch.object(scan_control, "get_scan_parameters", lambda: ((), {})),
|
||||
):
|
||||
scan_control.run_scan()
|
||||
scans.grid_scan.assert_called_once_with(metadata=TEST_MD)
|
||||
|
||||
|
||||
def test_restore_parameters_with_fewer_arg_bundles(scan_control, qtbot):
|
||||
|
Reference in New Issue
Block a user