mirror of
https://github.com/m-labs/artiq.git
synced 2024-12-25 11:18:27 +08:00
Merge branch 'qtdocks'
This commit is contained in:
commit
b24146e680
@ -6,10 +6,8 @@ import atexit
|
||||
import os
|
||||
|
||||
import PyQt5
|
||||
from quamash import QEventLoop, QtGui, QtCore
|
||||
# pyqtgraph will pick up any already imported Qt binding.
|
||||
from pyqtgraph import dockarea
|
||||
|
||||
from quamash import QEventLoop, QtGui, QtCore, QtWidgets
|
||||
assert QtGui is PyQt5.QtGui
|
||||
|
||||
from artiq import __artiq_dir__ as artiq_dir
|
||||
from artiq.tools import *
|
||||
@ -49,10 +47,14 @@ class MainWindow(QtGui.QMainWindow):
|
||||
self.exit_request.set()
|
||||
|
||||
def save_state(self):
|
||||
return bytes(self.saveGeometry())
|
||||
return {
|
||||
"state": bytes(self.saveState()),
|
||||
"geometry": bytes(self.saveGeometry())
|
||||
}
|
||||
|
||||
def restore_state(self, state):
|
||||
self.restoreGeometry(QtCore.QByteArray(state))
|
||||
self.restoreGeometry(QtCore.QByteArray(state["geometry"]))
|
||||
self.restoreState(QtCore.QByteArray(state["state"]))
|
||||
|
||||
|
||||
def main():
|
||||
@ -87,33 +89,30 @@ def main():
|
||||
sub_clients[notifier_name] = subscriber
|
||||
|
||||
# initialize main window
|
||||
win = MainWindow(args.server)
|
||||
dock_area = dockarea.DockArea()
|
||||
smgr.register(dock_area)
|
||||
smgr.register(win)
|
||||
win.setCentralWidget(dock_area)
|
||||
main_window = MainWindow(args.server)
|
||||
smgr.register(main_window)
|
||||
status_bar = QtGui.QStatusBar()
|
||||
status_bar.showMessage("Connected to {}".format(args.server))
|
||||
win.setStatusBar(status_bar)
|
||||
main_window.setStatusBar(status_bar)
|
||||
|
||||
# create UI components
|
||||
expmgr = experiments.ExperimentManager(status_bar, dock_area,
|
||||
expmgr = experiments.ExperimentManager(main_window,
|
||||
sub_clients["explist"],
|
||||
sub_clients["schedule"],
|
||||
rpc_clients["schedule"],
|
||||
rpc_clients["experiment_db"])
|
||||
smgr.register(expmgr)
|
||||
d_shortcuts = shortcuts.ShortcutsDock(win, expmgr)
|
||||
d_shortcuts = shortcuts.ShortcutsDock(main_window, expmgr)
|
||||
smgr.register(d_shortcuts)
|
||||
d_explorer = explorer.ExplorerDock(status_bar, expmgr, d_shortcuts,
|
||||
sub_clients["explist"],
|
||||
rpc_clients["schedule"],
|
||||
rpc_clients["experiment_db"])
|
||||
d_explorer = explorer.Explorer(status_bar, expmgr, d_shortcuts,
|
||||
sub_clients["explist"],
|
||||
rpc_clients["schedule"],
|
||||
rpc_clients["experiment_db"])
|
||||
|
||||
d_datasets = datasets.DatasetsDock(win, sub_clients["datasets"],
|
||||
d_datasets = datasets.DatasetsDock(sub_clients["datasets"],
|
||||
rpc_clients["dataset_db"])
|
||||
|
||||
d_applets = applets.AppletsDock(dock_area, sub_clients["datasets"])
|
||||
d_applets = applets.AppletsDock(main_window, sub_clients["datasets"])
|
||||
atexit_register_coroutine(d_applets.stop)
|
||||
smgr.register(d_applets)
|
||||
|
||||
@ -125,21 +124,21 @@ def main():
|
||||
d_schedule = schedule.ScheduleDock(
|
||||
status_bar, rpc_clients["schedule"], sub_clients["schedule"])
|
||||
|
||||
logmgr = log.LogDockManager(dock_area, sub_clients["log"])
|
||||
logmgr = log.LogDockManager(main_window, sub_clients["log"])
|
||||
smgr.register(logmgr)
|
||||
|
||||
# lay out docks
|
||||
main_window.setCentralWidget(d_explorer)
|
||||
if os.name != "nt":
|
||||
dock_area.addDock(d_ttl_dds.dds_dock, "top")
|
||||
dock_area.addDock(d_ttl_dds.ttl_dock, "above", d_ttl_dds.dds_dock)
|
||||
dock_area.addDock(d_applets, "above", d_ttl_dds.ttl_dock)
|
||||
dock_area.addDock(d_datasets, "above", d_applets)
|
||||
main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, d_ttl_dds.dds_dock)
|
||||
main_window.tabifyDockWidget(d_ttl_dds.dds_dock, d_ttl_dds.ttl_dock)
|
||||
main_window.tabifyDockWidget(d_ttl_dds.ttl_dock, d_applets)
|
||||
main_window.tabifyDockWidget(d_applets, d_datasets)
|
||||
else:
|
||||
dock_area.addDock(d_applets, "top")
|
||||
dock_area.addDock(d_datasets, "above", d_applets)
|
||||
dock_area.addDock(d_shortcuts, "above", d_datasets)
|
||||
dock_area.addDock(d_explorer, "above", d_shortcuts)
|
||||
dock_area.addDock(d_schedule, "bottom")
|
||||
main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, d_applets)
|
||||
main_window.tabifyDockWidget(d_applets, d_datasets)
|
||||
main_window.tabifyDockWidget(d_datasets, d_shortcuts)
|
||||
main_window.addDockWidget(QtCore.Qt.BottomDockWidgetArea, d_schedule)
|
||||
|
||||
# load/initialize state
|
||||
smgr.load()
|
||||
@ -149,11 +148,11 @@ def main():
|
||||
# create first log dock if not already in state
|
||||
d_log0 = logmgr.first_log_dock()
|
||||
if d_log0 is not None:
|
||||
dock_area.addDock(d_log0, "right", d_explorer)
|
||||
main_window.tabifyDockWidget(d_shortcuts, d_log0)
|
||||
|
||||
# run
|
||||
win.show()
|
||||
loop.run_until_complete(win.exit_request.wait())
|
||||
main_window.show()
|
||||
loop.run_until_complete(main_window.exit_request.wait())
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
@ -5,10 +5,10 @@ import shlex
|
||||
from functools import partial
|
||||
|
||||
from quamash import QtCore, QtGui, QtWidgets
|
||||
from pyqtgraph import dockarea
|
||||
|
||||
from artiq.protocols.pipe_ipc import AsyncioParentComm
|
||||
from artiq.protocols import pyon
|
||||
from artiq.gui.tools import QDockWidgetCloseDetect
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@ -85,12 +85,12 @@ class AppletIPCServer(AsyncioParentComm):
|
||||
await asyncio.wait([self.server_task])
|
||||
|
||||
|
||||
class AppletDock(dockarea.Dock):
|
||||
class AppletDock(QDockWidgetCloseDetect):
|
||||
def __init__(self, datasets_sub, uid, name, command):
|
||||
dockarea.Dock.__init__(self, "applet" + str(uid),
|
||||
label="Applet: " + name,
|
||||
closable=True)
|
||||
self.setMinimumSize(QtCore.QSize(500, 400))
|
||||
QDockWidgetCloseDetect.__init__(self, "Applet: " + name)
|
||||
self.setObjectName("applet" + str(uid))
|
||||
self.setMinimumSize(QtCore.QSize(100, 100))
|
||||
|
||||
self.datasets_sub = datasets_sub
|
||||
self.applet_name = name
|
||||
self.command = command
|
||||
@ -99,7 +99,7 @@ class AppletDock(dockarea.Dock):
|
||||
|
||||
def rename(self, name):
|
||||
self.applet_name = name
|
||||
self.label.setText("Applet: " + name)
|
||||
self.setWindowTitle("Applet: " + name)
|
||||
|
||||
async def start(self):
|
||||
if self.starting_stopping:
|
||||
@ -127,7 +127,7 @@ class AppletDock(dockarea.Dock):
|
||||
self.embed_window = QtGui.QWindow.fromWinId(win_id)
|
||||
self.embed_widget = QtWidgets.QWidget.createWindowContainer(
|
||||
self.embed_window)
|
||||
self.addWidget(self.embed_widget)
|
||||
self.setWidget(self.embed_widget)
|
||||
|
||||
# HACK: This function would not be needed if Qt window embedding
|
||||
# worked correctly.
|
||||
@ -181,16 +181,17 @@ _templates = [
|
||||
]
|
||||
|
||||
|
||||
class AppletsDock(dockarea.Dock):
|
||||
def __init__(self, dock_area, datasets_sub):
|
||||
self.dock_area = dock_area
|
||||
class AppletsDock(QtWidgets.QDockWidget):
|
||||
def __init__(self, main_window, datasets_sub):
|
||||
QtWidgets.QDockWidget.__init__(self, "Applets")
|
||||
self.setObjectName("Applets")
|
||||
self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable |
|
||||
QtWidgets.QDockWidget.DockWidgetFloatable)
|
||||
|
||||
self.main_window = main_window
|
||||
self.datasets_sub = datasets_sub
|
||||
self.dock_to_checkbox = dict()
|
||||
self.applet_uids = set()
|
||||
self.workaround_pyqtgraph_bug = False
|
||||
|
||||
dockarea.Dock.__init__(self, "Applets")
|
||||
self.setMinimumSize(QtCore.QSize(850, 450))
|
||||
|
||||
self.table = QtWidgets.QTableWidget(0, 3)
|
||||
self.table.setHorizontalHeaderLabels(["Enable", "Name", "Command"])
|
||||
@ -203,7 +204,7 @@ class AppletsDock(dockarea.Dock):
|
||||
QtGui.QHeaderView.ResizeToContents)
|
||||
self.table.verticalHeader().hide()
|
||||
self.table.setTextElideMode(QtCore.Qt.ElideNone)
|
||||
self.addWidget(self.table)
|
||||
self.setWidget(self.table)
|
||||
|
||||
self.table.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu)
|
||||
new_action = QtGui.QAction("New applet", self.table)
|
||||
@ -232,12 +233,8 @@ class AppletsDock(dockarea.Dock):
|
||||
|
||||
def create(self, uid, name, command):
|
||||
dock = AppletDock(self.datasets_sub, uid, name, command)
|
||||
# If a dock is floated and then dock state is restored, pyqtgraph
|
||||
# leaves a "phantom" window open.
|
||||
if self.workaround_pyqtgraph_bug:
|
||||
self.dock_area.addDock(dock)
|
||||
else:
|
||||
self.dock_area.floatDock(dock)
|
||||
self.main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, dock)
|
||||
dock.setFloating(True)
|
||||
asyncio.ensure_future(dock.start())
|
||||
dock.sigClosed.connect(partial(self.on_dock_closed, dock))
|
||||
return dock
|
||||
@ -340,7 +337,6 @@ class AppletsDock(dockarea.Dock):
|
||||
return state
|
||||
|
||||
def restore_state(self, state):
|
||||
self.workaround_pyqtgraph_bug = True
|
||||
for uid, enabled, name, command in state:
|
||||
row = self.new(uid)
|
||||
item = QtWidgets.QTableWidgetItem()
|
||||
@ -351,4 +347,3 @@ class AppletsDock(dockarea.Dock):
|
||||
self.table.setItem(row, 2, item)
|
||||
if enabled:
|
||||
self.table.item(row, 0).setCheckState(QtCore.Qt.Checked)
|
||||
self.workaround_pyqtgraph_bug = False
|
||||
|
@ -3,8 +3,7 @@ from collections import OrderedDict
|
||||
from functools import partial
|
||||
import logging
|
||||
|
||||
from quamash import QtGui, QtCore
|
||||
from pyqtgraph import dockarea
|
||||
from quamash import QtGui, QtCore, QtWidgets
|
||||
from pyqtgraph import LayoutWidget
|
||||
|
||||
from artiq.tools import short_format
|
||||
@ -29,14 +28,16 @@ class Model(DictSyncTreeSepModel):
|
||||
raise ValueError
|
||||
|
||||
|
||||
class DatasetsDock(dockarea.Dock):
|
||||
def __init__(self, dialog_parent, datasets_sub, dataset_ctl):
|
||||
dockarea.Dock.__init__(self, "Datasets")
|
||||
self.dialog_parent = dialog_parent
|
||||
class DatasetsDock(QtWidgets.QDockWidget):
|
||||
def __init__(self, datasets_sub, dataset_ctl):
|
||||
QtWidgets.QDockWidget.__init__(self, "Datasets")
|
||||
self.setObjectName("Datasets")
|
||||
self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable |
|
||||
QtWidgets.QDockWidget.DockWidgetFloatable)
|
||||
self.dataset_ctl = dataset_ctl
|
||||
|
||||
grid = LayoutWidget()
|
||||
self.addWidget(grid)
|
||||
self.setWidget(grid)
|
||||
|
||||
self.search = QtGui.QLineEdit()
|
||||
self.search.setPlaceholderText("search...")
|
||||
|
@ -3,11 +3,11 @@ import asyncio
|
||||
from functools import partial
|
||||
from collections import OrderedDict
|
||||
|
||||
from quamash import QtGui, QtCore
|
||||
from quamash import QtGui, QtCore, QtWidgets
|
||||
|
||||
from pyqtgraph import dockarea, LayoutWidget
|
||||
from pyqtgraph import LayoutWidget
|
||||
|
||||
from artiq.gui.tools import log_level_to_name
|
||||
from artiq.gui.tools import log_level_to_name, QDockWidgetCloseDetect
|
||||
from artiq.gui.entries import argty_to_entry
|
||||
|
||||
|
||||
@ -133,10 +133,16 @@ class _ArgumentEditor(QtGui.QTreeWidget):
|
||||
pass
|
||||
|
||||
|
||||
class _ExperimentDock(dockarea.Dock):
|
||||
class _ExperimentDock(QDockWidgetCloseDetect):
|
||||
def __init__(self, manager, expurl):
|
||||
dockarea.Dock.__init__(self, "Exp: " + expurl, closable=True)
|
||||
self.setMinimumSize(QtCore.QSize(740, 470))
|
||||
name = "Exp: " + expurl
|
||||
QDockWidgetCloseDetect.__init__(self, name)
|
||||
self.setObjectName(name)
|
||||
|
||||
self.layout = QtWidgets.QGridLayout()
|
||||
top_widget = QtWidgets.QWidget()
|
||||
top_widget.setLayout(self.layout)
|
||||
self.setWidget(top_widget)
|
||||
self.layout.setSpacing(5)
|
||||
self.layout.setContentsMargins(5, 5, 5, 5)
|
||||
|
||||
@ -144,7 +150,7 @@ class _ExperimentDock(dockarea.Dock):
|
||||
self.expurl = expurl
|
||||
|
||||
self.argeditor = _ArgumentEditor(self.manager, self, self.expurl)
|
||||
self.addWidget(self.argeditor, 0, 0, colspan=5)
|
||||
self.layout.addWidget(self.argeditor, 0, 0, 1, 5)
|
||||
self.layout.setRowStretch(0, 1)
|
||||
|
||||
scheduling = manager.get_submission_scheduling(expurl)
|
||||
@ -153,8 +159,8 @@ class _ExperimentDock(dockarea.Dock):
|
||||
datetime = QtGui.QDateTimeEdit()
|
||||
datetime.setDisplayFormat("MMM d yyyy hh:mm:ss")
|
||||
datetime_en = QtGui.QCheckBox("Due date:")
|
||||
self.addWidget(datetime_en, 1, 0)
|
||||
self.addWidget(datetime, 1, 1)
|
||||
self.layout.addWidget(datetime_en, 1, 0)
|
||||
self.layout.addWidget(datetime, 1, 1)
|
||||
|
||||
if scheduling["due_date"] is None:
|
||||
datetime.setDate(QtCore.QDate.currentDate())
|
||||
@ -175,8 +181,8 @@ class _ExperimentDock(dockarea.Dock):
|
||||
datetime_en.stateChanged.connect(update_datetime_en)
|
||||
|
||||
pipeline_name = QtGui.QLineEdit()
|
||||
self.addWidget(QtGui.QLabel("Pipeline:"), 1, 2)
|
||||
self.addWidget(pipeline_name, 1, 3)
|
||||
self.layout.addWidget(QtGui.QLabel("Pipeline:"), 1, 2)
|
||||
self.layout.addWidget(pipeline_name, 1, 3)
|
||||
|
||||
pipeline_name.setText(scheduling["pipeline_name"])
|
||||
def update_pipeline_name(text):
|
||||
@ -185,8 +191,8 @@ class _ExperimentDock(dockarea.Dock):
|
||||
|
||||
priority = QtGui.QSpinBox()
|
||||
priority.setRange(-99, 99)
|
||||
self.addWidget(QtGui.QLabel("Priority:"), 2, 0)
|
||||
self.addWidget(priority, 2, 1)
|
||||
self.layout.addWidget(QtGui.QLabel("Priority:"), 2, 0)
|
||||
self.layout.addWidget(priority, 2, 1)
|
||||
|
||||
priority.setValue(scheduling["priority"])
|
||||
def update_priority(value):
|
||||
@ -195,7 +201,7 @@ class _ExperimentDock(dockarea.Dock):
|
||||
|
||||
flush = QtGui.QCheckBox("Flush")
|
||||
flush.setToolTip("Flush the pipeline before starting the experiment")
|
||||
self.addWidget(flush, 2, 2, colspan=2)
|
||||
self.layout.addWidget(flush, 2, 2, 1, 2)
|
||||
|
||||
flush.setChecked(scheduling["flush"])
|
||||
def update_flush(checked):
|
||||
@ -209,8 +215,8 @@ class _ExperimentDock(dockarea.Dock):
|
||||
log_level.setToolTip("Minimum level for log entry production")
|
||||
log_level_label = QtGui.QLabel("Logging level:")
|
||||
log_level_label.setToolTip("Minimum level for log message production")
|
||||
self.addWidget(log_level_label, 3, 0)
|
||||
self.addWidget(log_level, 3, 1)
|
||||
self.layout.addWidget(log_level_label, 3, 0)
|
||||
self.layout.addWidget(log_level, 3, 1)
|
||||
|
||||
log_level.setCurrentIndex(log_levels.index(
|
||||
log_level_to_name(options["log_level"])))
|
||||
@ -224,8 +230,8 @@ class _ExperimentDock(dockarea.Dock):
|
||||
repo_rev_label = QtGui.QLabel("Revision:")
|
||||
repo_rev_label.setToolTip("Experiment repository revision "
|
||||
"(commit ID) to use")
|
||||
self.addWidget(repo_rev_label, 3, 2)
|
||||
self.addWidget(repo_rev, 3, 3)
|
||||
self.layout.addWidget(repo_rev_label, 3, 2)
|
||||
self.layout.addWidget(repo_rev, 3, 3)
|
||||
|
||||
if options["repo_rev"] is not None:
|
||||
repo_rev.setText(options["repo_rev"])
|
||||
@ -243,7 +249,7 @@ class _ExperimentDock(dockarea.Dock):
|
||||
submit.setShortcut("CTRL+RETURN")
|
||||
submit.setSizePolicy(QtGui.QSizePolicy.Expanding,
|
||||
QtGui.QSizePolicy.Expanding)
|
||||
self.addWidget(submit, 1, 4, rowspan=2)
|
||||
self.layout.addWidget(submit, 1, 4, 2, 1)
|
||||
submit.clicked.connect(self.submit_clicked)
|
||||
|
||||
reqterm = QtGui.QPushButton("Terminate instances")
|
||||
@ -253,7 +259,7 @@ class _ExperimentDock(dockarea.Dock):
|
||||
reqterm.setShortcut("CTRL+BACKSPACE")
|
||||
reqterm.setSizePolicy(QtGui.QSizePolicy.Expanding,
|
||||
QtGui.QSizePolicy.Expanding)
|
||||
self.addWidget(reqterm, 3, 4)
|
||||
self.layout.addWidget(reqterm, 3, 4)
|
||||
reqterm.clicked.connect(self.reqterm_clicked)
|
||||
|
||||
def submit_clicked(self):
|
||||
@ -287,7 +293,7 @@ class _ExperimentDock(dockarea.Dock):
|
||||
|
||||
self.argeditor.deleteLater()
|
||||
self.argeditor = _ArgumentEditor(self.manager, self, self.expurl)
|
||||
self.addWidget(self.argeditor, 0, 0, colspan=5)
|
||||
self.layout.addWidget(self.argeditor, 0, 0, 1, 5)
|
||||
|
||||
def save_state(self):
|
||||
return self.argeditor.save_state()
|
||||
@ -297,11 +303,10 @@ class _ExperimentDock(dockarea.Dock):
|
||||
|
||||
|
||||
class ExperimentManager:
|
||||
def __init__(self, status_bar, dock_area,
|
||||
def __init__(self, main_window,
|
||||
explist_sub, schedule_sub,
|
||||
schedule_ctl, experiment_db_ctl):
|
||||
self.status_bar = status_bar
|
||||
self.dock_area = dock_area
|
||||
self.main_window = main_window
|
||||
self.schedule_ctl = schedule_ctl
|
||||
self.experiment_db_ctl = experiment_db_ctl
|
||||
|
||||
@ -385,11 +390,12 @@ class ExperimentManager:
|
||||
def open_experiment(self, expurl):
|
||||
if expurl in self.open_experiments:
|
||||
dock = self.open_experiments[expurl]
|
||||
self.dock_area.floatDock(dock)
|
||||
dock.setFloating(True)
|
||||
return dock
|
||||
dock = _ExperimentDock(self, expurl)
|
||||
self.open_experiments[expurl] = dock
|
||||
self.dock_area.floatDock(dock)
|
||||
self.main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, dock)
|
||||
dock.setFloating(True)
|
||||
dock.sigClosed.connect(partial(self.on_dock_closed, expurl))
|
||||
return dock
|
||||
|
||||
@ -398,7 +404,8 @@ class ExperimentManager:
|
||||
|
||||
async def _submit_task(self, *args):
|
||||
rid = await self.schedule_ctl.submit(*args)
|
||||
self.status_bar.showMessage("Submitted RID {}".format(rid))
|
||||
self.main_window.statusBar().showMessage(
|
||||
"Submitted RID {}".format(rid))
|
||||
|
||||
def submit(self, expurl):
|
||||
file, class_name, _ = self.resolve_expurl(expurl)
|
||||
@ -436,8 +443,9 @@ class ExperimentManager:
|
||||
rid, exc_info=True)
|
||||
|
||||
def request_inst_term(self, expurl):
|
||||
self.status_bar.showMessage("Requesting termination of all instances "
|
||||
"of '{}'".format(expurl))
|
||||
self.main_window.statusBar().showMessage(
|
||||
"Requesting termination of all instances "
|
||||
"of '{}'".format(expurl))
|
||||
file, class_name, use_repository = self.resolve_expurl(expurl)
|
||||
rids = []
|
||||
for rid, desc in self.schedule.items():
|
||||
|
@ -2,8 +2,7 @@ import asyncio
|
||||
import logging
|
||||
from functools import partial
|
||||
|
||||
from quamash import QtGui, QtCore
|
||||
from pyqtgraph import dockarea
|
||||
from quamash import QtGui, QtCore, QtWidgets
|
||||
from pyqtgraph import LayoutWidget
|
||||
|
||||
from artiq.gui.models import DictSyncTreeSepModel
|
||||
@ -116,13 +115,15 @@ class Model(DictSyncTreeSepModel):
|
||||
DictSyncTreeSepModel.__init__(self, "/", ["Experiment"], init)
|
||||
|
||||
|
||||
class ExplorerDock(dockarea.Dock):
|
||||
class Explorer(QtWidgets.QWidget):
|
||||
def __init__(self, status_bar, exp_manager, d_shortcuts,
|
||||
explist_sub, schedule_ctl, experiment_db_ctl):
|
||||
dockarea.Dock.__init__(self, "Explorer")
|
||||
self.setMinimumSize(QtCore.QSize(300, 300))
|
||||
self.layout.setSpacing(5)
|
||||
self.layout.setContentsMargins(5, 5, 5, 5)
|
||||
QtWidgets.QWidget.__init__(self)
|
||||
|
||||
layout = QtWidgets.QGridLayout()
|
||||
self.setLayout(layout)
|
||||
layout.setSpacing(5)
|
||||
layout.setContentsMargins(5, 5, 5, 5)
|
||||
|
||||
self.status_bar = status_bar
|
||||
self.exp_manager = exp_manager
|
||||
@ -132,7 +133,7 @@ class ExplorerDock(dockarea.Dock):
|
||||
self.el = QtGui.QTreeView()
|
||||
self.el.setHeaderHidden(True)
|
||||
self.el.setSelectionBehavior(QtGui.QAbstractItemView.SelectItems)
|
||||
self.addWidget(self.el, 0, 0, colspan=2)
|
||||
layout.addWidget(self.el, 0, 0, 1, 2)
|
||||
self.el.doubleClicked.connect(
|
||||
partial(self.expname_action, "open_experiment"))
|
||||
|
||||
@ -140,7 +141,7 @@ class ExplorerDock(dockarea.Dock):
|
||||
open.setIcon(QtGui.QApplication.style().standardIcon(
|
||||
QtGui.QStyle.SP_DialogOpenButton))
|
||||
open.setToolTip("Open the selected experiment (Return)")
|
||||
self.addWidget(open, 1, 0)
|
||||
layout.addWidget(open, 1, 0)
|
||||
open.clicked.connect(
|
||||
partial(self.expname_action, "open_experiment"))
|
||||
|
||||
@ -148,7 +149,7 @@ class ExplorerDock(dockarea.Dock):
|
||||
submit.setIcon(QtGui.QApplication.style().standardIcon(
|
||||
QtGui.QStyle.SP_DialogOkButton))
|
||||
submit.setToolTip("Schedule the selected experiment (Ctrl+Return)")
|
||||
self.addWidget(submit, 1, 1)
|
||||
layout.addWidget(submit, 1, 1)
|
||||
submit.clicked.connect(
|
||||
partial(self.expname_action, "submit"))
|
||||
|
||||
|
@ -4,10 +4,10 @@ import time
|
||||
import re
|
||||
from functools import partial
|
||||
|
||||
from quamash import QtGui, QtCore
|
||||
from pyqtgraph import dockarea, LayoutWidget
|
||||
from quamash import QtGui, QtCore, QtWidgets
|
||||
from pyqtgraph import LayoutWidget
|
||||
|
||||
from artiq.gui.tools import log_level_to_name
|
||||
from artiq.gui.tools import log_level_to_name, QDockWidgetCloseDetect
|
||||
|
||||
|
||||
def _make_wrappable(row, width=30):
|
||||
@ -140,13 +140,13 @@ class _LogFilterProxyModel(QtCore.QSortFilterProxyModel):
|
||||
self.invalidateFilter()
|
||||
|
||||
|
||||
class _LogDock(dockarea.Dock):
|
||||
class _LogDock(QDockWidgetCloseDetect):
|
||||
def __init__(self, manager, name, log_sub):
|
||||
dockarea.Dock.__init__(self, name, label="Log")
|
||||
self.setMinimumSize(QtCore.QSize(720, 250))
|
||||
QDockWidgetCloseDetect.__init__(self, "Log")
|
||||
self.setObjectName(name)
|
||||
|
||||
grid = LayoutWidget()
|
||||
self.addWidget(grid)
|
||||
self.setWidget(grid)
|
||||
|
||||
grid.addWidget(QtGui.QLabel("Minimum level: "), 0, 0)
|
||||
self.filter_level = QtGui.QComboBox()
|
||||
@ -279,8 +279,8 @@ class _LogDock(dockarea.Dock):
|
||||
|
||||
|
||||
class LogDockManager:
|
||||
def __init__(self, dock_area, log_sub):
|
||||
self.dock_area = dock_area
|
||||
def __init__(self, main_window, log_sub):
|
||||
self.main_window = main_window
|
||||
self.log_sub = log_sub
|
||||
self.docks = dict()
|
||||
|
||||
@ -294,7 +294,8 @@ class LogDockManager:
|
||||
dock = _LogDock(self, name, self.log_sub)
|
||||
self.docks[name] = dock
|
||||
if add_to_area:
|
||||
self.dock_area.floatDock(dock)
|
||||
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
|
||||
@ -304,9 +305,12 @@ class LogDockManager:
|
||||
self.update_closable()
|
||||
|
||||
def update_closable(self):
|
||||
closable = len(self.docks) > 1
|
||||
flags = (QtWidgets.QDockWidget.DockWidgetMovable |
|
||||
QtWidgets.QDockWidget.DockWidgetFloatable)
|
||||
if len(self.docks) > 1:
|
||||
flags |= QtWidgets.QDockWidget.DockWidgetClosable
|
||||
for dock in self.docks.values():
|
||||
dock.setClosable(closable)
|
||||
dock.setFeatures(flags)
|
||||
|
||||
def save_state(self):
|
||||
return {name: dock.save_state() for name, dock in self.docks.items()}
|
||||
@ -317,8 +321,9 @@ class LogDockManager:
|
||||
for name, dock_state in state.items():
|
||||
dock = _LogDock(self, name, self.log_sub)
|
||||
dock.restore_state(dock_state)
|
||||
self.dock_area.addDock(dock)
|
||||
self.main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, dock)
|
||||
self.docks[name] = dock
|
||||
self.update_closable()
|
||||
|
||||
def first_log_dock(self):
|
||||
if self.docks:
|
||||
|
@ -4,8 +4,7 @@ import socket
|
||||
import struct
|
||||
from operator import itemgetter
|
||||
|
||||
from quamash import QtGui, QtCore
|
||||
from pyqtgraph import dockarea
|
||||
from quamash import QtGui, QtCore, QtWidgets
|
||||
|
||||
from artiq.tools import TaskObject
|
||||
from artiq.protocols.sync_struct import Subscriber
|
||||
@ -213,14 +212,17 @@ class _DeviceManager:
|
||||
return None
|
||||
|
||||
|
||||
class _MonInjDock(dockarea.Dock):
|
||||
class _MonInjDock(QtWidgets.QDockWidget):
|
||||
def __init__(self, name):
|
||||
dockarea.Dock.__init__(self, name)
|
||||
QtWidgets.QDockWidget.__init__(self, name)
|
||||
self.setObjectName(name)
|
||||
self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable |
|
||||
QtWidgets.QDockWidget.DockWidgetFloatable)
|
||||
|
||||
self.grid = QtGui.QGridLayout()
|
||||
gridw = QtGui.QWidget()
|
||||
gridw.setLayout(self.grid)
|
||||
self.addWidget(gridw)
|
||||
self.setWidget(gridw)
|
||||
|
||||
def layout_widgets(self, widgets):
|
||||
w = self.grid.itemAt(0)
|
||||
|
@ -2,7 +2,7 @@ import asyncio
|
||||
import time
|
||||
from functools import partial
|
||||
|
||||
from quamash import QtGui, QtCore
|
||||
from quamash import QtGui, QtCore, QtWidgets
|
||||
from pyqtgraph import dockarea
|
||||
|
||||
from artiq.gui.models import DictSyncModel
|
||||
@ -55,10 +55,12 @@ class Model(DictSyncModel):
|
||||
raise ValueError
|
||||
|
||||
|
||||
class ScheduleDock(dockarea.Dock):
|
||||
class ScheduleDock(QtWidgets.QDockWidget):
|
||||
def __init__(self, status_bar, schedule_ctl, schedule_sub):
|
||||
dockarea.Dock.__init__(self, "Schedule")
|
||||
self.setMinimumSize(QtCore.QSize(740, 200))
|
||||
QtWidgets.QDockWidget.__init__(self, "Schedule")
|
||||
self.setObjectName("Schedule")
|
||||
self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable |
|
||||
QtWidgets.QDockWidget.DockWidgetFloatable)
|
||||
|
||||
self.status_bar = status_bar
|
||||
self.schedule_ctl = schedule_ctl
|
||||
@ -71,7 +73,7 @@ class ScheduleDock(dockarea.Dock):
|
||||
self.table.verticalHeader().setResizeMode(
|
||||
QtGui.QHeaderView.ResizeToContents)
|
||||
self.table.verticalHeader().hide()
|
||||
self.addWidget(self.table)
|
||||
self.setWidget(self.table)
|
||||
|
||||
self.table.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu)
|
||||
request_termination_action = QtGui.QAction("Request termination", self.table)
|
||||
|
@ -2,53 +2,61 @@ import logging
|
||||
from functools import partial
|
||||
|
||||
from quamash import QtGui, QtCore, QtWidgets
|
||||
from pyqtgraph import dockarea
|
||||
from pyqtgraph import LayoutWidget
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ShortcutsDock(dockarea.Dock):
|
||||
class ShortcutsDock(QtWidgets.QDockWidget):
|
||||
def __init__(self, main_window, exp_manager):
|
||||
dockarea.Dock.__init__(self, "Shortcuts")
|
||||
self.layout.setSpacing(5)
|
||||
self.layout.setContentsMargins(5, 5, 5, 5)
|
||||
QtWidgets.QDockWidget.__init__(self, "Shortcuts")
|
||||
self.setObjectName("Shortcuts")
|
||||
self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable |
|
||||
QtWidgets.QDockWidget.DockWidgetFloatable)
|
||||
|
||||
layout = QtWidgets.QGridLayout()
|
||||
top_widget = QtWidgets.QWidget()
|
||||
top_widget.setLayout(layout)
|
||||
self.setWidget(top_widget)
|
||||
layout.setSpacing(5)
|
||||
layout.setContentsMargins(5, 5, 5, 5)
|
||||
|
||||
self.exp_manager = exp_manager
|
||||
self.shortcut_widgets = dict()
|
||||
|
||||
for n, title in enumerate(["Key", "Experiment"]):
|
||||
label = QtGui.QLabel("<b>" + title + "</b>")
|
||||
self.addWidget(label, 0, n)
|
||||
layout.addWidget(label, 0, n)
|
||||
label.setMaximumHeight(label.sizeHint().height())
|
||||
self.layout.setColumnStretch(1, 1)
|
||||
layout.setColumnStretch(1, 1)
|
||||
|
||||
for i in range(12):
|
||||
row = i + 1
|
||||
|
||||
self.addWidget(QtGui.QLabel("F" + str(i+1)), row, 0)
|
||||
layout.addWidget(QtGui.QLabel("F" + str(i+1)), row, 0)
|
||||
|
||||
label = QtGui.QLabel()
|
||||
label.setSizePolicy(QtGui.QSizePolicy.Ignored,
|
||||
QtGui.QSizePolicy.Ignored)
|
||||
self.addWidget(label, row, 1)
|
||||
layout.addWidget(label, row, 1)
|
||||
|
||||
clear = QtGui.QToolButton()
|
||||
clear.setIcon(QtGui.QApplication.style().standardIcon(
|
||||
QtGui.QStyle.SP_DialogResetButton))
|
||||
self.addWidget(clear, row, 2)
|
||||
layout.addWidget(clear, row, 2)
|
||||
clear.clicked.connect(partial(self.set_shortcut, i, ""))
|
||||
|
||||
open = QtGui.QToolButton()
|
||||
open.setIcon(QtGui.QApplication.style().standardIcon(
|
||||
QtGui.QStyle.SP_DialogOpenButton))
|
||||
self.addWidget(open, row, 3)
|
||||
layout.addWidget(open, row, 3)
|
||||
open.clicked.connect(partial(self._open_experiment, i))
|
||||
|
||||
submit = QtGui.QPushButton("Submit")
|
||||
submit.setIcon(QtGui.QApplication.style().standardIcon(
|
||||
QtGui.QStyle.SP_DialogOkButton))
|
||||
self.addWidget(submit, row, 4)
|
||||
layout.addWidget(submit, row, 4)
|
||||
submit.clicked.connect(partial(self._activated, i))
|
||||
|
||||
clear.hide()
|
||||
|
@ -1,6 +1,6 @@
|
||||
import logging
|
||||
|
||||
from quamash import QtCore
|
||||
from PyQt5 import QtCore, QtWidgets, QtGui
|
||||
|
||||
|
||||
def log_level_to_name(level):
|
||||
@ -27,3 +27,11 @@ class _WheelFilter(QtCore.QObject):
|
||||
def disable_scroll_wheel(widget):
|
||||
widget.setFocusPolicy(QtCore.Qt.StrongFocus)
|
||||
widget.installEventFilter(_WheelFilter(widget))
|
||||
|
||||
|
||||
class QDockWidgetCloseDetect(QtWidgets.QDockWidget):
|
||||
sigClosed = QtCore.pyqtSignal()
|
||||
|
||||
def closeEvent(self, event):
|
||||
self.sigClosed.emit()
|
||||
QtWidgets.QDockWidget.closeEvent(self, event)
|
||||
|
Loading…
Reference in New Issue
Block a user