forked from M-Labs/artiq
1
0
Fork 0
artiq/artiq/gui/results.py

148 lines
4.6 KiB
Python

import asyncio
from collections import OrderedDict
from functools import partial
import logging
from quamash import QtGui, QtCore
from pyqtgraph import dockarea
from pyqtgraph import LayoutWidget
from artiq.protocols.sync_struct import Subscriber
from artiq.gui.tools import DictSyncModel, short_format
from artiq.gui.displays import *
logger = logging.getLogger(__name__)
class ResultsModel(DictSyncModel):
def __init__(self, parent, init):
DictSyncModel.__init__(self, ["Result", "Value"],
parent, init)
def sort_key(self, k, v):
return k
def convert(self, k, v, column):
if column == 0:
return k
elif column == 1:
return short_format(v)
else:
raise ValueError
def _get_display_type_name(display_cls):
for name, (_, cls) in display_types.items():
if cls is display_cls:
return name
class ResultsDock(dockarea.Dock):
def __init__(self, dialog_parent, dock_area):
dockarea.Dock.__init__(self, "Results", size=(1500, 500))
self.dialog_parent = dialog_parent
self.dock_area = dock_area
grid = LayoutWidget()
self.addWidget(grid)
self.table = QtGui.QTableView()
self.table.setSelectionMode(QtGui.QAbstractItemView.NoSelection)
self.table.horizontalHeader().setResizeMode(
QtGui.QHeaderView.ResizeToContents)
grid.addWidget(self.table, 0, 0)
add_display_box = QtGui.QGroupBox("Add display")
grid.addWidget(add_display_box, 0, 1)
display_grid = QtGui.QGridLayout()
add_display_box.setLayout(display_grid)
for n, name in enumerate(display_types.keys()):
btn = QtGui.QPushButton(name)
display_grid.addWidget(btn, n, 0)
btn.clicked.connect(partial(self.create_dialog, name))
self.displays = dict()
def get_result(self, key):
return self.table_model.backing_store[key]
@asyncio.coroutine
def sub_connect(self, host, port):
self.subscriber = Subscriber("rt_results", self.init_results_model,
self.on_mod)
yield from self.subscriber.connect(host, port)
@asyncio.coroutine
def sub_close(self):
yield from self.subscriber.close()
def init_results_model(self, init):
self.table_model = ResultsModel(self.table, init)
self.table.setModel(self.table_model)
return self.table_model
def on_mod(self, mod):
if mod["action"] == "init":
for display in self.displays.values():
display.update_data(self.table_model.backing_store)
return
if mod["action"] == "setitem":
source = mod["key"]
elif mod["path"]:
source = mod["path"][0]
else:
return
for display in self.displays.values():
if source in display.data_sources():
display.update_data(self.table_model.backing_store)
def create_dialog(self, ty):
dlg_class = display_types[ty][0]
dlg = dlg_class(self.dialog_parent, None, dict(),
sorted(self.table_model.backing_store.keys()),
partial(self.create_display, ty, None))
dlg.open()
def create_display(self, ty, prev_name, name, settings):
if prev_name is not None and prev_name in self.displays:
raise NotImplementedError
dsp_class = display_types[ty][1]
dsp = dsp_class(name, settings)
self.displays[name] = dsp
dsp.update_data(self.table_model.backing_store)
def on_close():
del self.displays[name]
dsp.sigClosed.connect(on_close)
self.dock_area.addDock(dsp)
self.dock_area.floatDock(dsp)
return dsp
def save_state(self):
r = dict()
for name, display in self.displays.items():
r[name] = {
"ty": _get_display_type_name(type(display)),
"settings": display.settings,
"state": display.save_state()
}
return r
def restore_state(self, state):
for name, desc in state.items():
try:
dsp = self.create_display(desc["ty"], None, name,
desc["settings"])
except:
logger.warning("Failed to create display '%s'", name,
exc_info=True)
try:
dsp.restore_state(desc["state"])
except:
logger.warning("Failed to restore display state of '%s'",
name, exc_info=True)