From 9c49c33fb75fe29a3f4966444c56fb52f51c98bf Mon Sep 17 00:00:00 2001 From: wyzula-jan Date: Tue, 12 Nov 2024 13:03:55 +0100 Subject: [PATCH] fix(dock_area): Docks can be open as temporary and do not return after closing to the parent DockArea --- bec_widgets/cli/client.py | 2 + bec_widgets/widgets/dock/dock_area.py | 15 +++-- tests/unit_tests/test_bec_dock.py | 91 +++++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 4 deletions(-) diff --git a/bec_widgets/cli/client.py b/bec_widgets/cli/client.py index 8b8d3594..4249d9a7 100644 --- a/bec_widgets/cli/client.py +++ b/bec_widgets/cli/client.py @@ -396,6 +396,7 @@ class BECDockArea(RPCBase, BECGuiClientMixin): relative_to: "BECDock | None" = None, closable: "bool" = True, floating: "bool" = False, + temporary: "bool" = False, prefix: "str" = "dock", widget: "str | QWidget | None" = None, row: "int" = None, @@ -412,6 +413,7 @@ class BECDockArea(RPCBase, BECGuiClientMixin): relative_to(BECDock): The dock to which the new dock should be added relative to. closable(bool): Whether the dock is closable. floating(bool): Whether the dock is detached after creating. + temporary(bool): Whether the dock is temporary. After closing the dock do not return to the parent DockArea. prefix(str): The prefix for the dock name if no name is provided. widget(str|QWidget|None): The widget to be added to the dock. While using RPC, only BEC RPC widgets from RPCWidgetHandler are allowed. row(int): The row of the added widget. diff --git a/bec_widgets/widgets/dock/dock_area.py b/bec_widgets/widgets/dock/dock_area.py index 3d947ff4..ce9630b7 100644 --- a/bec_widgets/widgets/dock/dock_area.py +++ b/bec_widgets/widgets/dock/dock_area.py @@ -280,6 +280,7 @@ class BECDockArea(BECWidget, QWidget): relative_to: BECDock | None = None, closable: bool = True, floating: bool = False, + temporary: bool = False, prefix: str = "dock", widget: str | QWidget | None = None, row: int = None, @@ -296,6 +297,7 @@ class BECDockArea(BECWidget, QWidget): relative_to(BECDock): The dock to which the new dock should be added relative to. closable(bool): Whether the dock is closable. floating(bool): Whether the dock is detached after creating. + temporary(bool): Whether the dock is temporary. After closing the dock do not return to the parent DockArea. prefix(str): The prefix for the dock name if no name is provided. widget(str|QWidget|None): The widget to be added to the dock. While using RPC, only BEC RPC widgets from RPCWidgetHandler are allowed. row(int): The row of the added widget. @@ -317,16 +319,21 @@ class BECDockArea(BECWidget, QWidget): if position is None: position = "bottom" + if temporary: + target_area = self.dock_area.addTempArea() + else: + target_area = self.dock_area + dock = BECDock(name=name, parent_dock_area=self, closable=closable) dock.config.position = position self.config.docks[name] = dock.config - self.dock_area.addDock(dock=dock, position=position, relativeTo=relative_to) + target_area.addDock(dock=dock, position=position, relativeTo=relative_to) - if len(self.dock_area.docks) <= 1: + if len(target_area.docks) <= 1: dock.hide_title_bar() - elif len(self.dock_area.docks) > 1: - for dock in self.dock_area.docks.values(): + elif len(target_area.docks) > 1: + for dock in target_area.docks.values(): dock.show_title_bar() if widget is not None and isinstance(widget, str): diff --git a/tests/unit_tests/test_bec_dock.py b/tests/unit_tests/test_bec_dock.py index 3fbd02af..93e2fcf3 100644 --- a/tests/unit_tests/test_bec_dock.py +++ b/tests/unit_tests/test_bec_dock.py @@ -159,3 +159,94 @@ def test_toolbar_add_utils_progress_bar(bec_dock_area): assert ( bec_dock_area.panels["progress_bar_1"].widgets[0].config.widget_class == "RingProgressBar" ) + + +################################### +# Tests for Temporary Docks +################################### +def test_add_temporary_dock(bec_dock_area, qtbot): + # Add a temporary dock + temp_dock = bec_dock_area.add_dock(name="temp_dock_1", temporary=True) + + # Check that tempAreas has one area + assert len(bec_dock_area.dock_area.tempAreas) == 1 + + # Check that the dock is in the tempArea's docks + temp_area = bec_dock_area.dock_area.tempAreas[0] + assert temp_dock.name() in temp_area.docks + + # Close the temporary dock + temp_dock.close() + qtbot.wait(100) + + # Check that tempAreas is now empty + assert len(bec_dock_area.dock_area.tempAreas) == 0 + + # Check that the dock is removed from docks + assert temp_dock.name() not in bec_dock_area.dock_area.docks + + bec_dock_area.close() + + +def test_clear_all_with_temporary_docks(bec_dock_area, qtbot): + # Add normal docks + d0 = bec_dock_area.add_dock(name="dock_0") + d1 = bec_dock_area.add_dock(name="dock_1") + # Add temporary docks + temp_dock_1 = bec_dock_area.add_dock(name="temp_dock_1", temporary=True) + temp_dock_2 = bec_dock_area.add_dock(name="temp_dock_2", temporary=True) + + # Check that tempAreas have 2 areas + assert len(bec_dock_area.dock_area.tempAreas) == 2 + + # Clear all docks + bec_dock_area.clear_all() + qtbot.wait(100) + + # Check that all docks are removed + assert len(bec_dock_area.dock_area.docks) == 0 + assert len(bec_dock_area.dock_area.tempAreas) == 0 + + +def test_attach_all_removes_temporary_docks(bec_dock_area, qtbot): + # Add normal dock + d0 = bec_dock_area.add_dock(name="dock_0") + # Add temporary dock + temp_dock = bec_dock_area.add_dock(name="temp_dock", temporary=True) + + # Detach normal dock + d0.detach() + + # Check tempAreas + assert len(bec_dock_area.dock_area.tempAreas) == 2 # One for temp_dock, one for detached d0 + + # Call attach_all + bec_dock_area.attach_all() + qtbot.wait(100) + + # Check that tempAreas is now empty + assert len(bec_dock_area.dock_area.tempAreas) == 0 + + # Check that temp_dock is not in docks + assert temp_dock.name() not in bec_dock_area.dock_area.docks + + +def test_close_temporary_dock(bec_dock_area, qtbot): + # Add temporary dock + temp_dock = bec_dock_area.add_dock(name="temp_dock", temporary=True) + + # Check tempAreas + assert len(bec_dock_area.dock_area.tempAreas) == 1 + + # Close the temporary dock + temp_dock.close() + qtbot.wait(100) + + # Check that tempAreas is now empty + assert len(bec_dock_area.dock_area.tempAreas) == 0 + + # Check that the dock is removed from docks + assert temp_dock.name() not in bec_dock_area.dock_area.docks + + # Close parent area + bec_dock_area.close()