Bug hunting and polishing

Change-Id: I0f05730dd4e01e926ab0c4870c27ed5754f3ccfd
This commit is contained in:
Enrico Faulhaber
2017-01-20 18:21:27 +01:00
parent 8e3d0da5dd
commit d5e935788f
18 changed files with 552 additions and 202 deletions

View File

@ -27,6 +27,7 @@ from PyQt4.QtCore import pyqtSignature as qtsig, QObject, pyqtSignal
from secop.gui.util import loadUi
from secop.gui.nodectrl import NodeCtrl
from secop.gui.modulectrl import ModuleCtrl
from secop.gui.paramview import ParameterView
from secop.client.baseclient import Client as SECNode
ITEM_TYPE_NODE = QTreeWidgetItem.UserType + 1
@ -35,7 +36,7 @@ ITEM_TYPE_PARAMETER = QTreeWidgetItem.UserType + 3
class QSECNode(SECNode, QObject):
newData = pyqtSignal(str, str, object) # module, parameter, data
newData = pyqtSignal(str, str, object) # module, parameter, data
def __init__(self, opts, autoconnect=False, parent=None):
SECNode.__init__(self, opts, autoconnect)
@ -79,7 +80,7 @@ class MainWindow(QMainWindow):
@qtsig('')
def on_actionAdd_SEC_node_triggered(self):
host, ok = QInputDialog.getText(self, 'Add SEC node',
'Enter SEC node hostname:')
'Enter SEC node hostname:')
if not ok:
return
@ -91,6 +92,10 @@ class MainWindow(QMainWindow):
self._displayNode(current.text(0))
elif current.type() == ITEM_TYPE_MODULE:
self._displayModule(current.parent().text(0), current.text(0))
elif current.type() == ITEM_TYPE_PARAMETER:
self._displayParameter(current.parent().parent().text(0),
current.parent().text(0),
current.text(0))
def _addNode(self, host):
@ -99,9 +104,10 @@ class MainWindow(QMainWindow):
if ':' in host:
host, port = host.split(':', 1)
port = int(port)
node = QSECNode({'connectto':host, 'port':port}, parent=self)
node = QSECNode({'connectto': host, 'port': port}, parent=self)
host = '%s:%d' % (host, port)
host = '%s (%s)' % (node.equipment_id, host)
self._nodes[host] = node
# fill tree
@ -127,6 +133,13 @@ class MainWindow(QMainWindow):
def _displayModule(self, node, module):
self._replaceCtrlWidget(ModuleCtrl(self._nodes[node], module))
def _displayParameter(self, node, module, parameter):
self._replaceCtrlWidget(
ParameterView(
self._nodes[node],
module,
parameter))
def _replaceCtrlWidget(self, new):
old = self.splitter.widget(1).layout().takeAt(0)
if old:

View File

@ -26,10 +26,12 @@ from PyQt4.QtCore import pyqtSignature as qtsig, Qt, pyqtSignal
from secop.gui.util import loadUi
class ParameterButtons(QWidget):
setRequested = pyqtSignal(str, str, str) # module, parameter, setpoint
def __init__(self, module, parameter, initval='', parent=None):
class ParameterButtons(QWidget):
setRequested = pyqtSignal(str, str, str) # module, parameter, target
def __init__(self, module, parameter, initval='',
readonly=True, parent=None):
super(ParameterButtons, self).__init__(parent)
loadUi(self, 'parambuttons.ui')
@ -37,20 +39,24 @@ class ParameterButtons(QWidget):
self._parameter = parameter
self.currentLineEdit.setText(str(initval))
if readonly:
self.setPushButton.setEnabled(False)
self.setLineEdit.setEnabled(False)
def on_setPushButton_clicked(self):
self.setRequested.emit(self._module, self._parameter,
self.setLineEdit.text())
self.setLineEdit.text())
class ModuleCtrl(QWidget):
def __init__(self, node, module, parent=None):
super(ModuleCtrl, self).__init__(parent)
loadUi(self, 'modulectrl.ui')
self._node = node
self._module = module
self._paramWidgets = {} # widget cache do avoid garbage collection
self._paramWidgets = {} # widget cache do avoid garbage collection
self.moduleNameLabel.setText(module)
self._initModuleWidgets()
@ -68,8 +74,12 @@ class ModuleCtrl(QWidget):
label = QLabel(param + ':')
label.setFont(font)
props = self._node.getProperties(self._module, param)
buttons = ParameterButtons(self._module, param,
initValues[param].value)
initValues[param].value,
props['readonly'])
buttons.setRequested.connect(self._node.setParameter)
self.paramGroupBox.layout().addWidget(label, row, 0)

View File

@ -27,8 +27,11 @@ from PyQt4.QtGui import QWidget, QTextCursor, QFont, QFontMetrics
from PyQt4.QtCore import pyqtSignature as qtsig, Qt
from secop.gui.util import loadUi
from secop.protocol.errors import SECOPError
class NodeCtrl(QWidget):
def __init__(self, node, parent=None):
super(NodeCtrl, self).__init__(parent)
loadUi(self, 'nodectrl.ui')
@ -49,9 +52,12 @@ class NodeCtrl(QWidget):
self._addLogEntry('<span style="font-weight:bold">Request:</span> '
'%s:' % msg, raw=True)
msg = msg.split(' ', 2)
reply = self._node.syncCommunicate(*msg)
self._addLogEntry(reply, newline=True, pretty=True)
# msg = msg.split(' ', 2)
try:
reply = self._node.syncCommunicate(*self._node.decode_message(msg))
self._addLogEntry(reply, newline=True, pretty=True)
except SECOPError as e:
self._addLogEntry(e, newline=True, pretty=True, error=True)
@qtsig('')
def on_clearPushButton_clicked(self):
@ -64,13 +70,19 @@ class NodeCtrl(QWidget):
self._addLogEntry('=========================')
self._addLogEntry('', newline=True)
def _addLogEntry(self, msg, newline=False, pretty=False, raw=False):
def _addLogEntry(self, msg, newline=False,
pretty=False, raw=False, error=False):
if pretty:
msg = pprint.pformat(msg, width=self._getLogWidth())
if not raw:
msg = '<pre>%s</pre>' % Qt.escape(str(msg)).replace('\n', '<br />')
if error:
msg = '<div style="color:#FF0000"><b><pre>%s</pre></b></div>' % Qt.escape(
str(msg)).replace('\n', '<br />')
else:
msg = '<pre>%s</pre>' % Qt.escape(str(msg)
).replace('\n', '<br />')
content = ''
if self.logTextBrowser.toPlainText():
@ -89,4 +101,3 @@ class NodeCtrl(QWidget):
# due to monospace)
result = self.logTextBrowser.width() / fontMetrics.width('a')
return result

81
secop/gui/paramview.py Normal file
View File

@ -0,0 +1,81 @@
# -*- coding: utf-8 -*-
# *****************************************************************************
# Copyright (c) 2015-2017 by the authors, see LICENSE
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# Module authors:
# Enrico Faulhaber <enrico.faulhaber@frm2.tum.de>
#
# *****************************************************************************
from PyQt4.QtGui import QWidget, QLabel, QSizePolicy
from PyQt4.QtCore import pyqtSignature as qtsig, Qt, pyqtSignal
from secop.gui.util import loadUi
from secop.validators import validator_to_str
class ParameterView(QWidget):
def __init__(self, node, module, parameter, parent=None):
super(ParameterView, self).__init__(parent)
loadUi(self, 'paramview.ui')
self._node = node
self._module = module
self._parameter = parameter
self._propWidgets = {} # widget cache do avoid garbage collection
self.paramNameLabel.setText("%s:%s" % (module, parameter))
self._initParamWidgets()
# self._node.newData.connect(self._updateValue)
def _initParamWidgets(self):
# initValues = self._node.queryCache(self._module) #? mix live data?
row = 0
font = self.font()
font.setBold(True)
props = self._node._getDescribingParameterData(
self._module, self._parameter)
for prop in sorted(props):
label = QLabel(prop + ':')
label.setFont(font)
label.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred)
# make 'display' label
if prop == 'validator':
view = QLabel(validator_to_str(props[prop]))
else:
view = QLabel(str(props[prop]))
view.setFont(self.font())
view.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
view.setWordWrap(True)
self.propertyGroupBox.layout().addWidget(label, row, 0)
self.propertyGroupBox.layout().addWidget(view, row, 1)
self._propWidgets[prop] = (label, view)
row += 1
def _updateValue(self, module, parameter, value):
if module != self._module:
return
self._paramWidgets[parameter][1].currentLineEdit.setText(str(value[0]))

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>730</width>
<height>31</height>
<height>33</height>
</rect>
</property>
<property name="windowTitle">
@ -33,7 +33,7 @@
<item row="0" column="1">
<widget class="QLineEdit" name="currentLineEdit">
<property name="enabled">
<bool>false</bool>
<bool>true</bool>
</property>
<property name="minimumSize">
<size>
@ -41,6 +41,9 @@
<height>0</height>
</size>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="2">

99
secop/gui/ui/paramview.ui Normal file
View File

@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>230</width>
<height>121</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="3" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="font">
<font>
<weight>75</weight>
<italic>false</italic>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Parameter name:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="paramNameLabel">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QGroupBox" name="propertyGroupBox">
<property name="title">
<string>Parameters:</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<property name="spacing">
<number>6</number>
</property>
</layout>
</widget>
</item>
<item row="1" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>