Beispiel #1
0
    def __init__(self, parent, client, instrument, configs, config=None):
        QDialog.__init__(self, parent)
        self.instrument = instrument
        self.configs = configs
        self.client = client
        self.setWindowTitle('Sample configuration')
        layout = QVBoxLayout()
        self.frm = QFrame(self)
        loadUi(self.frm,
               findResource('nicos_ess/loki/gui/ui_files/sampleconf_one.ui'))
        self.frm.addDevBtn.clicked.connect(self.on_addDevBtn_clicked)
        self.frm.delDevBtn.clicked.connect(self.on_delDevBtn_clicked)
        self.frm.readDevsBtn.clicked.connect(self.on_readDevsBtn_clicked)
        box = QDialogButtonBox(self)
        box.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        box.accepted.connect(self.maybeAccept)
        box.rejected.connect(self.reject)
        layout.addWidget(self.frm)
        layout.addWidget(box)
        self.setLayout(layout)
        self.frm.thickBox.setValidator(DoubleValidator(self))
        if config is not None:
            configToFrame(self.frm, config)

        # Apply local customisations to the stylesheet
        self.setStyleSheet(ConfigEditDialog_QSS)

        if not config:
            self.frm.whatLbl.setText('New sample configuration')
Beispiel #2
0
 def __init__(self, parent, client, instrument, configs, config=None):
     QDialog.__init__(self, parent)
     self.instrument = instrument
     self.configs = configs
     self.client = client
     self.setWindowTitle('Sample configuration')
     layout = QVBoxLayout()
     self.frm = QFrame(self)
     loadUi(self.frm, findResource('nicos_mlz/kws1/gui/sampleconf_one.ui'))
     self.frm.addDevBtn.clicked.connect(self.on_addDevBtn_clicked)
     self.frm.delDevBtn.clicked.connect(self.on_delDevBtn_clicked)
     self.frm.readDevsBtn.clicked.connect(self.on_readDevsBtn_clicked)
     self.frm.readApBtn.clicked.connect(self.on_readApBtn_clicked)
     box = QDialogButtonBox(self)
     box.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
     box.accepted.connect(self.maybeAccept)
     box.rejected.connect(self.reject)
     layout.addWidget(self.frm)
     layout.addWidget(box)
     self.setLayout(layout)
     for box in [self.frm.offsetBox, self.frm.thickBox, self.frm.factorBox,
                 self.frm.apXBox, self.frm.apYBox, self.frm.apWBox,
                 self.frm.apHBox]:
         box.setValidator(DoubleValidator(self))
     if config is not None:
         configToFrame(self.frm, config)
Beispiel #3
0
    def __init__(self, item, window, menuwindow, parent):
        from nicos.clients.gui.panels.utils import createWindowItem
        QMainWindow.__init__(self, parent)
        self.user_color = window.user_color
        self.mainwindow = window.mainwindow
        self.log = NicosLogger('AuxiliarySubWindow')
        self.log.parent = self.mainwindow.log

        self.panels = []

        # we have to nest one step to get consistent layout spacing
        # around the central widget
        central = QWidget(self)
        layout = QVBoxLayout()
        # only keep margin at the top (below the tabs)
        layout.setContentsMargins(0, 6, 0, 0)
        if len(item) == 1:
            (subitem, setupSpec) = item + (None, )
        else:
            (subitem, setupSpec) = item
        it = createWindowItem(subitem, window, menuwindow, self, self.log)
        if it:
            if isinstance(it, (
                    Panel,
                    QSplitter,
            )):
                if isinstance(it, Panel):
                    it.hideTitle()
                # if tab has its own setups overwrite panels setups
                if setupSpec:
                    it.setSetups(setupSpec)
                it.setWidgetVisible.connect(parent.setWidgetVisibleSlot)
            layout.addWidget(it)
            central.setLayout(layout)
            self.setCentralWidget(central)
Beispiel #4
0
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)

        self.canvas = FigureCanvas(Figure(figsize=(20, 16)))
        self._static_ax = self.canvas.figure.subplots()

        layout = QVBoxLayout()
        layout.addWidget(self.canvas)
        self.setLayout(layout)
Beispiel #5
0
class CustomButtonPanel(Panel):
    """Base class for custom instrument specific panels

    with a QDialogButtonBox at the lower right and some glue magic for
    fancy stuff...
    """
    buttons = QDialogButtonBox.Close | QDialogButtonBox.Apply

    def __init__(self, parent, client, options):
        Panel.__init__(self, parent, client, options)

        # make a vertical layout for 'ourself'
        self.vBoxLayout = QVBoxLayout(self)

        # make a buttonBox
        self.buttonBox = QDialogButtonBox(self.buttons, parent=self)
        self.buttonBox.setObjectName('buttonBox')

        # put buttonBox below main content
        self.vBoxLayout.addWidget(self.buttonBox)

        allButtons = 'Ok Open Save Cancel Close Discard Apply Reset '\
                     'RestoreDefaults Help SaveAll Yes YesToAll No NoToAll '\
                     'Abort Retry Ignore'.split()
        for btn_name in allButtons:
            btn = self.buttonBox.button(getattr(QDialogButtonBox, btn_name))
            if btn:
                handler = getattr(self, 'on_buttonBox_%s_clicked' % btn_name,
                                  None)
                if not handler:
                    # pylint: disable=function-redefined
                    def handler(self=self, n=btn_name):
                        self.showError('on_buttonBox_%s_clicked not '
                                       'implemented!' % n)

                btn.clicked.connect(handler)

    def panelState(self):
        """returns current window state as obtained from the stack of parents"""
        obj = self
        while hasattr(obj, 'parent'):
            if isinstance(obj, AuxiliaryWindow):
                return "tab"
            elif isinstance(obj, DetachedWindow):
                return "detached"
            obj = obj.parent()
        return "main"

    def on_buttonBox_Close_clicked(self):
        self.closeWindow()

    def on_buttonBox_Ok_clicked(self):
        """OK = Apply + Close"""
        if hasattr(self, 'on_buttonBox_Apply_clicked'):
            self.on_buttonBox_Apply_clicked()
        self.on_buttonBox_Close_clicked()
Beispiel #6
0
 def __init__(self, parent=None, designMode=False, **kwds):
     QWidget.__init__(self, parent, **kwds)
     NicosWidget.__init__(self)
     self._last_mtime = None
     self.namelabel = QLabel(self)
     self.namelabel.setAlignment(Qt.AlignHCenter)
     self.piclabel = QLabel(self)
     self.piclabel.setScaledContents(True)
     layout = QVBoxLayout()
     layout.setContentsMargins(0, 0, 0, 0)
     layout.addWidget(self.piclabel, 1)
     self.setLayout(layout)
Beispiel #7
0
    def __init__(self, parent):
        QMainWindow.__init__(self, parent)
        DlgUtils.__init__(self, 'Live data')
        self.panel = parent
        layout1 = QVBoxLayout()
        self.plot = QwtPlot(self)
        layout1.addWidget(self.plot)
        self.curve = QwtPlotCurve()
        self.curve.setRenderHint(QwtPlotCurve.RenderAntialiased)
        self.curve.attach(self.plot)
        self.marker = QwtPlotMarker()
        self.marker.attach(self.plot)
        self.markerpen = QPen(Qt.red)
        self.marker.setSymbol(
            QwtSymbol(QwtSymbol.Ellipse, QBrush(), self.markerpen, QSize(7,
                                                                         7)))
        self.zoomer = QwtPlotZoomer(self.plot.canvas())
        self.zoomer.setMousePattern(QwtPlotZoomer.MouseSelect3, Qt.NoButton)
        self.picker = QwtPlotPicker(self.plot.canvas())
        self.picker.setSelectionFlags(QwtPlotPicker.PointSelection
                                      | QwtPlotPicker.ClickSelection)
        self.picker.setMousePattern(QwtPlotPicker.MouseSelect1, Qt.MidButton)
        self.picker.selected.connect(self.pickerSelected)
        layout2 = QHBoxLayout()
        layout2.addWidget(QLabel('Scale:', self))
        self.scale = QComboBox(self)
        self.scale.addItems([
            'Single detectors, sorted by angle',
            'Scattering angle 2theta (deg)', 'Q value (A-1)'
        ])
        self.scale.currentIndexChanged[int].connect(self.scaleChanged)
        layout2.addWidget(self.scale)
        layout2.addStretch()
        self.scaleframe = QFrame(self)
        self.scaleframe.setLayout(layout2)
        self.scaleframe.setVisible(False)
        layout1.addWidget(self.scaleframe)
        mainframe = QFrame(self)
        mainframe.setLayout(layout1)
        self.setCentralWidget(mainframe)
        self.setContentsMargins(6, 6, 6, 6)
        plotfont = scaledFont(self.font(), 0.7)
        self.plot.setAxisFont(QwtPlot.xBottom, plotfont)
        self.plot.setAxisFont(QwtPlot.yLeft, plotfont)
        self.plot.setCanvasBackground(Qt.white)
        self.resize(800, 200)

        self._detinfo = None
        self._anglemap = None
        self._infowindow = None
        self._infolabel = None
        self._xs = self._ys = None
        self._type = None
Beispiel #8
0
    def __init__(self, parent, measdef, client):
        self._edit = None
        self.measdef = measdef
        self.client = client
        QDialog.__init__(self, parent)
        loadUi(self, findResource('nicos_ess/loki/gui/ui_files/detsets.ui'))
        self.table.setColumnCount(len(measdef.getElements()))

        # apply current settings
        self._rows = []
        if measdef.detsets:
            for row in measdef.detsets[0]:
                self.addRow(row)

        # create widgets for new setting
        self._new_elements = {}
        headers = []
        for i, (eltype, cls) in enumerate(measdef.getElements()):
            element = self._new_elements[eltype] = cls(eltype, self.client)
            w = element.createWidget(self, self.client)
            for other in self._new_elements.values():
                if other is not element:
                    element.otherChanged(other.eltype, other.getValue())

            def handler(new_value, eltype=eltype):
                for other in self._new_elements.values():
                    other.otherChanged(eltype, new_value)

            element.changed.connect(handler)
            headers.append(element.getLabel())
            layout = QVBoxLayout()
            layout.addWidget(QLabel(headers[-1], self))
            layout.addWidget(w)
            self.widgetFrame.layout().insertLayout(i, layout)

        # update table widget
        self.table.setHorizontalHeaderLabels(headers)
        self.table.resizeColumnsToContents()
        for i in range(len(measdef.getElements())):
            self.table.setColumnWidth(i,
                                      max(50, 1.5 * self.table.columnWidth(i)))
        self.table.resizeRowsToContents()
Beispiel #9
0
 def propertyUpdated(self, pname, value):
     NicosWidget.propertyUpdated(self, pname, value)
     if pname == 'filepath':
         self._filePath = findResource(value)
         self.setPicture()
     elif pname == 'name':
         layout = QVBoxLayout()
         if value:
             layout.addWidget(self.namelabel)
             layout.addSpacing(5)
         layout.addWidget(self.piclabel, 1)
         sip.delete(self.layout())
         self.setLayout(layout)
         self.namelabel.setText(value)
     elif pname in ('width', 'height'):
         self.setPicture()
     elif pname == 'refresh':
         if value:
             self._refreshTimer = QTimer()
             self._refreshTimer.setInterval(value * 1000)
             self._refreshTimer.timeout.connect(self.updatePicture)
             self._refreshTimer.start()
Beispiel #10
0
 def viewTextFile(self, fname):
     with open(fname) as f:
         contents = f.read()
     qd = QDialog(self, 'PreviewDlg', True)
     qd.setCaption('File preview')
     qd.resize(QSize(500, 500))
     lay = QVBoxLayout(qd, 11, 6, 'playout')
     lb = QLabel(qd, 'label')
     lb.setText('Viewing %s:' % fname)
     lay.addWidget(lb)
     tx = QTextEdit(qd, 'preview')
     tx.setReadOnly(1)
     tx.setText(contents)
     font = QFont(tx.font())
     font.setFamily('monospace')
     tx.setFont(font)
     lay.addWidget(tx)
     btn = QPushButton(qd, 'ok')
     btn.setAutoDefault(1)
     btn.setDefault(1)
     btn.setText('Close')
     btn.clicked.connect(qd.accept)
     lay.addWidget(btn, 0, QWidget.AlignRight)
     qd.show()
Beispiel #11
0
class MultiList(NicosWidget, QWidget):
    """A list of entries, where each entry is a frame loaded from a UI file."""

    designer_description = 'A list (with add/remove controls) of .ui entries'

    uifile = PropDef('uifile', str, '', 'UI file to use for the entries')

    entryAdded = pyqtSignal(object)
    entryRemoved = pyqtSignal(object)

    def __init__(self, parent, designMode=False, **kwds):
        QWidget.__init__(self, parent, **kwds)
        NicosWidget.__init__(self)
        self._entries = []
        self._vlayout = QVBoxLayout()
        self._vlayout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(self._vlayout)
        self._add()
        self._designer = designMode

    def registerKeys(self):
        pass

    def propertyUpdated(self, pname, value):
        if pname == 'uifile':
            self.clear()
        NicosWidget.propertyUpdated(self, pname, value)

    def entry(self, i):
        return self._entries[i].subwidget

    def entries(self):
        return [e.subwidget for e in self._entries]

    def count(self):
        return len(self._entries)

    def clear(self):
        for entry in self._entries[::-1]:
            self._remove(entry)
        self._add()

    def _remove(self, entry):
        self._entries.remove(entry)
        self._vlayout.removeWidget(entry)
        self.entryRemoved.emit(entry.subwidget)
        entry.deleteLater()
        if self._entries:
            self._entries[-1].setButton('+')

    def _add(self):
        new_frame = MultiEntry(self, self._client, self.props['uifile'])
        new_frame.addOrRemove.connect(self._addRemove)
        if self._entries:
            self._entries[-1].setButton('-')
        self._entries.append(new_frame)
        self._vlayout.addWidget(new_frame)
        self.entryAdded.emit(self._entries[-1].subwidget)

    def _addRemove(self):
        if not self._entries or self.sender() is self._entries[-1]:
            self._add()
        else:
            self._remove(self.sender())
Beispiel #12
0
class ItemsWidget(QScrollArea):

    valueModified = pyqtSignal()
    valueChosen = pyqtSignal(object)

    allow_reorder = True

    def __init__(self, parent, nmin, allow_enter=False):
        QScrollArea.__init__(self, parent)
        self.setWidgetResizable(True)
        self.frame = QFrame(self)
        self.layout = QVBoxLayout()
        self.layout.setContentsMargins(2, 2, 2, 2)
        self.addBtn = QPushButton(QIcon(':/add'), '', self.frame)
        self.addBtn.clicked.connect(self.on_addBtn_clicked)
        self.addBtn.setSizePolicy(
            QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred))
        self.layout.addWidget(self.addBtn)
        self.layout.addStretch()
        self.frame.setLayout(self.layout)
        self.setWidget(self.frame)
        self.items = []
        self.nmin = nmin
        self.allow_enter = allow_enter

    def insertItem(self, *widgets):
        item = QWidget(self.frame)
        item._widgets = widgets
        layout = QHBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        for widget in widgets:
            layout.addWidget(widget)
        if self.allow_reorder:
            btn = QPushButton(QIcon(':/up'), '', item)
            btn._item = item
            btn.clicked.connect(self.on_upBtn_clicked)
            layout.addWidget(btn)
            btn = QPushButton(QIcon(':/down'), '', item)
            btn._item = item
            btn.clicked.connect(self.on_downBtn_clicked)
            layout.addWidget(btn)
        btn = QPushButton(QIcon(':/remove'), '', item)
        btn._item = item
        btn.clicked.connect(self.on_removeBtn_clicked)
        layout.addWidget(btn)
        item.setLayout(layout)
        self.layout.insertWidget(self.layout.count() - 2, item)
        self.items.append(item)

    def on_addBtn_clicked(self):
        self.insertItem(*self.createItem())
        self.valueModified.emit()

    def on_removeBtn_clicked(self):
        if len(self.items) <= self.nmin:
            return
        item = self.sender()._item
        index = self.items.index(item)
        del self.items[index]
        self.layout.takeAt(index).widget().deleteLater()
        self.valueModified.emit()

    def on_upBtn_clicked(self):
        item = self.sender()._item
        index = self.items.index(item)
        if index <= 0:
            return
        self._swapItems(index - 1)

    def on_downBtn_clicked(self):
        item = self.sender()._item
        index = self.items.index(item)
        if index >= len(self.items) - 1:
            return
        self._swapItems(index)

    def _swapItems(self, firstindex):
        item1 = self.items[firstindex]
        item2 = self.items[firstindex + 1]
        self.layout.takeAt(firstindex)
        self.layout.takeAt(firstindex)  # moved up one
        self.items[firstindex:firstindex + 2] = [item2, item1]
        self.layout.insertWidget(firstindex, item2)
        self.layout.insertWidget(firstindex + 1, item1)
        self.valueModified.emit()
Beispiel #13
0
class MainWindow(QMainWindow):
    i = 0

    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)

        # scroll area Widget contents - layout
        self.scrollLayout = QFormLayout()
        self.scrollLayout.setContentsMargins(0, 0, 0, 0)

        # scroll area Widget contents
        self.scrollWidget = QWidget()
        self.scrollWidget.setLayout(self.scrollLayout)

        # scroll area
        self.scrollArea = QScrollArea()
        self.scrollArea.setWidgetResizable(True)
        self.scrollArea.setWidget(self.scrollWidget)

        # main layout
        self.mainLayout = QVBoxLayout()
        self.mainLayout.setSpacing(0)

        # add all main to the main vLayout
        self.mainLayout.addWidget(self.scrollArea)

        # central Widget
        self.centralWidget = QWidget()
        self.centralWidget.setLayout(self.mainLayout)

        # set central Widget
        self.setCentralWidget(self.centralWidget)

        try:
            self._bus = ModbusTcpClient('drum.panda.frm2')
            self._bus.connect()
            self._sync()
            print("Modbus synced!")
            print(self.ReadWord(0x20), self.ReadWord(0x21))
        except Exception as err:
            print("Modbus failed: %r, using demo mode!" % err)
            self._bus = None

        self._sync()

        widgets = []

        widgets.append(
            BaseDev(self, 'mtt motor inputs', 0, has_status=True, addr=34))

        widgets.append(
            BaseDev(self, 'spare inputs', 1, has_status=True, addr=44))
        widgets.append(
            BaseDev(self,
                    'spare outputs',
                    2,
                    has_status=True,
                    target='0x%04x' % self.ReadWord(60),
                    addr=59))
        widgets.append(
            BaseDev(self,
                    'enable_word',
                    3,
                    target='0x%04x' % self.ReadWord(73),
                    addr=73))
        widgets.append(BaseDev(self, 'cycle_counter', 4, addr=74))
        widgets.append(
            BaseDev(self,
                    'handle_cw',
                    5,
                    has_status=True,
                    target='%d' % self.ReadWord(51),
                    addr=50))
        widgets.append(
            BaseDev(self,
                    'handle_ccw',
                    6,
                    has_status=True,
                    target='%d' % self.ReadWord(54),
                    addr=53))
        widgets.append(BaseDev(self, 'enc1', 7, has_status=True, addr=46))
        widgets.append(BaseDev(self, 'enc2', 8, has_status=True, addr=48))
        widgets.append(
            BaseDev(self,
                    'arm_switch',
                    9,
                    has_status=True,
                    target='%d' % self.ReadWord(63),
                    addr=62))
        widgets.append(BaseDev(self, 'encoder1', 10, has_status=False,
                               addr=65))
        widgets.append(
            BaseDev(self,
                    'arm',
                    11,
                    has_status=True,
                    target='%f' % self.ReadFloat(70),
                    value_offset=2,
                    addr=68))
        widgets.append(
            BaseDev(self,
                    'magnet',
                    12,
                    has_status=True,
                    target='%d' % self.ReadWord(57),
                    addr=56))
        widgets.append(
            BaseDev(self,
                    'air',
                    13,
                    has_status=True,
                    target='%d' % self.ReadWord(60),
                    addr=59))

        for w in widgets:
            self.addWidget(w)

        widgets.sort(key=lambda w: w.index)
        self.widgets = widgets

        self.startTimer(225)  # in ms !

    def resetter(self, index):
        w = self.widgets[index]
        if w.has_status:
            addr = w.base_address + w.offset
            if w.has_target:
                addr += w.offset
            print(addr)
            self.reset(addr)
        else:
            print("resetter: device %d has no status" % index)

    def stopper(self, index):
        w = self.widgets[index]
        if w.has_target:
            addr = w.base_address
            if w.name == 'enable_word':
                print("stopper: DISABLING %d" % (addr))
                self.WriteWord(addr, 0)
            else:
                addr += w.offset
                if w.has_target:
                    addr += w.offset
                print("stopper: stopping on addr %d" % (addr))
                self.stop(addr)

        else:
            print("stopper: cannot stop - no target %d" % index)

    def targeter(self, index, valuestr):
        w = self.widgets[index]
        if w.has_target:
            v = str(valuestr).strip()
            if not v:
                return  # ignore empty values (no value entered into the box?)
            addr = w.base_address
            if w.offset == 2:
                v = float(v)
                addr += w.offset
                print("targeter: setting addr %d to %f" % (addr, v))
                self.WriteFloat(addr, v)
            else:
                if v.startswith('0x') or v.startswith('0X'):
                    v = int(v[2:], 16)
                elif v.startswith(('x', 'X', '$')):
                    v = int(v[1:], 16)
                else:
                    v = int(v)
                if w.name != 'enable_word':
                    addr += w.offset
                print("targeter: setting addr %d to %r" % (addr, valuestr))
                self.WriteWord(addr, v)
        else:
            print("targeter: device fas no target %d:%r" % (index, valuestr))

    def ReadWord(self, addr):
        return self._registers[int(addr)]

    def WriteWord(self, addr, value):
        self._bus.write_register(int(addr | 0x4000), int(value))
        self._sync()

    def ReadDWord(self, addr):
        return unpack(
            '<I',
            pack('<HH', self._registers[int(addr)],
                 self._registers[int(addr) + 1]))

    def WriteDWord(self, addr, value):
        low, high = unpack('<HH', pack('<I', int(value)))
        self._bus.write_registers(int(addr | 0x4000), [low, high])
        self._sync()

    def ReadFloat(self, addr):
        return unpack(
            '<f',
            pack('<HH', self._registers[int(addr) + 1],
                 self._registers[int(addr)]))

    def WriteFloat(self, addr, value):
        low, high = unpack('<HH', pack('<f', float(value)))
        self._bus.write_registers(int(addr | 0x4000), [high, low])
        self._sync()

    def _sync(self):
        if self._bus:
            self._registers = self._bus.read_holding_registers(0x4000,
                                                               75).registers[:]
            # print(self._registers)
        else:
            self._registers = [self.i] * 75
            self.i += 1

    def reset(self, addr):
        self.WriteWord(addr, 0x0fff & self.ReadWord(addr))

    def stop(self, addr):
        self.WriteWord(addr, 0x1000 | (0x0fff & self.ReadWord(addr)))

    def timerEvent(self, event):

        self._sync()
        w = self.widgets

        # 1: %MB68: cycle counter
        val = self.ReadWord(34)
        stat = self.ReadWord(35)
        w[0].valueWidget.setText(bin(65536 | val)[3:])
        w[0].statvalueWidget.setText('0x%04x' % stat)
        w[0].statusWidget.setText('mtt motor inputs')

        # 10: %MB96: spare inputs
        val = self.ReadWord(44)
        stat = self.ReadWord(45)
        w[1].valueWidget.setText(bin(65536 | val)[3:])
        w[1].statvalueWidget.setText('0x%04x' % stat)
        w[1].statusWidget.setText('spare inputs')

        # 17: %MB136: spare outputs
        val = self.ReadWord(59)
        target = self.ReadWord(60)
        stat = self.ReadWord(61)
        stati = Stati(stat)
        w[2].valueWidget.setText('%d' % val)
        w[2].statvalueWidget.setText('0x%04x' % stat)
        w[2].statusWidget.setText(', '.join(stati))
        w[2].targetWidget.setPlaceholderText('%d' % target)

        # 19: %MB146: enable code word
        val = self.ReadWord(73)
        w[3].valueWidget.setText('0x%04x' % val)
        w[3].targetWidget.setPlaceholderText('0x%04x' % val)

        # 20: %MB148: cycle counter
        val = self.ReadWord(74)
        w[4].valueWidget.setText('0x%04x' % val)

        # 13: %MB112: liftclamp
        val = self.ReadWord(50)
        target = self.ReadWord(51)
        stat = self.ReadWord(52)
        stati = Stati(stat)
        if (stat & 0x9000) == 0x9000:
            stati.append('ERR:Movement timed out')
        if stat & 0x0800:
            stati.append('ERR:liftclamp switches in Error')
        if stat & 0x0004:
            stati.append('No Air pressure')
        if stat & 0x0002:
            stati.append('ERR:Actuator Wire shorted!')
        if stat & 0x0001:
            stati.append('ERR:Actuator Wire open!')
        w[5].valueWidget.setText('%d' % val)
        w[5].statvalueWidget.setText('0x%04x' % stat)
        w[5].statusWidget.setText(', '.join(stati))
        w[5].targetWidget.setPlaceholderText('%d' % target)

        # 13: %MB112: liftclamp
        val = self.ReadWord(53)
        target = self.ReadWord(54)
        stat = self.ReadWord(55)
        stati = Stati(stat)
        if (stat & 0x9000) == 0x9000:
            stati.append('ERR:Movement timed out')
        if stat & 0x0800:
            stati.append('ERR:liftclamp switches in Error')
        if stat & 0x0004:
            stati.append('No Air pressure')
        if stat & 0x0002:
            stati.append('ERR:Actuator Wire shorted!')
        if stat & 0x0001:
            stati.append('ERR:Actuator Wire open!')
        w[6].valueWidget.setText('%d' % val)
        w[6].statvalueWidget.setText('0x%04x' % stat)
        w[6].statusWidget.setText(', '.join(stati))
        w[6].targetWidget.setPlaceholderText('%d' % target)

        # 7: %MB192: enc1
        val = self.ReadWord(46)
        stat = self.ReadWord(47)
        stati = Stati(stat)
        if stat & 0x0002:
            stati.append('ERR:Underflow!')
        if stat & 0x0001:
            stati.append('ERR:Overflow!')
        w[7].valueWidget.setText(str(val))
        w[7].statvalueWidget.setText('0x%04x' % stat)
        w[7].statusWidget.setText(', '.join(stati))

        # 7: %MB192: arm
        val = self.ReadWord(48)
        stat = self.ReadWord(49)
        stati = Stati(stat)
        if stat & 0x0002:
            stati.append('ERR:Underflow!')
        if stat & 0x0001:
            stati.append('ERR:Overflow!')
        w[8].valueWidget.setText(str(val))
        w[8].statvalueWidget.setText('0x%04x' % stat)
        w[8].statusWidget.setText(', '.join(stati))

        # 17: %MB136: spare outputs
        val = self.ReadWord(62)
        target = self.ReadWord(63)
        stat = self.ReadWord(64)
        stati = Stati(stat)
        w[9].valueWidget.setText('%d' % val)
        w[9].statvalueWidget.setText('0x%04x' % stat)
        w[9].statusWidget.setText(', '.join(stati))
        w[9].targetWidget.setPlaceholderText('%d' % target)

        # encoder
        val = self.ReadFloat(65)
        w[10].valueWidget.setText('%f' % val)

        # motro
        val = self.ReadFloat(68)
        target = self.ReadFloat(70)
        stat = self.ReadWord(72)
        stati = Stati(stat)
        w[11].valueWidget.setText('%f' % val)
        w[11].statvalueWidget.setText('0x%04x' % stat)
        w[11].statusWidget.setText(', '.join(stati))
        w[11].targetWidget.setPlaceholderText('%f' % target)

        # 13: %MB112: liftclamp
        val = self.ReadWord(56)
        target = self.ReadWord(57)
        stat = self.ReadWord(58)
        stati = Stati(stat)
        if (stat & 0x9000) == 0x9000:
            stati.append('ERR:Movement timed out')
        if stat & 0x0800:
            stati.append('ERR:liftclamp switches in Error')
        if stat & 0x0004:
            stati.append('No Air pressure')
        if stat & 0x0002:
            stati.append('ERR:Actuator Wire shorted!')
        if stat & 0x0001:
            stati.append('ERR:Actuator Wire open!')
        w[12].valueWidget.setText('%d' % val)
        w[12].statvalueWidget.setText('0x%04x' % stat)
        w[12].statusWidget.setText(', '.join(stati))
        w[12].targetWidget.setPlaceholderText('%d' % target)

        # 13: %MB112: air
        val = self.ReadWord(59)
        target = self.ReadWord(60)
        stat = self.ReadWord(61)
        stati = Stati(stat)
        if (stat & 0x9000) == 0x9000:
            stati.append('ERR:Movement timed out')
        if stat & 0x0800:
            stati.append('ERR:liftclamp switches in Error')
        if stat & 0x0004:
            stati.append('No Air pressure')
        if stat & 0x0002:
            stati.append('ERR:Actuator Wire shorted!')
        if stat & 0x0001:
            stati.append('ERR:Actuator Wire open!')
        w[13].valueWidget.setText('%d' % val)
        w[13].statvalueWidget.setText('0x%04x' % stat)
        w[13].statusWidget.setText(', '.join(stati))
        w[13].targetWidget.setPlaceholderText('%d' % target)

    def addWidget(self, which):
        which.setContentsMargins(10, 0, 0, 0)
        self.scrollLayout.addRow(which)
        l = QFrame()
        l.setLineWidth(1)
        # l.setMidLineWidth(4)
        l.setFrameShape(QFrame.HLine)
        l.setContentsMargins(10, 0, 10, 0)
        self.scrollLayout.addRow(l)
class MainWindow(QMainWindow):
    i = 0

    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        # scroll area Widget contents - layout
        self.scrollLayout = QFormLayout()
        self.scrollLayout.setContentsMargins(0, 0, 0, 0)

        # scroll area Widget contents
        self.scrollWidget = QWidget()
        self.scrollWidget.setLayout(self.scrollLayout)

        # scroll area
        self.scrollArea = QScrollArea()
        self.scrollArea.setWidgetResizable(True)
        self.scrollArea.setWidget(self.scrollWidget)

        # main layout
        self.mainLayout = QVBoxLayout()
        self.mainLayout.setSpacing(0)

        # add all main to the main vLayout
        self.mainLayout.addWidget(self.scrollArea)

        # central Widget
        self.centralWidget = QWidget()
        self.centralWidget.setLayout(self.mainLayout)

        # set central Widget
        self.setCentralWidget(self.centralWidget)

        try:
            self._bus = ModbusTcpClient('wechsler.panda.frm2')
            self._bus.connect()
            self._sync()
            print("PLC conforms to spec %.4f" % self.ReadFloat(0))
        except Exception:
            print("Modbus failed, using demo mode!")
            self._bus = None

        self._sync()

        widgets = []
        widgets.append(WriteWord(self, 'last_liftpos', addr=58 / 2))
        widgets.append(ReadWord(self, 'analog1', addr=92 / 2))
        widgets.append(ReadWord(self, 'analog2', addr=96 / 2))
        widgets.append(AnalogInput(self, 'liftpos_analog', addr=146 / 2))
        widgets.append(DiscreteInput(self, 'lift_sw', addr=68 / 2))
        widgets.append(LIFT(self, 'lift', 104 / 2))

        widgets.append(WriteWord(self, 'last_magpos', addr=60 / 2))
        widgets.append(DiscreteInput(self, 'magazin_sw', addr=72 / 2))
        widgets.append(MAGAZIN(self, 'magazin', addr=110 / 2))

        widgets.append(DiscreteInput(self, 'magazin_occ_sw', addr=84 / 2))
        widgets.append(DiscreteInput(self, 'magazin_occ', addr=88 / 2))

        widgets.append(DiscreteInput(self, 'liftclamp_sw', addr=76 / 2))
        widgets.append(CLAMP(self, 'liftclamp', addr=116 / 2))

        widgets.append(DiscreteInput(self, 'magazinclamp_sw', addr=80 / 2))
        widgets.append(CLAMP(self, 'magazinclamp', addr=122 / 2))

        widgets.append(CLAMP(self, 'tableclamp', addr=128 / 2))

        widgets.append(CLAMP(self, 'inhibit_relay', addr=134 / 2))

        widgets.append(WriteWord(self, 'enable_word', addr=150 / 2))

        widgets.append(DiscreteInput(self, 'spare inputs', addr=100 / 2))
        widgets.append(DiscreteOutput(self, 'spare outputs', addr=140 / 2))

        widgets.append(ReadWord(self, 'cycle_counter', addr=152 / 2))

        for w in widgets:
            self.addWidget(w)

        self.widgets = widgets

        self.startTimer(225)  # in ms !

    def ReadWord(self, addr):
        return self._registers[int(addr)]

    def WriteWord(self, addr, value):
        if self._bus:
            self._bus.write_register(int(addr | 0x4000), int(value))
            self._sync()

    def ReadDWord(self, addr):
        return unpack(
            '<I',
            pack('<HH', self._registers[int(addr)],
                 self._registers[int(addr) + 1]))

    def WriteDWord(self, addr, value):
        if self._bus:
            low, high = unpack('<HH', pack('<I', int(value)))
            self._bus.write_registers(int(addr | 0x4000), [low, high])
            self._sync()

    def ReadFloat(self, addr):
        return unpack(
            '<f',
            pack('<HH', self._registers[int(addr) + 1],
                 self._registers[int(addr)]))

    def WriteFloat(self, addr, value):
        if self._bus:
            low, high = unpack('<HH', pack('<f', float(value)))
            self._bus.write_registers(int(addr | 0x4000), [high, low])
            self._sync()

    def _sync(self):
        if self._bus:
            self._registers = self._bus.read_holding_registers(0x4000,
                                                               77).registers[:]
        else:
            self._registers = [self.i + i for i in range(77)]
            self.i += 1

    def timerEvent(self, event):  # pylint: disable=R0915
        self._sync()
        for w in self.widgets:
            w._update()
        return

    def addWidget(self, which):
        which.setContentsMargins(10, 0, 0, 0)
        self.scrollLayout.addRow(which)
        l = QFrame()
        l.setLineWidth(1)
        # l.setMidLineWidth(4)
        l.setFrameShape(QFrame.HLine)
        l.setContentsMargins(10, 0, 10, 0)
        self.scrollLayout.addRow(l)
Beispiel #15
0
    def initGui(self):
        def log_unhandled(*exc_info):
            traceback.print_exception(*exc_info)
            self.log.exception('unhandled exception in QT callback',
                               exc_info=exc_info)
        sys.excepthook = log_unhandled

        self._qtapp = QApplication(['qtapp'], organizationName='nicos',
                                   applicationName='gui')
        self._master = master = MonitorWindow()

        if self._geometry == 'fullscreen':
            master.showFullScreen()
            master._wantFullScreen = True
            # In some Qt5 versions, showFullScreen is buggy and doesn't
            # actually resize the window (but hides decoration etc).
            # So, explicitly set the geometry of the first screen.
            master.setGeometry(QApplication.screens()[0].geometry())
            QCursor.setPos(master.geometry().bottomRight())
        elif isinstance(self._geometry, tuple):
            w, h, x, y = self._geometry
            master.setGeometry(x, y, w, h)

        # colors used for the display of watchdog warnings, not for the
        # individual value displays
        self._bgcolor = QColor('gray')
        self._black = QColor('black')
        self._red = QColor('red')
        self._gray = QColor('gray')

        master.setWindowTitle(self.title)
        self._bgcolor = master.palette().color(QPalette.Window)

        timefont  = QFont(self.font, self._timefontsize)
        blockfont = QFont(self.font, self._fontsizebig)
        warnfont  = QFont(self.font, self._fontsizebig)
        warnfont.setBold(True)
        labelfont = QFont(self.font, self._fontsize)
        stbarfont = QFont(self.font, int(self._fontsize * 0.8))
        valuefont = QFont(self.valuefont or self.font, self._fontsize)

        blheight = QFontMetrics(blockfont).height()
        tiheight = QFontMetrics(timefont).height()

        # split window into to panels/frames below each other:
        # one displays time, the other is divided further to display blocks.
        # first the timeframe:
        masterframe = QFrame(master)
        masterlayout = QVBoxLayout()
        if self.title:
            self._titlelabel = QLabel(
                '', master, font=timefont, autoFillBackground=True,
                alignment=Qt.AlignHCenter)
            pal = self._titlelabel.palette()
            pal.setColor(QPalette.WindowText, self._gray)
            self._titlelabel.setPalette(pal)
            self._titlelabel.setSizePolicy(QSizePolicy.Preferred,
                                           QSizePolicy.Fixed)
            self._master.updateTitle.connect(self._titlelabel.setText)
            masterlayout.addWidget(self._titlelabel)
            masterlayout.addSpacing(0.2 * tiheight)
        else:
            self._titlelabel = None

        self._warnpanel = QFrame(master)
        self._warnpanel.setVisible(False)

        warningslayout = QVBoxLayout()
        lbl = QLabel('Warnings', self._warnpanel, font=warnfont)
        lbl.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
        warningslayout.addWidget(lbl)
        self._warnlabel = SqueezedLabel('', self._warnpanel, font=blockfont)
        warningslayout.addWidget(self._warnlabel)
        self._warnpanel.setLayout(warningslayout)
        masterlayout.addWidget(self._warnpanel)
        master.switchWarnPanel.connect(self._switch_warnpanel)

        displayframe = QFrame(master)
        self._plots = {}

        colorScheme = lightColorScheme if self.colors == 'light' else None
        fontCache = {1.0: valuefont}

        def _create_field(groupframe, field):

            def _setup(widget):
                fontscale = field.get('fontscale', 1.0)
                if fontscale not in fontCache:
                    fontCache[fontscale] = scaledFont(valuefont, fontscale)
                widget.valueFont = fontCache[fontscale]
                widget.setFont(labelfont)
                for key in field:
                    if key in widget.properties:
                        setattr(widget, key, field[key])
                widget.setSource(self)
                if hasattr(widget, 'widgetInfo'):
                    widget.widgetInfo.connect(self.newWidgetInfo)
                return widget

            if isinstance(field, str):
                field = {'dev': field}
            if 'min' in field:
                field['min'] = repr(field['min'])
            if 'max' in field:
                field['max'] = repr(field['max'])
            setups = field.get('setups', None)

            if 'gui' in field:
                resource = findResource(field.pop('gui'))
                try:
                    instance = uic.loadUi(resource)
                except Exception as err:
                    self.log.exception('could not load .ui file %r, ignoring',
                                       resource)
                    instance = QLabel('%r could not be loaded:\n%s' %
                                      (resource, err))
                else:
                    for child in instance.findChildren(NicosWidget):
                        _setup(child)
                instance.setups = setups
                return instance
            elif 'widget' in field:
                widget_class = self._class_import(field.pop('widget'))
                widget = widget_class(groupframe)
                if isinstance(widget, NicosWidget):
                    _setup(widget)
                for child in widget.findChildren(NicosWidget):
                    _setup(child)
                widget.setups = setups
                return widget
            elif 'plot' in field and plot_available:
                # XXX make this more standard
                plotwidget = self._plots.get(field['plot'])
                if plotwidget:
                    plotwidget.devices += [field.get('dev', field.get('key', ''))]
                    plotwidget.names += [field.get('name', field.get('dev', field.get('key', '')))]
                    return None
                plotwidget = TrendPlot(groupframe)
                _setup(plotwidget)
                plotwidget.legend = field.get('legend', True)
                plotwidget.plotwindow = field.get('plotwindow', 3600)
                plotwidget.plotinterval = field.get('plotinterval', 2)
                self._plots[field['plot']] = plotwidget
                plotwidget.devices = [field.get('dev', field.get('key', ''))]
                plotwidget.names = [field.get('name', field.get('dev', field.get('key', '')))]
                plotwidget.setups = setups
                return plotwidget
            elif 'picture' in field:
                picwidget = PictureDisplay(groupframe)
                picwidget.filepath = field['picture']
                picwidget.setups = setups
                return _setup(picwidget)
            else:
                display = ValueDisplay(groupframe, colorScheme=colorScheme,
                                       showExpiration=self.noexpired)
                display.setups = setups
                return _setup(display)

        # now iterate through the layout and create the widgets to display it
        displaylayout = QVBoxLayout(spacing=20)
        for superrow in self.layout:
            boxlayout = QHBoxLayout(spacing=20)
            boxlayout.setContentsMargins(10, 10, 10, 10)
            for column in superrow:
                columnlayout = QVBoxLayout(spacing=0.8*blheight)
                for block in column:
                    block = self._resolve_block(block)
                    blocklayout_outer = QHBoxLayout()
                    blocklayout_outer.addStretch()
                    blocklayout = QVBoxLayout()
                    blocklayout.addSpacing(0.5 * blheight)
                    blockbox = BlockBox(displayframe, block._title, blockfont,
                                        block._options)
                    for row in block:
                        if row in (None, '---'):
                            blocklayout.addSpacing(12)
                        else:
                            rowlayout = QHBoxLayout()
                            rowlayout.addStretch()
                            rowlayout.addSpacing(self._padding)
                            for field in row:
                                fieldwidget = _create_field(blockbox, field)
                                if fieldwidget:
                                    rowlayout.addWidget(fieldwidget)
                                    rowlayout.addSpacing(self._padding)
                                    if fieldwidget.setups:
                                        if blockbox.setups:
                                            blockbox._onlyfields.append(fieldwidget)
                                        else:
                                            self._onlyfields.append(fieldwidget)
                                            # start hidden
                                            fieldwidget.setHidden(True)
                            rowlayout.addStretch()
                            blocklayout.addLayout(rowlayout)
                    if blockbox.setups:
                        self._onlyblocks.append((blocklayout_outer, blockbox))
                        blockbox.setHidden(True)  # start hidden
                    blocklayout.addSpacing(0.3 * blheight)
                    blockbox.setLayout(blocklayout)
                    blocklayout_outer.addWidget(blockbox)
                    blocklayout_outer.addStretch()
                    columnlayout.addLayout(blocklayout_outer)
                columnlayout.addStretch()
                boxlayout.addLayout(columnlayout)
            displaylayout.addLayout(boxlayout)
        displayframe.setLayout(displaylayout)

        for plot in self._plots.values():
            plot.setSource(self)

        masterlayout.addWidget(displayframe)

        masterframe.setLayout(masterlayout)
        master.setCentralWidget(masterframe)

        # initialize status bar
        self._statuslabel = QLabel(font=stbarfont)
        master.statusBar().addWidget(self._statuslabel)
        self._statustimer = None
        master.show()