0
0
mirror of https://github.com/bec-project/bec_widgets.git synced 2025-07-14 03:31:50 +02:00

fix(widget_state_manager): skip QLabel saving; skip_setting property widget excluded from INI; stored=False property excluded from INI

This commit is contained in:
2025-01-27 22:09:09 +01:00
parent 12e06fa971
commit b2b0450bcb
6 changed files with 261 additions and 35 deletions

View File

@ -3,7 +3,7 @@ import tempfile
import pytest
from qtpy.QtCore import Property
from qtpy.QtWidgets import QLineEdit, QVBoxLayout, QWidget
from qtpy.QtWidgets import QCheckBox, QGroupBox, QLineEdit, QVBoxLayout, QWidget
from bec_widgets.utils.widget_state_manager import WidgetStateManager
@ -23,6 +23,21 @@ class MyLineEdit(QLineEdit):
self._customColor = color
# A specialized widget that has a property declared with stored=False
class MyLineEditStoredFalse(QLineEdit):
def __init__(self, parent=None):
super().__init__(parent)
self._noStoreProperty = ""
@Property(str, stored=False)
def noStoreProperty(self):
return self._noStoreProperty
@noStoreProperty.setter
def noStoreProperty(self, value):
self._noStoreProperty = value
@pytest.fixture
def test_widget(qtbot):
w = QWidget()
@ -39,8 +54,15 @@ def test_widget(qtbot):
child2.setText("World")
child2.customColor = "blue"
# A widget that we want to skip settings
skip_widget = QCheckBox("Skip Widget", w)
skip_widget.setObjectName("SkipCheckBox")
skip_widget.setChecked(True)
skip_widget.setProperty("skip_settings", True)
layout.addWidget(child1)
layout.addWidget(child2)
layout.addWidget(skip_widget)
qtbot.addWidget(w)
qtbot.waitExposed(w)
@ -51,7 +73,6 @@ def test_save_load_widget_state(test_widget):
"""
Test saving and loading the state
"""
manager = WidgetStateManager(test_widget)
# Before saving, confirm initial properties
@ -97,7 +118,6 @@ def test_save_load_without_filename(test_widget, monkeypatch, qtbot):
"""
Test that the dialog would open if filename is not provided.
"""
manager = WidgetStateManager(test_widget)
# Mock QFileDialog.getSaveFileName to return a temporary filename
@ -133,3 +153,130 @@ def test_save_load_without_filename(test_widget, monkeypatch, qtbot):
# Clean up
os.remove(tmp_filename)
def test_skip_settings(test_widget):
"""
Verify that a widget with skip_settings=True is not saved/loaded.
"""
manager = WidgetStateManager(test_widget)
skip_checkbox = test_widget.findChild(QCheckBox, "SkipCheckBox")
# Double check initial state
assert skip_checkbox.isChecked() is True
with tempfile.NamedTemporaryFile(delete=False, suffix=".ini") as tmp_file:
tmp_filename = tmp_file.name
# Save state
manager.save_state(tmp_filename)
# Change skip checkbox state
skip_checkbox.setChecked(False)
assert skip_checkbox.isChecked() is False
# Load state
manager.load_state(tmp_filename)
# The skip checkbox should not revert because it was never saved.
assert skip_checkbox.isChecked() is False
os.remove(tmp_filename)
def test_property_stored_false(qtbot):
"""
Verify that a property with stored=False is not saved.
"""
w = QWidget()
w.setObjectName("TestStoredFalse")
layout = QVBoxLayout(w)
stored_false_widget = MyLineEditStoredFalse(w)
stored_false_widget.setObjectName("NoStoreLineEdit")
stored_false_widget.setText("VisibleText") # normal text property is stored
stored_false_widget.noStoreProperty = "ShouldNotBeStored"
layout.addWidget(stored_false_widget)
qtbot.addWidget(w)
qtbot.waitExposed(w)
manager = WidgetStateManager(w)
with tempfile.NamedTemporaryFile(delete=False, suffix=".ini") as tmp_file:
tmp_filename = tmp_file.name
# Save the current state
manager.save_state(tmp_filename)
# Modify the properties
stored_false_widget.setText("ChangedText")
stored_false_widget.noStoreProperty = "ChangedNoStore"
# Load the previous state
manager.load_state(tmp_filename)
# The text should have reverted
assert stored_false_widget.text() == "VisibleText"
# The noStoreProperty should remain changed, as it was never saved.
assert stored_false_widget.noStoreProperty == "ChangedNoStore"
os.remove(tmp_filename)
def test_skip_parent_settings(qtbot):
"""
Demonstrates that if a PARENT widget has skip_settings=True, all its
children (even if they do NOT have skip_settings=True) also get skipped.
"""
main_widget = QWidget()
main_widget.setObjectName("TopWidget")
layout = QVBoxLayout(main_widget)
# Create a parent widget with skip_settings=True
parent_group = QGroupBox("ParentGroup", main_widget)
parent_group.setObjectName("ParentGroupBox")
parent_group.setProperty("skip_settings", True) # The crucial setting
child_layout = QVBoxLayout(parent_group)
child_line_edit_1 = MyLineEdit(parent_group)
child_line_edit_1.setObjectName("ChildLineEditA")
child_line_edit_1.setText("OriginalA")
child_line_edit_2 = MyLineEdit(parent_group)
child_line_edit_2.setObjectName("ChildLineEditB")
child_line_edit_2.setText("OriginalB")
child_layout.addWidget(child_line_edit_1)
child_layout.addWidget(child_line_edit_2)
parent_group.setLayout(child_layout)
layout.addWidget(parent_group)
main_widget.setLayout(layout)
qtbot.addWidget(main_widget)
qtbot.waitExposed(main_widget)
manager = WidgetStateManager(main_widget)
# Create a temp file to hold settings
with tempfile.NamedTemporaryFile(delete=False, suffix=".ini") as tmp_file:
tmp_filename = tmp_file.name
# Save the state
manager.save_state(tmp_filename)
# Change child widget values
child_line_edit_1.setText("ChangedA")
child_line_edit_2.setText("ChangedB")
# Load state
manager.load_state(tmp_filename)
# Because the PARENT has skip_settings=True, none of its children get saved or loaded
# Hence, the changes remain and do NOT revert
assert child_line_edit_1.text() == "ChangedA"
assert child_line_edit_2.text() == "ChangedB"
os.remove(tmp_filename)