diff --git a/artiq/applets/simple.py b/artiq/applets/simple.py index 50c851cbe..94ba27c00 100644 --- a/artiq/applets/simple.py +++ b/artiq/applets/simple.py @@ -1,9 +1,10 @@ import argparse import asyncio -from quamash import QEventLoop, QtWidgets, QtCore +from quamash import QEventLoop, QtWidgets, QtGui, QtCore from artiq.protocols.sync_struct import Subscriber +from artiq.protocols.pc_rpc import Client class SimpleApplet: @@ -13,11 +14,20 @@ class SimpleApplet: self.argparser = argparse.ArgumentParser(description=cmd_description) group = self.argparser.add_argument_group("data server") group.add_argument( - "--server", default="::1", - help="hostname or IP to connect to") + "--server-notify", default="::1", + help="hostname or IP to connect to for dataset notifications") group.add_argument( - "--port", default=3250, type=int, - help="TCP port to connect to") + "--port-notify", default=3250, type=int, + help="TCP port to connect to for dataset notifications") + group = self.argparser.add_argument_group("GUI server") + group.add_argument( + "--server-gui", default="::1", + help="hostname or IP to connect to for GUI control") + group.add_argument( + "--port-gui", default=6501, type=int, + help="TCP port to connect to for GUI control") + group.add_argument("--embed", default=None, type=int, + help="embed main widget into existing window") self._arggroup_datasets = self.argparser.add_argument_group("datasets") def add_dataset(self, name, help=None): @@ -36,6 +46,22 @@ class SimpleApplet: def create_main_widget(self): self.main_widget = self.main_widget_class(self.args) + # Qt window embedding is ridiculously buggy, and empirical testing + # has shown that the following procedure must be followed exactly: + # 1. applet creates widget + # 2. applet creates native window without showing it, and get its ID + # 3. applet sends the ID to host, host embeds the widget + # 4. applet shows the widget + # Doing embedding the other way around (using QWindow.setParent in the + # applet) breaks resizing; furthermore the host needs to know our + # window ID to request graceful termination by closing the window. + if self.args.embed is not None: + win_id = int(self.main_widget.winId()) + remote = Client(self.args.server_gui, self.args.port_gui, "applets") + try: + remote.embed(self.args.embed, win_id) + finally: + remote.close_rpc() self.main_widget.show() def sub_init(self, data): @@ -49,7 +75,7 @@ class SimpleApplet: self.subscriber = Subscriber("datasets", self.sub_init, self.sub_mod) self.loop.run_until_complete(self.subscriber.connect( - self.args.server, self.args.port)) + self.args.server_notify, self.args.port_notify)) def run(self): self.args_init()