
* different color for value fields * placeholder text in input fields Change-Id: Ibb94eb09ab7bfd7c2807f27226b7e2825ac3ea5d Reviewed-on: https://forge.frm2.tum.de/review/c/secop/frappy/+/30579 Tested-by: Jenkins Automated Tests <pedersen+jenkins@frm2.tum.de> Reviewed-by: Georg Brandl <g.brandl@fz-juelich.de> Reviewed-by: Alexander Zaft <a.zaft@fz-juelich.de>
271 lines
9.0 KiB
Python
271 lines
9.0 KiB
Python
from frappy.gui.qt import QDialog, QIcon, QLabel, QLineEdit, QMessageBox, \
|
|
QPushButton, QToolButton, QWidget, pyqtSignal
|
|
|
|
import frappy.gui.resources # pylint: disable=unused-import
|
|
from frappy.gui.util import Colors, loadUi
|
|
from frappy.gui.valuewidgets import get_widget
|
|
|
|
|
|
class CommandDialog(QDialog):
|
|
def __init__(self, cmdname, argument, parent=None):
|
|
super().__init__(parent)
|
|
loadUi(self, 'cmddialog.ui')
|
|
|
|
self.setWindowTitle('Arguments for %s' % cmdname)
|
|
# row = 0
|
|
|
|
self._labels = []
|
|
self.widgets = []
|
|
# improve! recursive?
|
|
dtype = argument
|
|
label = QLabel(repr(dtype))
|
|
label.setWordWrap(True)
|
|
widget = get_widget(dtype, readonly=False)
|
|
self.gridLayout.addWidget(label, 0, 0)
|
|
self.gridLayout.addWidget(widget, 0, 1)
|
|
self._labels.append(label)
|
|
self.widgets.append(widget)
|
|
|
|
self.gridLayout.setRowStretch(1, 1)
|
|
self.setModal(True)
|
|
self.resize(self.sizeHint())
|
|
|
|
def get_value(self):
|
|
return True, self.widgets[0].get_value()
|
|
|
|
def exec_(self):
|
|
if super().exec_():
|
|
return self.get_value()
|
|
return None
|
|
|
|
|
|
def showCommandResultDialog(command, args, result, extras=''):
|
|
m = QMessageBox()
|
|
args = '' if args is None else repr(args)
|
|
m.setText('calling: %s(%s)\nyielded: %r\nqualifiers: %s' %
|
|
(command, args, result, extras))
|
|
m.exec_()
|
|
|
|
|
|
def showErrorDialog(command, args, error):
|
|
m = QMessageBox()
|
|
args = '' if args is None else repr(args)
|
|
m.setText('calling: %s(%s)\nraised %r' % (command, args, error))
|
|
m.exec_()
|
|
|
|
|
|
class CommandButton(QPushButton):
|
|
def __init__(self, cmdname, cmdinfo, cb, parent=None):
|
|
super().__init__(parent)
|
|
|
|
self._cmdname = cmdname
|
|
self._argintype = cmdinfo['datatype'].argument # single datatype
|
|
self.result = cmdinfo['datatype'].result
|
|
self._cb = cb # callback function for exection
|
|
|
|
self.setText(cmdname)
|
|
if cmdinfo['description']:
|
|
self.setToolTip(cmdinfo['description'])
|
|
self.pressed.connect(self.on_pushButton_pressed)
|
|
|
|
def on_pushButton_pressed(self):
|
|
#self.setEnabled(False)
|
|
if self._argintype:
|
|
dlg = CommandDialog(self._cmdname, self._argintype)
|
|
args = dlg.exec_()
|
|
if args: # not 'Cancel' clicked
|
|
self._cb(self._cmdname, args[1])
|
|
else:
|
|
# no need for arguments
|
|
self._cb(self._cmdname, None)
|
|
#self.setEnabled(True)
|
|
|
|
|
|
class ModuleWidget(QWidget):
|
|
plot = pyqtSignal(str)
|
|
plotAdd = pyqtSignal(str)
|
|
def __init__(self, node, name, parent=None):
|
|
super().__init__()
|
|
loadUi(self, 'modulewidget.ui')
|
|
self._node = node
|
|
self._name = name
|
|
self._paramDisplays = {}
|
|
self._paramInputs = {}
|
|
self._addbtns = []
|
|
self._paramWidgets = {}
|
|
|
|
self.moduleName.setText(name)
|
|
props = self._node.getModuleProperties(self._name)
|
|
description = props.get('description', '')
|
|
self.moduleDescription.setText(description)
|
|
|
|
row = 0
|
|
params = dict(self._node.getParameters(self._name))
|
|
if 'status' in params:
|
|
params.pop('status')
|
|
self._addRParam('status', row)
|
|
row += 1
|
|
if 'value' in params:
|
|
params.pop('value')
|
|
self._addRParam('value', row)
|
|
row += 1
|
|
if 'target' in params:
|
|
params.pop('target')
|
|
self._addRWParam('target', row)
|
|
row += 1
|
|
for param in params:
|
|
paramProps = self._node.getProperties(self._name, param)
|
|
if paramProps['readonly']:
|
|
self._addRParam(param, row)
|
|
else:
|
|
self._addRWParam(param, row)
|
|
row += 1
|
|
self._setParamHidden(param, True)
|
|
|
|
self._addCommands(row)
|
|
|
|
cache = self._node.queryCache(self._name)
|
|
for param, val in cache.items():
|
|
self._updateValue(self._name, param, val)
|
|
|
|
node.newData.connect(self._updateValue)
|
|
|
|
def _updateValue(self, mod, param, val):
|
|
if mod != self._name:
|
|
return
|
|
if param in self._paramDisplays:
|
|
# TODO: stopgap
|
|
if val.readerror:
|
|
strvalue = str(val)
|
|
else:
|
|
strvalue = ('%g' if isinstance(val.value, float)
|
|
else '%s') % (val.value,)
|
|
self._paramDisplays[param].setText(strvalue)
|
|
|
|
def _addRParam(self, param, row):
|
|
props = self._node.getProperties(self._name, param)
|
|
|
|
nameLabel = QLabel(param)
|
|
unitLabel = QLabel(props.get('unit', ''))
|
|
display = QLineEdit()
|
|
|
|
p = display.palette()
|
|
p.setColor(display.backgroundRole(), Colors.palette.window().color())
|
|
display.setPalette(p)
|
|
self._paramDisplays[param] = display
|
|
self._paramWidgets[param] = [nameLabel, unitLabel, display]
|
|
|
|
l = self.moduleDisplay.layout()
|
|
l.addWidget(nameLabel, row,0,1,1)
|
|
l.addWidget(display, row,1,1,5)
|
|
l.addWidget(unitLabel, row,6)
|
|
self._addPlotButtons(param, row)
|
|
|
|
def _addRWParam(self, param, row):
|
|
props = self._node.getProperties(self._name, param)
|
|
|
|
nameLabel = QLabel(param)
|
|
unitLabel = QLabel(props.get('unit', ''))
|
|
unitLabel2 = QLabel(props.get('unit', ''))
|
|
display = QLineEdit()
|
|
inputEdit = QLineEdit()
|
|
submitButton = QPushButton('Go')
|
|
submitButton.setIcon(QIcon(':/icons/submit'))
|
|
|
|
inputEdit.setPlaceholderText('new value')
|
|
p = display.palette()
|
|
p.setColor(display.backgroundRole(), Colors.palette.window().color())
|
|
display.setPalette(p)
|
|
submitButton.pressed.connect(lambda: self._button_pressed(param))
|
|
inputEdit.returnPressed.connect(lambda: self._button_pressed(param))
|
|
self._paramDisplays[param] = display
|
|
self._paramInputs[param] = inputEdit
|
|
self._paramWidgets[param] = [nameLabel, unitLabel, unitLabel2,
|
|
display, inputEdit, submitButton]
|
|
|
|
l = self.moduleDisplay.layout()
|
|
l.addWidget(nameLabel, row,0,1,1)
|
|
l.addWidget(display, row,1,1,2)
|
|
l.addWidget(unitLabel, row,3,1,1)
|
|
l.addWidget(inputEdit, row,4,1,2)
|
|
l.addWidget(unitLabel2, row,6,1,1)
|
|
l.addWidget(submitButton, row, 7)
|
|
self._addPlotButtons(param, row)
|
|
|
|
def _addPlotButtons(self, param, row):
|
|
if param == 'status':
|
|
return
|
|
plotButton = QToolButton()
|
|
plotButton.setIcon(QIcon(':/icons/plot'))
|
|
plotButton.setToolTip('Plot %s' % param)
|
|
plotAddButton = QToolButton()
|
|
plotAddButton.setIcon(QIcon(':/icons/plot-add'))
|
|
plotAddButton.setToolTip('Plot With...')
|
|
|
|
plotButton.clicked.connect(lambda: self.plot.emit(param))
|
|
plotAddButton.clicked.connect(lambda: self.plotAdd.emit(param))
|
|
|
|
self._addbtns.append(plotAddButton)
|
|
plotAddButton.setDisabled(True)
|
|
self._paramWidgets[param].append(plotButton)
|
|
self._paramWidgets[param].append(plotAddButton)
|
|
|
|
l = self.moduleDisplay.layout()
|
|
l.addWidget(plotButton, row, 8)
|
|
l.addWidget(plotAddButton, row, 9)
|
|
|
|
def _addCommands(self, startrow):
|
|
cmdicons = {
|
|
'stop': QIcon(':/icons/stop'),
|
|
}
|
|
cmds = self._node.getCommands(self._name)
|
|
if not cmds:
|
|
return
|
|
|
|
l = self.moduleDisplay.layout()
|
|
# max cols in GridLayout, find out programmatically?
|
|
maxcols = 7
|
|
l.addWidget(QLabel('Commands:'))
|
|
for (i, cmd) in enumerate(cmds):
|
|
cmdb = CommandButton(cmd, cmds[cmd], self._execCommand)
|
|
if cmd in cmdicons:
|
|
cmdb.setIcon(cmdicons[cmd])
|
|
row = startrow + i // maxcols
|
|
col = (i % maxcols) + 1
|
|
l.addWidget(cmdb, row, col)
|
|
|
|
|
|
def _execCommand(self, command, args=None):
|
|
try:
|
|
result, qualifiers = self._node.execCommand(
|
|
self._name, command, args)
|
|
except Exception as e:
|
|
showErrorDialog(command, args, e)
|
|
return
|
|
if result is not None:
|
|
showCommandResultDialog(command, args, result, qualifiers)
|
|
|
|
def _setParamHidden(self, param, hidden):
|
|
for w in self._paramWidgets[param]:
|
|
w.setHidden(hidden)
|
|
|
|
def _setGroupHidden(self, group):
|
|
pass
|
|
|
|
def rebuildAdvanced(self, advanced):
|
|
for param in self._paramWidgets:
|
|
if param in ['value', 'status', 'target']:
|
|
continue
|
|
self._setParamHidden(param, not advanced)
|
|
|
|
def _button_pressed(self, param):
|
|
target = self._paramInputs[param].text()
|
|
try:
|
|
self._node.setParameter(self._name, param, target)
|
|
except Exception as e:
|
|
QMessageBox.warning(self.parent(), 'Operation failed', str(e))
|
|
|
|
def plotsPresent(self, present):
|
|
for btn in self._addbtns:
|
|
btn.setDisabled(present)
|