diff --git a/bec_widgets/utils/bec_widget.py b/bec_widgets/utils/bec_widget.py index ed58aeb2..dccd82ff 100644 --- a/bec_widgets/utils/bec_widget.py +++ b/bec_widgets/utils/bec_widget.py @@ -4,6 +4,7 @@ from datetime import datetime from typing import TYPE_CHECKING import darkdetect +import PySide6QtAds as QtAds import shiboken6 from bec_lib.logger import bec_logger from qtpy.QtCore import QObject @@ -14,6 +15,7 @@ from bec_widgets.utils.bec_connector import BECConnector, ConnectionConfig from bec_widgets.utils.colors import set_theme from bec_widgets.utils.error_popups import SafeSlot from bec_widgets.utils.rpc_decorator import rpc_timeout +from bec_widgets.utils.widget_io import WidgetHierarchy if TYPE_CHECKING: # pragma: no cover from bec_widgets.widgets.containers.dock import BECDock @@ -27,7 +29,7 @@ class BECWidget(BECConnector): # The icon name is the name of the icon in the icon theme, typically a name taken # from fonts.google.com/icons. Override this in subclasses to set the icon name. ICON_NAME = "widgets" - USER_ACCESS = ["remove"] + USER_ACCESS = ["remove", "attach", "detach"] # pylint: disable=too-many-arguments def __init__( @@ -124,6 +126,26 @@ class BECWidget(BECConnector): screenshot.save(file_name) logger.info(f"Screenshot saved to {file_name}") + def attach(self): + dock = WidgetHierarchy.find_ancestor(self, QtAds.CDockWidget) + if dock is None: + return + + if not dock.isFloating(): + return + dock.dockManager().addDockWidget(QtAds.DockWidgetArea.RightDockWidgetArea, dock) + + def detach(self): + """ + Detach the widget from its parent dock widget (if widget is in the dock), making it a floating widget. + """ + dock = WidgetHierarchy.find_ancestor(self, QtAds.CDockWidget) + if dock is None: + return + if dock.isFloating(): + return + dock.setFloating() + def cleanup(self): """Cleanup the widget.""" with RPCRegister.delayed_broadcast(): diff --git a/bec_widgets/widgets/control/device_control/positioner_box/positioner_box/positioner_box.py b/bec_widgets/widgets/control/device_control/positioner_box/positioner_box/positioner_box.py index 78cd5fa2..4a686d8c 100644 --- a/bec_widgets/widgets/control/device_control/positioner_box/positioner_box/positioner_box.py +++ b/bec_widgets/widgets/control/device_control/positioner_box/positioner_box/positioner_box.py @@ -33,7 +33,7 @@ class PositionerBox(PositionerBoxBase): PLUGIN = True RPC = True - USER_ACCESS = ["set_positioner", "screenshot"] + USER_ACCESS = ["set_positioner", "attach", "detach", "screenshot"] device_changed = Signal(str, str) # Signal emitted to inform listeners about a position update position_update = Signal(float) diff --git a/bec_widgets/widgets/control/device_control/positioner_box/positioner_box_2d/positioner_box_2d.py b/bec_widgets/widgets/control/device_control/positioner_box/positioner_box_2d/positioner_box_2d.py index 23630380..f0853e5b 100644 --- a/bec_widgets/widgets/control/device_control/positioner_box/positioner_box_2d/positioner_box_2d.py +++ b/bec_widgets/widgets/control/device_control/positioner_box/positioner_box_2d/positioner_box_2d.py @@ -37,6 +37,8 @@ class PositionerBox2D(PositionerBoxBase): USER_ACCESS = [ "set_positioner_hor", "set_positioner_ver", + "attach", + "detach", "screenshot", "enable_controls_hor", "enable_controls_hor.setter", diff --git a/bec_widgets/widgets/control/device_control/positioner_group/positioner_group.py b/bec_widgets/widgets/control/device_control/positioner_group/positioner_group.py index f3ac8892..e16c8371 100644 --- a/bec_widgets/widgets/control/device_control/positioner_group/positioner_group.py +++ b/bec_widgets/widgets/control/device_control/positioner_group/positioner_group.py @@ -62,7 +62,7 @@ class PositionerGroup(BECWidget, QWidget): PLUGIN = True ICON_NAME = "grid_view" - USER_ACCESS = ["set_positioners"] + USER_ACCESS = ["set_positioners", "attach", "detach", "screenshot"] # Signal emitted to inform listeners about a position update of the first positioner position_update = Signal(float) diff --git a/bec_widgets/widgets/control/scan_control/scan_control.py b/bec_widgets/widgets/control/scan_control/scan_control.py index 043250e3..27bad023 100644 --- a/bec_widgets/widgets/control/scan_control/scan_control.py +++ b/bec_widgets/widgets/control/scan_control/scan_control.py @@ -45,7 +45,7 @@ class ScanControl(BECWidget, QWidget): Widget to submit new scans to the queue. """ - USER_ACCESS = ["remove", "screenshot"] + USER_ACCESS = ["attach", "detach", "screenshot"] PLUGIN = True ICON_NAME = "tune" ARG_BOX_POSITION: int = 2 diff --git a/bec_widgets/widgets/editors/monaco/monaco_widget.py b/bec_widgets/widgets/editors/monaco/monaco_widget.py index 07600530..eb05cec7 100644 --- a/bec_widgets/widgets/editors/monaco/monaco_widget.py +++ b/bec_widgets/widgets/editors/monaco/monaco_widget.py @@ -32,6 +32,9 @@ class MonacoWidget(BECWidget, QWidget): "set_vim_mode_enabled", "set_lsp_header", "get_lsp_header", + "attach", + "detach", + "screenshot", ] def __init__(self, parent=None, config=None, client=None, gui_id=None, **kwargs): diff --git a/bec_widgets/widgets/editors/website/website.py b/bec_widgets/widgets/editors/website/website.py index 7839b789..fa9c8815 100644 --- a/bec_widgets/widgets/editors/website/website.py +++ b/bec_widgets/widgets/editors/website/website.py @@ -21,7 +21,16 @@ class WebsiteWidget(BECWidget, QWidget): PLUGIN = True ICON_NAME = "travel_explore" - USER_ACCESS = ["set_url", "get_url", "reload", "back", "forward"] + USER_ACCESS = [ + "set_url", + "get_url", + "reload", + "back", + "forward", + "attach", + "detach", + "screenshot", + ] def __init__( self, parent=None, url: str = None, config=None, client=None, gui_id=None, **kwargs diff --git a/bec_widgets/widgets/progress/ring_progress_bar/ring_progress_bar.py b/bec_widgets/widgets/progress/ring_progress_bar/ring_progress_bar.py index eeb41307..6385e387 100644 --- a/bec_widgets/widgets/progress/ring_progress_bar/ring_progress_bar.py +++ b/bec_widgets/widgets/progress/ring_progress_bar/ring_progress_bar.py @@ -92,6 +92,9 @@ class RingProgressBar(BECWidget, QWidget): "set_diameter", "reset_diameter", "enable_auto_updates", + "attach", + "detach", + "screenshot", ] def __init__( diff --git a/bec_widgets/widgets/services/bec_status_box/bec_status_box.py b/bec_widgets/widgets/services/bec_status_box/bec_status_box.py index f3268c71..04677e1a 100644 --- a/bec_widgets/widgets/services/bec_status_box/bec_status_box.py +++ b/bec_widgets/widgets/services/bec_status_box/bec_status_box.py @@ -78,7 +78,7 @@ class BECStatusBox(BECWidget, CompactPopupWidget): PLUGIN = True CORE_SERVICES = ["DeviceServer", "ScanServer", "SciHub", "ScanBundler", "FileWriterManager"] - USER_ACCESS = ["get_server_state", "remove"] + USER_ACCESS = ["get_server_state", "remove", "attach", "detach", "screenshot"] service_update = Signal(BECServiceInfoContainer) bec_core_state = Signal(str)