diff --git a/bec_widgets/cli/client.py b/bec_widgets/cli/client.py index 11663d1e..918ea5db 100644 --- a/bec_widgets/cli/client.py +++ b/bec_widgets/cli/client.py @@ -369,6 +369,18 @@ class BECDockArea(RPCBase): name (str | None): The name of the profile to load. If None, prompts the user. """ + @rpc_timeout(None) + @rpc_call + def restore_baseline_profile(self, name: "str | None" = None, show_dialog: "bool" = True): + """ + Overwrite the runtime copy of *name* with the baseline. + If *name* is None, target the currently active profile. + + Args: + name (str | None): The name of the profile to restore. If None, uses the current profile. + show_dialog (bool): If True, ask for confirmation before restoring. + """ + @rpc_call def delete_profile(self, name: "str | None" = None, show_dialog: "bool" = False) -> "bool": """ @@ -1377,6 +1389,18 @@ class DockAreaView(RPCBase): name (str | None): The name of the profile to load. If None, prompts the user. """ + @rpc_timeout(None) + @rpc_call + def restore_baseline_profile(self, name: "str | None" = None, show_dialog: "bool" = True): + """ + Overwrite the runtime copy of *name* with the baseline. + If *name* is None, target the currently active profile. + + Args: + name (str | None): The name of the profile to restore. If None, uses the current profile. + show_dialog (bool): If True, ask for confirmation before restoring. + """ + @rpc_call def delete_profile(self, name: "str | None" = None, show_dialog: "bool" = False) -> "bool": """ diff --git a/bec_widgets/widgets/containers/dock_area/dock_area.py b/bec_widgets/widgets/containers/dock_area/dock_area.py index 783f9b6d..434934c9 100644 --- a/bec_widgets/widgets/containers/dock_area/dock_area.py +++ b/bec_widgets/widgets/containers/dock_area/dock_area.py @@ -108,6 +108,7 @@ class BECDockArea(DockAreaWidget): "list_profiles", "save_profile", "load_profile", + "restore_baseline_profile", "delete_profile", ] @@ -896,30 +897,34 @@ class BECDockArea(DockAreaWidget): @SafeSlot() @SafeSlot(str) - def restore_runtime_profile_from_baseline(self, name: str | None = None): + @SafeSlot(str, bool) + @rpc_timeout(None) + def restore_baseline_profile(self, name: str | None = None, show_dialog: bool = True): """ Overwrite the runtime copy of *name* with the baseline. If *name* is None, target the currently active profile. Args: name (str | None): The name of the profile to restore. If None, uses the current profile. + show_dialog (bool): If True, ask for confirmation before restoring. """ target = name or getattr(self, "_current_profile_name", None) if not target: return namespace = self.profile_namespace - current_pixmap = None - if self.isVisible(): - current_pixmap = QPixmap() - ba = bytes(self.screenshot_bytes()) - current_pixmap.loadFromData(ba) - if current_pixmap is None or current_pixmap.isNull(): - current_pixmap = load_runtime_profile_screenshot(target, namespace=namespace) - baseline_pixmap = load_baseline_profile_screenshot(target, namespace=namespace) + if show_dialog: + current_pixmap = None + if self.isVisible(): + current_pixmap = QPixmap() + ba = bytes(self.screenshot_bytes()) + current_pixmap.loadFromData(ba) + if current_pixmap is None or current_pixmap.isNull(): + current_pixmap = load_runtime_profile_screenshot(target, namespace=namespace) + baseline_pixmap = load_baseline_profile_screenshot(target, namespace=namespace) - if not RestoreProfileDialog.confirm(self, current_pixmap, baseline_pixmap): - return + if not RestoreProfileDialog.confirm(self, current_pixmap, baseline_pixmap): + return restore_runtime_from_baseline(target, namespace=namespace) self.delete_all() diff --git a/bec_widgets/widgets/containers/dock_area/toolbar_components/workspace_actions.py b/bec_widgets/widgets/containers/dock_area/toolbar_components/workspace_actions.py index a7f49b5c..7cae771f 100644 --- a/bec_widgets/widgets/containers/dock_area/toolbar_components/workspace_actions.py +++ b/bec_widgets/widgets/containers/dock_area/toolbar_components/workspace_actions.py @@ -229,4 +229,4 @@ class WorkspaceConnection(BundleConnection): """ Refreshes the current workspace. """ - self.target_widget.restore_runtime_profile_from_baseline() + self.target_widget.restore_baseline_profile() diff --git a/tests/unit_tests/test_dock_area.py b/tests/unit_tests/test_dock_area.py index 46b6a117..78abd601 100644 --- a/tests/unit_tests/test_dock_area.py +++ b/tests/unit_tests/test_dock_area.py @@ -1421,7 +1421,7 @@ class TestAdvancedDockAreaRestoreAndDialogs: patch.object(advanced_dock_area, "delete_all") as mock_delete_all, patch.object(advanced_dock_area, "load_profile") as mock_load_profile, ): - advanced_dock_area.restore_runtime_profile_from_baseline() + advanced_dock_area.restore_baseline_profile() assert mock_restore.call_count == 1 args, kwargs = mock_restore.call_args @@ -1455,16 +1455,41 @@ class TestAdvancedDockAreaRestoreAndDialogs: with patch( "bec_widgets.widgets.containers.dock_area.dock_area.restore_runtime_from_baseline" ) as mock_restore: - advanced_dock_area.restore_runtime_profile_from_baseline() + advanced_dock_area.restore_baseline_profile() mock_restore.assert_not_called() + def test_restore_runtime_profile_from_baseline_without_dialog(self, advanced_dock_area): + profile_name = "alignment_scan" + helper = profile_helper(advanced_dock_area) + helper.open_baseline(profile_name).sync() + helper.open_runtime(profile_name).sync() + + with ( + patch( + "bec_widgets.widgets.containers.dock_area.dock_area.RestoreProfileDialog.confirm" + ) as mock_confirm, + patch( + "bec_widgets.widgets.containers.dock_area.dock_area.restore_runtime_from_baseline" + ) as mock_restore, + patch.object(advanced_dock_area, "delete_all") as mock_delete_all, + patch.object(advanced_dock_area, "load_profile") as mock_load_profile, + ): + advanced_dock_area.restore_baseline_profile(profile_name, show_dialog=False) + + mock_confirm.assert_not_called() + mock_restore.assert_called_once_with( + profile_name, namespace=advanced_dock_area.profile_namespace + ) + mock_delete_all.assert_called_once() + mock_load_profile.assert_called_once_with(profile_name) + def test_restore_runtime_profile_from_baseline_no_target(self, advanced_dock_area, monkeypatch): advanced_dock_area._current_profile_name = None with patch( "bec_widgets.widgets.containers.dock_area.dock_area.RestoreProfileDialog.confirm" ) as mock_confirm: - advanced_dock_area.restore_runtime_profile_from_baseline() + advanced_dock_area.restore_baseline_profile() mock_confirm.assert_not_called() def test_refresh_workspace_list_with_refresh_profiles(self, advanced_dock_area):