dashboard/moninj: fancy level setting and layout improvements. Closes #163

This commit is contained in:
Sebastien Bourdeauducq 2016-04-05 18:38:05 +08:00
parent e7c58a7d62
commit fc524961b2
1 changed files with 81 additions and 67 deletions

View File

@ -8,6 +8,7 @@ from PyQt5 import QtCore, QtWidgets, QtGui
from artiq.tools import TaskObject from artiq.tools import TaskObject
from artiq.protocols.sync_struct import Subscriber from artiq.protocols.sync_struct import Subscriber
from artiq.gui.tools import LayoutWidget
from artiq.gui.flowlayout import FlowLayout from artiq.gui.flowlayout import FlowLayout
@ -27,8 +28,8 @@ class _MoninjWidget(QtWidgets.QFrame):
QtWidgets.QFrame.__init__(self) QtWidgets.QFrame.__init__(self)
qfm = QtGui.QFontMetrics(self.font()) qfm = QtGui.QFontMetrics(self.font())
self._size = QtCore.QSize( self._size = QtCore.QSize(
29*qfm.averageCharWidth(), 18*qfm.averageCharWidth(),
10*qfm.lineSpacing()) 6*qfm.lineSpacing())
self.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) self.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
self.setFrameShape(QtWidgets.QFrame.Box) self.setFrameShape(QtWidgets.QFrame.Box)
@ -53,52 +54,66 @@ class _TTLWidget(_MoninjWidget):
label.setWordWrap(True) label.setWordWrap(True)
grid.addWidget(label, 1, 1) grid.addWidget(label, 1, 1)
self._direction = QtWidgets.QLabel() self.stack = QtWidgets.QStackedWidget()
self._direction.setAlignment(QtCore.Qt.AlignCenter) grid.addWidget(self.stack, 2, 1)
grid.addWidget(self._direction, 2, 1)
self._override = QtWidgets.QLabel()
self._override.setAlignment(QtCore.Qt.AlignCenter)
grid.addWidget(self._override, 3, 1)
self._value = QtWidgets.QLabel()
self._value.setAlignment(QtCore.Qt.AlignCenter)
grid.addWidget(self._value, 4, 1, 6, 1)
self._value.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) self.direction = QtWidgets.QLabel()
menu = QtWidgets.QActionGroup(self._value) self.direction.setAlignment(QtCore.Qt.AlignCenter)
menu.setExclusive(True) self.stack.addWidget(self.direction)
self._expctl_action = QtWidgets.QAction("Experiment controlled", self._value)
self._expctl_action.setCheckable(True) grid_cb = LayoutWidget()
menu.addAction(self._expctl_action) self.override = QtWidgets.QCheckBox("Override")
self._value.addAction(self._expctl_action) grid_cb.addWidget(self.override, 3, 1)
self._expctl_action.triggered.connect(lambda: self.set_mode("exp")) self.level = QtWidgets.QCheckBox("Level")
separator = QtWidgets.QAction(self._value) grid_cb.addWidget(self.level, 3, 2)
separator.setSeparator(True) self.stack.addWidget(grid_cb)
self._value.addAction(separator)
self._force1_action = QtWidgets.QAction("Force 1", self._value) self.value = QtWidgets.QLabel()
self._force1_action.setCheckable(True) self.value.setAlignment(QtCore.Qt.AlignCenter)
menu.addAction(self._force1_action) grid.addWidget(self.value, 3, 1)
self._value.addAction(self._force1_action)
self._force1_action.triggered.connect(lambda: self.set_mode("1"))
self._force0_action = QtWidgets.QAction("Force 0", self._value)
self._force0_action.setCheckable(True)
menu.addAction(self._force0_action)
self._value.addAction(self._force0_action)
self._force0_action.triggered.connect(lambda: self.set_mode("0"))
self._forcein_action = QtWidgets.QAction("Force input", self._value)
self._forcein_action.setCheckable(True)
self._forcein_action.setEnabled(not force_out)
menu.addAction(self._forcein_action)
self._value.addAction(self._forcein_action)
self._forcein_action.triggered.connect(lambda: self.set_mode("in"))
grid.setRowStretch(1, 1) grid.setRowStretch(1, 1)
grid.setRowStretch(2, 0) grid.setRowStretch(2, 0)
grid.setRowStretch(3, 0) grid.setRowStretch(3, 0)
grid.setRowStretch(4, 0) grid.setRowStretch(4, 1)
grid.setRowStretch(5, 1)
self.programmatic_change = False
self.override.stateChanged.connect(self.override_toggled)
self.level.stateChanged.connect(self.level_toggled)
self.set_value(0, False, False) self.set_value(0, False, False)
def enterEvent(self, event):
self.stack.setCurrentIndex(1)
_MoninjWidget.enterEvent(self, event)
def leaveEvent(self, event):
if not self.override.isChecked():
self.stack.setCurrentIndex(0)
_MoninjWidget.leaveEvent(self, event)
def override_toggled(self, override):
print("override", override, self.programmatic_change)
if self.programmatic_change:
return
if override:
if self.level.isChecked():
self.set_mode("1")
else:
self.set_mode("0")
else:
self.set_mode("exp")
def level_toggled(self, level):
print("level", level, self.programmatic_change)
if self.programmatic_change:
return
if self.override.isChecked():
if level:
self.set_mode("1")
else:
self.set_mode("0")
def set_mode(self, mode): def set_mode(self, mode):
data = struct.pack("bbb", data = struct.pack("bbb",
2, # MONINJ_REQ_TTLSET 2, # MONINJ_REQ_TTLSET
@ -110,25 +125,22 @@ class _TTLWidget(_MoninjWidget):
if override: if override:
value_s = "<b>" + value_s + "</b>" value_s = "<b>" + value_s + "</b>"
color = " color=\"red\"" color = " color=\"red\""
self._override.setText("<font size=\"1\" color=\"red\">OVERRIDE</font>")
else: else:
color = "" color = ""
self._override.setText("") self.value.setText("<font size=\"9\"{}>{}</font>".format(
self._value.setText("<font size=\"9\"{}>{}</font>".format(
color, value_s)) color, value_s))
oe = oe or self.force_out oe = oe or self.force_out
direction = "OUT" if oe else "IN" direction = "OUT" if oe else "IN"
self._direction.setText("<font size=\"1\">" + direction + "</font>") self.direction.setText("<font size=\"1\">" + direction + "</font>")
if override:
if oe: self.programmatic_change = True
if value: try:
self._force1_action.setChecked(True) self.override.setChecked(bool(override))
else: if override:
self._force0_action.setChecked(True) self.stack.setCurrentIndex(1)
else: self.level.setChecked(bool(value))
self._forcein_action.setChecked(True) finally:
else: self.programmatic_change = False
self._expctl_action.setChecked(True)
class _DDSWidget(_MoninjWidget): class _DDSWidget(_MoninjWidget):
@ -146,10 +158,10 @@ class _DDSWidget(_MoninjWidget):
label.setWordWrap(True) label.setWordWrap(True)
grid.addWidget(label, 1, 1) grid.addWidget(label, 1, 1)
self._value = QtWidgets.QLabel() self.value = QtWidgets.QLabel()
self._value.setAlignment(QtCore.Qt.AlignCenter) self.value.setAlignment(QtCore.Qt.AlignCenter)
self._value.setWordWrap(True) self.value.setWordWrap(True)
grid.addWidget(self._value, 2, 1, 6, 1) grid.addWidget(self.value, 2, 1, 6, 1)
grid.setRowStretch(1, 1) grid.setRowStretch(1, 1)
grid.setRowStretch(2, 0) grid.setRowStretch(2, 0)
@ -159,8 +171,8 @@ class _DDSWidget(_MoninjWidget):
def set_value(self, ftw): def set_value(self, ftw):
frequency = ftw*self.sysclk()/2**32 frequency = ftw*self.sysclk()/2**32
self._value.setText("<font size=\"6\">{:.7f} MHz</font>" self.value.setText("<font size=\"5\">{:.7f} MHz</font>"
.format(float(frequency)/1e6)) .format(frequency/1e6))
class _DeviceManager: class _DeviceManager:
@ -188,14 +200,13 @@ class _DeviceManager:
return return
try: try:
if v["type"] == "local": if v["type"] == "local":
title = k widget = None
if "comment" in v:
title += ": " + v["comment"]
if v["module"] == "artiq.coredevice.ttl": if v["module"] == "artiq.coredevice.ttl":
channel = v["arguments"]["channel"] channel = v["arguments"]["channel"]
force_out = v["class"] == "TTLOut" force_out = v["class"] == "TTLOut"
self.ttl_widgets[k] = _TTLWidget( widget = _TTLWidget(
channel, self.send_to_device, force_out, title) channel, self.send_to_device, force_out, k)
self.ttl_widgets[k] = widget
self.ttl_cb() self.ttl_cb()
if (v["module"] == "artiq.coredevice.dds" if (v["module"] == "artiq.coredevice.dds"
and v["class"] == "CoreDDS"): and v["class"] == "CoreDDS"):
@ -204,9 +215,12 @@ class _DeviceManager:
and v["class"] in {"AD9858", "AD9914"}): and v["class"] in {"AD9858", "AD9914"}):
bus_channel = v["arguments"]["bus_channel"] bus_channel = v["arguments"]["bus_channel"]
channel = v["arguments"]["channel"] channel = v["arguments"]["channel"]
self.dds_widgets[channel] = _DDSWidget( widget = _DDSWidget(
bus_channel, channel, self.get_dds_sysclk, title) bus_channel, channel, self.get_dds_sysclk, k)
self.dds_widgets[channel] = widget
self.dds_cb() self.dds_cb()
if widget is not None and "comment" in v:
widget.setToolTip(v["comment"])
except KeyError: except KeyError:
pass pass