Skip to content

Commit c299785

Browse files
committed
Fix dataset corruption in DataSetShowGroupBox.get() by updating widget build modes to prevent stale values
1 parent 1cd2773 commit c299785

2 files changed

Lines changed: 21 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,14 @@
200200

201201
🛠️ Bug fixes:
202202

203+
* Fixed dataset corruption in `DataSetShowGroupBox.get()` when updating widgets with dependencies:
204+
* When updating widgets from dataset values (e.g., when switching between objects in DataLab), the `get()` method would set `build_mode=True` on widgets sequentially while calling their `get()` methods.
205+
* This caused Qt signal callbacks to invoke `update_widgets()` on other widgets that hadn't yet had their `build_mode` set, leading `_display_callback()` to call `update_dataitems()`.
206+
* As a result, stale widget values would be written back to the dataset before those widgets were updated from the new dataset values, corrupting the data.
207+
* The fix uses a three-phase approach: (1) set `build_mode=True` on ALL terminal widgets (including nested ones) before any updates, (2) update all widgets from dataset values, (3) reset `build_mode=False` on all terminal widgets.
208+
* This ensures callbacks during the update phase find all widgets with `build_mode=True`, preventing premature writes of stale widget values to the dataset.
209+
* This issue was particularly visible when switching between images in DataLab where field values (like `zscalemin`) would incorrectly retain values from the previously selected object instead of showing `None` or the new object's actual values.
210+
203211
* Fixed widget `get()` methods to properly reset widgets to default state when item value is `None`:
204212
* Previously, when a data item value was `None`, widgets would retain their previous displayed values instead of resetting to a default state.
205213
* This affected multiple widget types: `LineEditWidget` (text fields), `TextEditWidget` (text areas), `CheckBoxWidget` (checkboxes), `DateWidget` (date pickers), `DateTimeWidget` (datetime pickers), `ChoiceWidget` (combo boxes/radio buttons), `MultipleChoiceWidget` (multiple checkboxes), and `FloatArrayWidget` (array editor).

guidata/dataset/qtwidgets.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -819,11 +819,23 @@ def get_edit_layout(self) -> DataSetEditLayout[AnyDataSet]:
819819

820820
def get(self) -> None:
821821
"""Update group box contents from data item values"""
822-
for widget in self.edit.widgets:
822+
# Set build_mode=True for ALL widgets (including nested ones) FIRST
823+
# to prevent update_dataitems() from being called during callbacks
824+
# (which would write stale widget values back to the dataset before
825+
# those widgets have been updated)
826+
all_widgets = self.edit.get_terminal_widgets()
827+
for widget in all_widgets:
823828
widget.build_mode = True
829+
830+
# Now update all widgets from dataset
831+
for widget in self.edit.widgets:
824832
widget.get()
825833
widget.set_state()
834+
835+
# Reset build_mode after all updates are complete
836+
for widget in all_widgets:
826837
widget.build_mode = False
838+
827839
if self.apply_button is not None:
828840
self.apply_button.setVisible(not self.dataset.is_readonly())
829841

0 commit comments

Comments
 (0)