diff --git a/bec_widgets/cli/client_utils.py b/bec_widgets/cli/client_utils.py index d6a679a1..27746f49 100644 --- a/bec_widgets/cli/client_utils.py +++ b/bec_widgets/cli/client_utils.py @@ -31,7 +31,8 @@ logger = bec_logger.logger IGNORE_WIDGETS = ["LaunchWindow"] RegistryState: TypeAlias = dict[ - Literal["gui_id", "name", "widget_class", "config", "__rpc__"], str | bool | dict + Literal["gui_id", "name", "widget_class", "config", "__rpc__", "container_proxy"], + str | bool | dict, ] # pylint: disable=redefined-outer-scope diff --git a/bec_widgets/cli/rpc/rpc_base.py b/bec_widgets/cli/rpc/rpc_base.py index ea86027e..db7918eb 100644 --- a/bec_widgets/cli/rpc/rpc_base.py +++ b/bec_widgets/cli/rpc/rpc_base.py @@ -130,6 +130,7 @@ class RPCBase: config: dict | None = None, object_name: str | None = None, parent=None, + **kwargs, ) -> None: self._client = BECClient() # BECClient is a singleton; here, we simply get the instance self._config = config if config is not None else {} @@ -150,6 +151,13 @@ class RPCBase: """ Remove the widget. """ + obj = self._root._server_registry.get(self._gui_id) + if obj is None: + raise ValueError(f"Widget {self._gui_id} not found.") + if proxy := obj.get("container_proxy"): + assert isinstance(proxy, str) + self._run_rpc("remove", gui_id=proxy) + return self._run_rpc("remove") @property @@ -164,7 +172,15 @@ class RPCBase: parent = parent._parent return parent # type: ignore - def _run_rpc(self, method, *args, wait_for_rpc_response=True, timeout=5, **kwargs) -> Any: + def _run_rpc( + self, + method, + *args, + wait_for_rpc_response=True, + timeout=5, + gui_id: str | None = None, + **kwargs, + ) -> Any: """ Run the RPC call. @@ -172,6 +188,8 @@ class RPCBase: method: The method to call. args: The arguments to pass to the method. wait_for_rpc_response: Whether to wait for the RPC response. + timeout: The timeout for the RPC response. + gui_id: The GUI ID to use for the RPC call. If None, the default GUI ID is used. kwargs: The keyword arguments to pass to the method. Returns: @@ -180,7 +198,7 @@ class RPCBase: request_id = str(uuid.uuid4()) rpc_msg = messages.GUIInstructionMessage( action=method, - parameter={"args": args, "kwargs": kwargs, "gui_id": self._gui_id}, + parameter={"args": args, "kwargs": kwargs, "gui_id": gui_id or self._gui_id}, metadata={"request_id": request_id}, ) # pylint: disable=protected-access diff --git a/bec_widgets/utils/rpc_server.py b/bec_widgets/utils/rpc_server.py index c6ee70d1..1121aad0 100644 --- a/bec_widgets/utils/rpc_server.py +++ b/bec_widgets/utils/rpc_server.py @@ -18,6 +18,7 @@ from bec_widgets.cli.rpc.rpc_register import RPCRegister from bec_widgets.utils import BECDispatcher from bec_widgets.utils.bec_connector import BECConnector from bec_widgets.utils.error_popups import ErrorPopupUtility +from bec_widgets.widgets.containers.main_window.main_window import BECMainWindow if TYPE_CHECKING: # pragma: no cover from bec_lib import messages @@ -212,6 +213,15 @@ class RPCServer: config_dict = connector.config.model_dump() config_dict["parent_id"] = getattr(connector, "parent_id", None) + try: + parent = connector.parent() + if isinstance(parent, BECMainWindow): + container_proxy = parent.gui_id + else: + container_proxy = None + except Exception: + container_proxy = None + if wait: while not self.rpc_register.object_is_registered(connector): QApplication.processEvents() @@ -225,6 +235,7 @@ class RPCServer: "object_name": connector.object_name or connector.__class__.__name__, "widget_class": widget_class, "config": config_dict, + "container_proxy": container_proxy, "__rpc__": True, }