From 05c38d9b82cc6dfaec8f5abf8e0ececa5d001524 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 23 Mar 2026 13:04:04 +0000 Subject: [PATCH] fix(lmfit_dialog): fix fit_curve_id type annotation and remove_dap_data selection behavior Co-authored-by: wyzula-jan <133381102+wyzula-jan@users.noreply.github.com> Agent-Logs-Url: https://github.com/bec-project/bec_widgets/sessions/97395c0e-0271-4cdf-b39f-f3117d21bfa3 --- .../widgets/dap/lmfit_dialog/lmfit_dialog.py | 19 ++++++---- tests/unit_tests/test_lmfit_dialog.py | 35 ++++++++++++++++++- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/bec_widgets/widgets/dap/lmfit_dialog/lmfit_dialog.py b/bec_widgets/widgets/dap/lmfit_dialog/lmfit_dialog.py index f0557b48..9b261c89 100644 --- a/bec_widgets/widgets/dap/lmfit_dialog/lmfit_dialog.py +++ b/bec_widgets/widgets/dap/lmfit_dialog/lmfit_dialog.py @@ -80,7 +80,8 @@ class LMFitDialog(BECWidget, QWidget): self._enable_actions = enable valid_buttons = {} for name, button in self.action_buttons.items(): - if button is None or not shiboken6.isValid(button): # to fix cpp object deleted + # just to be sure we have a valid c++ object + if button is None or not shiboken6.isValid(button): continue button.setEnabled(enable) valid_buttons[name] = button @@ -150,19 +151,21 @@ class LMFitDialog(BECWidget, QWidget): self.ui.group_parameters.setVisible(not show) @property - def fit_curve_id(self) -> str: + def fit_curve_id(self) -> str | None: """SafeProperty for the currently displayed fit curve_id.""" return self._fit_curve_id @fit_curve_id.setter - def fit_curve_id(self, curve_id: str): + def fit_curve_id(self, curve_id: str | None): """Setter for the currently displayed fit curve_id. Args: - curve_id (str): The curve_id of the fit curve to be displayed. + curve_id (str | None): The curve_id of the fit curve to be displayed, + or None to clear the selection. """ self._fit_curve_id = curve_id - self.selected_fit.emit(curve_id) + if curve_id is not None: + self.selected_fit.emit(curve_id) @SafeSlot(str) def remove_dap_data(self, curve_id: str): @@ -173,10 +176,14 @@ class LMFitDialog(BECWidget, QWidget): """ self.summary_data.pop(curve_id, None) if self.fit_curve_id == curve_id: - self._fit_curve_id = None self.action_buttons = {} self.ui.summary_tree.clear() self.ui.param_tree.clear() + remaining = list(self.summary_data.keys()) + if remaining: + self.fit_curve_id = remaining[0] + else: + self._fit_curve_id = None self.refresh_curve_list() @SafeSlot(str) diff --git a/tests/unit_tests/test_lmfit_dialog.py b/tests/unit_tests/test_lmfit_dialog.py index 476e3f75..4299949b 100644 --- a/tests/unit_tests/test_lmfit_dialog.py +++ b/tests/unit_tests/test_lmfit_dialog.py @@ -140,7 +140,7 @@ def lmfit_message(): def test_fit_curve_id(lmfit_dialog): - """Test hide_curve_selection property""" + """Test fit_curve_id property and selected_fit signal""" my_callback = mock.MagicMock() lmfit_dialog.selected_fit.connect(my_callback) assert lmfit_dialog.fit_curve_id is None @@ -148,6 +148,10 @@ def test_fit_curve_id(lmfit_dialog): assert lmfit_dialog.fit_curve_id == "test_curve_id" assert my_callback.call_count == 1 assert my_callback.call_args == mock.call("test_curve_id") + # Setting to None should not emit selected_fit + lmfit_dialog.fit_curve_id = None + assert lmfit_dialog.fit_curve_id is None + assert my_callback.call_count == 1 def test_remove_dap_data(lmfit_dialog): @@ -166,6 +170,35 @@ def test_remove_dap_data(lmfit_dialog): assert lmfit_dialog.ui.curve_list.count() == 1 +def test_remove_dap_data_selected_curve_switches_to_next(lmfit_dialog): + """Removing the currently selected curve should switch to the next available one""" + my_callback = mock.MagicMock() + lmfit_dialog.selected_fit.connect(my_callback) + lmfit_dialog.summary_data = {"curve_a": "data_a", "curve_b": "data_b"} + lmfit_dialog.fit_curve_id = "curve_a" + my_callback.reset_mock() + + lmfit_dialog.remove_dap_data("curve_a") + + assert lmfit_dialog.fit_curve_id == "curve_b" + assert my_callback.call_count == 1 + assert my_callback.call_args == mock.call("curve_b") + + +def test_remove_dap_data_selected_curve_clears_when_last(lmfit_dialog): + """Removing the only/last selected curve should clear the selection without emitting""" + my_callback = mock.MagicMock() + lmfit_dialog.selected_fit.connect(my_callback) + lmfit_dialog.summary_data = {"curve_a": "data_a"} + lmfit_dialog.fit_curve_id = "curve_a" + my_callback.reset_mock() + + lmfit_dialog.remove_dap_data("curve_a") + + assert lmfit_dialog.fit_curve_id is None + assert my_callback.call_count == 0 + + def test_update_summary_tree(lmfit_dialog, lmfit_message): """Test display_fit_details method""" lmfit_dialog.active_action_list = ["center", "amplitude"]