moninj: user spawned docks

This commit is contained in:
Simon Renblad 2024-04-24 11:27:12 +08:00
parent 687c12033e
commit 2fe89fcac3
2 changed files with 70 additions and 20 deletions

View File

@ -2,12 +2,13 @@ import asyncio
import logging import logging
import textwrap import textwrap
from collections import namedtuple from collections import namedtuple
from functools import partial
from PyQt5 import QtCore, QtWidgets from PyQt5 import QtCore, QtWidgets
from artiq.coredevice.comm_moninj import CommMonInj, TTLOverride, TTLProbe from artiq.coredevice.comm_moninj import CommMonInj, TTLOverride, TTLProbe
from artiq.coredevice.ad9912_reg import AD9912_SER_CONF from artiq.coredevice.ad9912_reg import AD9912_SER_CONF
from artiq.gui.tools import LayoutWidget from artiq.gui.tools import LayoutWidget, QDockWidgetCloseDetect
from artiq.gui.flowlayout import FlowLayout from artiq.gui.flowlayout import FlowLayout
@ -782,17 +783,26 @@ class _DeviceManager:
await self.mi_connection.close() await self.mi_connection.close()
class _MonInjDock(QtWidgets.QDockWidget): class _MonInjDock(QDockWidgetCloseDetect):
def __init__(self, name): def __init__(self, name, manager):
QtWidgets.QDockWidget.__init__(self, name) QtWidgets.QDockWidget.__init__(self, "MonInj")
self.setObjectName(name) self.setObjectName(name)
self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable | self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable |
QtWidgets.QDockWidget.DockWidgetFloatable) QtWidgets.QDockWidget.DockWidgetFloatable)
self.name = name
grid = LayoutWidget()
newdock = QtWidgets.QToolButton()
newdock.setToolTip("Create new moninj dock")
newdock.setIcon(QtWidgets.QApplication.style().standardIcon(
QtWidgets.QStyle.SP_FileDialogNewFolder))
# note the lambda, the default parameter is overriden otherwise
newdock.clicked.connect(lambda: manager.create_new_dock())
grid.addWidget(newdock, 0, 0)
self.setWidget(grid)
self.scroll_area = QtWidgets.QScrollArea()
grid.addWidget(self.scroll_area, 1, 0)
def layout_widgets(self, handlers): def layout_widgets(self, handlers):
scroll_area = QtWidgets.QScrollArea()
self.setWidget(scroll_area)
grid = FlowLayout() grid = FlowLayout()
grid_widget = QtWidgets.QWidget() grid_widget = QtWidgets.QWidget()
grid_widget.setLayout(grid) grid_widget.setLayout(grid)
@ -800,16 +810,56 @@ class _MonInjDock(QtWidgets.QDockWidget):
for handler in sorted(handlers, key=lambda h: h.sort_key()): for handler in sorted(handlers, key=lambda h: h.sort_key()):
grid.addWidget(handler.widget) grid.addWidget(handler.widget)
scroll_area.setWidgetResizable(True) self.scroll_area.setWidgetResizable(True)
scroll_area.setWidget(grid_widget) self.scroll_area.setWidget(grid_widget)
class MonInj: class MonInj:
def __init__(self, schedule_ctl): def __init__(self, schedule_ctl, main_window):
self.dock = _MonInjDock("MonInj") self.docks = dict()
self.main_window = main_window
self.dm = _DeviceManager(schedule_ctl) self.dm = _DeviceManager(schedule_ctl)
self.dm.channels_cb = lambda: self.dock.layout_widgets(self.dm.handlers_by_uid.values()) self.dm.channels_cb = self.add_widgets
def add_widgets(self):
self.docks["moninj0"].layout_widgets(self.dm.handlers_by_uid.values())
def create_new_dock(self, add_to_area=True):
n = 0
name = "moninj0"
while name in self.docks:
n += 1
name = "moninj" + str(n)
dock = _MonInjDock(name, self)
self.docks[name] = dock
if add_to_area:
self.main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, dock)
dock.setFloating(True)
dock.sigClosed.connect(partial(self.on_dock_closed, name))
self.update_closable()
return dock
def on_dock_closed(self, name):
dock = self.docks[name]
dock.deleteLater()
del self.docks[name]
self.update_closable()
def update_closable(self):
flags = (QtWidgets.QDockWidget.DockWidgetMovable |
QtWidgets.QDockWidget.DockWidgetFloatable)
if len(self.docks) > 1:
flags |= QtWidgets.QDockWidget.DockWidgetClosable
for dock in self.docks.values():
dock.setFeatures(flags)
def first_moninj_dock(self):
if self.docks:
return None
dock = self.create_new_dock(False)
return dock
async def stop(self): async def stop(self):
if self.dm is not None: if self.dm is not None:

View File

@ -226,8 +226,8 @@ def main():
smgr.register(d_applets) smgr.register(d_applets)
broadcast_clients["ccb"].notify_cbs.append(d_applets.ccb_notify) broadcast_clients["ccb"].notify_cbs.append(d_applets.ccb_notify)
d_ttl_dds = moninj.MonInj(rpc_clients["schedule"]) moninj_mgr = moninj.MonInj(rpc_clients["schedule"], main_window)
atexit_register_coroutine(d_ttl_dds.stop, loop=loop) atexit_register_coroutine(moninj_mgr.stop, loop=loop)
d_waveform = waveform.WaveformDock( d_waveform = waveform.WaveformDock(
args.analyzer_proxy_timeout, args.analyzer_proxy_timeout,
@ -237,10 +237,10 @@ def main():
atexit_register_coroutine(d_waveform.stop, loop=loop) atexit_register_coroutine(d_waveform.stop, loop=loop)
def init_cbs(ddb): def init_cbs(ddb):
d_ttl_dds.dm.init_ddb(ddb) moninj_mgr.dm.init_ddb(ddb)
d_waveform.init_ddb(ddb) d_waveform.init_ddb(ddb)
return ddb return ddb
devices_sub = Subscriber("devices", init_cbs, [d_ttl_dds.dm.notify_ddb, d_waveform.notify_ddb]) devices_sub = Subscriber("devices", init_cbs, [moninj_mgr.dm.notify_ddb, d_waveform.notify_ddb])
loop.run_until_complete(devices_sub.connect(args.server, args.port_notify)) loop.run_until_complete(devices_sub.connect(args.server, args.port_notify))
atexit_register_coroutine(devices_sub.close, loop=loop) atexit_register_coroutine(devices_sub.close, loop=loop)
@ -261,12 +261,15 @@ def main():
# lay out docks # lay out docks
right_docks = [ right_docks = [
d_explorer, d_shortcuts, d_explorer, d_shortcuts,
d_ttl_dds.dock, d_datasets, d_applets, d_datasets, d_applets,
d_waveform, d_interactive_args d_waveform, d_interactive_args
] ]
main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, right_docks[0]) main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, right_docks[0])
for d1, d2 in zip(right_docks, right_docks[1:]): for d1, d2 in zip(right_docks, right_docks[1:]):
main_window.tabifyDockWidget(d1, d2) main_window.tabifyDockWidget(d1, d2)
d_moninj0 = moninj_mgr.first_moninj_dock()
if d_moninj0 is not None:
main_window.tabifyDockWidget(right_docks[-1], d_moninj0)
main_window.addDockWidget(QtCore.Qt.BottomDockWidgetArea, d_schedule) main_window.addDockWidget(QtCore.Qt.BottomDockWidgetArea, d_schedule)
# load/initialize state # load/initialize state
@ -279,9 +282,6 @@ def main():
smgr.start(loop=loop) smgr.start(loop=loop)
atexit_register_coroutine(smgr.stop, loop=loop) atexit_register_coroutine(smgr.stop, loop=loop)
# work around for https://github.com/m-labs/artiq/issues/1307
d_ttl_dds.dock.show()
# create first log dock if not already in state # create first log dock if not already in state
d_log0 = logmgr.first_log_dock() d_log0 = logmgr.first_log_dock()
if d_log0 is not None: if d_log0 is not None: