Ejemplo n.º 1
0
    def get_measurement_widget(self, parent):
        """."""
        meas_wid = QWidget(parent)
        meas_lay = QVBoxLayout(meas_wid)

        strt = PyDMPushButton(
            meas_wid,
            init_channel=self.devpref.substitute(propty="MeasRespMat-Cmd"),
            pressValue=ConstTLines.MeasRespMatCmd.Start)
        strt.setEnabled(True)
        strt.setToolTip('Start Measurement')
        strt.setIcon(qta.icon('fa5s.play'))
        strt.setObjectName('strt')
        strt.setStyleSheet(
            '#strt{min-width:25px; max-width:25px; icon-size:20px;}')
        stop = PyDMPushButton(
            meas_wid,
            init_channel=self.devpref.substitute(propty="MeasRespMat-Cmd"),
            pressValue=ConstTLines.MeasRespMatCmd.Stop)
        stop.setEnabled(True)
        stop.setToolTip('Stop Measurement')
        stop.setIcon(qta.icon('fa5s.stop'))
        stop.setObjectName('stop')
        stop.setStyleSheet(
            '#stop{min-width:25px; max-width:25px; icon-size:20px;}')
        rst = PyDMPushButton(
            meas_wid,
            init_channel=self.devpref.substitute(propty="MeasRespMat-Cmd"),
            pressValue=ConstTLines.MeasRespMatCmd.Reset)
        rst.setEnabled(True)
        rst.setToolTip('Reset Measurement Status')
        rst.setIcon(qta.icon('fa5s.sync'))
        rst.setObjectName('conf')
        rst.setStyleSheet(
            '#conf{min-width:25px; max-width:25px; icon-size:20px;}')
        lbl = PyDMLabel(
            meas_wid, self.devpref.substitute(propty='MeasRespMat-Mon'))
        lbl.setAlignment(Qt.AlignCenter)
        hbl = QHBoxLayout()
        hbl.setSpacing(8)
        meas_lay.addItem(hbl)
        hbl.addWidget(strt)
        hbl.addWidget(stop)
        hbl.addWidget(rst)
        hbl.addStretch()
        hbl.addWidget(lbl)

        fml = QFormLayout()
        meas_lay.addSpacing(20)
        meas_lay.addItem(fml)
        lbl = QLabel('CH [urad]', meas_wid)
        wid = self.create_pair(meas_wid, 'MeasRespMatKickCH')
        fml.addRow(lbl, wid)
        lbl = QLabel('CV [urad]', meas_wid)
        wid = self.create_pair(meas_wid, 'MeasRespMatKickCV')
        fml.addRow(lbl, wid)
        if self.acc in {'SI', 'BO'}:
            lbl = QLabel('RF [Hz]', meas_wid)
            wid = self.create_pair(meas_wid, 'MeasRespMatKickRF')
            fml.addRow(lbl, wid)
        lbl = QLabel('Wait [s]', meas_wid)
        lbl.setToolTip('Time to wait between kicks')
        wid = self.create_pair(meas_wid, 'MeasRespMatWait')
        fml.addRow(lbl, wid)

        return meas_wid
Ejemplo n.º 2
0
class InjSysStbyControlWidget(QWidget):
    """Injection System Control Widget."""

    expand = Signal()

    def __init__(self,
                 parent=None,
                 prefix=VACA_PREFIX,
                 is_summary=False,
                 handler=None):
        """Init."""
        super().__init__(parent)
        self.prefix = prefix
        self._inj_prefix = SiriusPVName('AS-Glob:AP-InjCtrl').substitute(
            prefix=prefix)
        self._is_summary = is_summary
        self._last_comm = None

        self._handler = handler or InjSysStandbyHandler()
        self._icon_off = qta.icon('mdi.power-off')
        self._icon_on = qta.icon('mdi.power-on')
        self._icon_check = qta.icon('fa5s.check')
        self._pixmap_check = self._icon_check.pixmap(
            self._icon_check.actualSize(QSize(16, 16)))
        self._icon_not = qta.icon('fa5s.times')
        self._pixmap_not = self._icon_not.pixmap(
            self._icon_not.actualSize(QSize(16, 16)))

        self.menu = QMenu(self)
        self.rstord_act = self.menu.addAction('Reset Commands')
        self.rstord_act.triggered.connect(self._reset_commands_order)

        if is_summary:
            self._setupSummary()
        else:
            self._setupFull()

        self._ch_cmdsts = SiriusConnectionSignal(
            self._inj_prefix.substitute(propty='InjSysCmdSts-Mon'))

        self._ch_off_order_sp = SiriusConnectionSignal(
            self._inj_prefix.substitute(propty='InjSysTurnOffOrder-SP'))
        self._ch_off_order_rb = SiriusConnectionSignal(
            self._inj_prefix.substitute(propty='InjSysTurnOffOrder-RB'))
        self._ch_on_order_sp = SiriusConnectionSignal(
            self._inj_prefix.substitute(propty='InjSysTurnOnOrder-SP'))
        self._ch_on_order_rb = SiriusConnectionSignal(
            self._inj_prefix.substitute(propty='InjSysTurnOnOrder-RB'))
        if not is_summary:
            self._ch_cmdone = SiriusConnectionSignal(
                self._inj_prefix.substitute(propty='InjSysCmdDone-Mon'))

        self._ch_cmdsts.new_value_signal[int].connect(
            self._handle_cmdsts_buttons_enbl)
        self._ch_off_order_rb.new_value_signal[str].connect(
            self._handle_buttons_color)
        self._ch_on_order_rb.new_value_signal[str].connect(
            self._handle_buttons_color)
        self._ch_off_order_rb.new_value_signal[str].connect(
            self._handle_actions_state)
        self._ch_on_order_rb.new_value_signal[str].connect(
            self._handle_actions_state)
        if not is_summary:
            self._ch_cmdone.new_value_signal[str].connect(
                self._handle_cmdone_labels)
            self._ch_cmdsts.new_value_signal[int].connect(
                self._handle_cmdsts_labels)

    def _setupSummary(self):
        self._pb_off = PyDMPushButton(self,
                                      label='',
                                      icon=self._icon_off,
                                      init_channel=self._inj_prefix.substitute(
                                          propty='InjSysTurnOff-Cmd'),
                                      pressValue=0)
        self._pb_off.setObjectName('bt')
        self._pb_off.setStyleSheet(
            '#bt{min-width:25px; max-width:25px; icon-size:20px;}')
        self._pb_on = PyDMPushButton(self,
                                     label='',
                                     icon=self._icon_on,
                                     init_channel=self._inj_prefix.substitute(
                                         propty='InjSysTurnOn-Cmd'),
                                     pressValue=0)
        self._pb_on.setObjectName('bt')
        self._pb_on.setStyleSheet(
            '#bt{min-width:25px; max-width:25px; icon-size:20px;}')

        self._led_sts = InjSysStbyLed(self)
        self._led_sts.setStyleSheet(
            'QLed{min-width:1.29em; max-width:1.29em;}')

        lay = QGridLayout(self)
        lay.setAlignment(Qt.AlignCenter)
        lay.addWidget(self._pb_off, 0, 0)
        lay.addWidget(self._pb_on, 0, 1)
        lay.addWidget(self._led_sts, 1, 0, 1, 2, alignment=Qt.AlignCenter)

        # menu
        for cmmtype in ['on', 'off']:
            order = getattr(self._handler, cmmtype + '_order')
            menu = QMenu('Select Turn ' + cmmtype.upper() + ' Commands', self)
            setattr(self, cmmtype + '_menu', menu)
            self.menu.addMenu(menu)
            for cmm in order:
                act = menu.addAction(self._handler.HANDLER_DESC[cmm])
                act.setObjectName(cmm)
                act.setCheckable(True)

    def _setupFull(self):
        lay = QGridLayout(self)

        lay.addWidget(QLabel('Off', self, alignment=Qt.AlignCenter), 0, 1)
        lay.addWidget(QLabel('On', self, alignment=Qt.AlignCenter), 0, 2)
        lay.addWidget(QLabel('Status', self, alignment=Qt.AlignCenter), 0, 3)

        self._checkbox_off = dict()
        self._checkbox_on = dict()
        self._labels_sts = dict()
        for idx, name in enumerate(self._handler.DEF_ON_ORDER):
            cb_off = QCheckBox(self)
            cb_off.setObjectName(name)
            self._checkbox_off[name] = cb_off
            cb_on = QCheckBox(self)
            cb_on.setObjectName(name)
            self._checkbox_on[name] = cb_on
            desc = self._handler.HANDLER_DESC[name]
            splitd = desc.split('(')
            lbl_txt = splitd[0]
            tip = ''
            if len(splitd) > 1:
                lbl_txt, tip = splitd
            lb_dsc = QLabel(lbl_txt, self, alignment=Qt.AlignLeft)
            if tip:
                lb_dsc.setToolTip(tip[:-1])
            lb_sts = QLabel('', self, alignment=Qt.AlignCenter)
            lb_sts.setObjectName(name)
            self._labels_sts[name] = lb_sts
            lay.addWidget(lb_dsc, idx + 1, 0)
            lay.addWidget(cb_off, idx + 1, 1, alignment=Qt.AlignCenter)
            lay.addWidget(cb_on, idx + 1, 2, alignment=Qt.AlignCenter)
            lay.addWidget(lb_sts, idx + 1, 3)

        self._pb_off = PyDMPushButton(self,
                                      label='',
                                      icon=self._icon_off,
                                      init_channel=self._inj_prefix.substitute(
                                          propty='InjSysTurnOff-Cmd'),
                                      pressValue=0)
        self._pb_off.setObjectName('bt')
        self._pb_off.setStyleSheet(
            '#bt{min-width:25px; max-width:25px; icon-size:20px;}')
        self._pb_on = PyDMPushButton(self,
                                     label='',
                                     icon=self._icon_on,
                                     init_channel=self._inj_prefix.substitute(
                                         propty='InjSysTurnOn-Cmd'),
                                     pressValue=0)
        self._pb_on.setObjectName('bt')
        self._pb_on.setStyleSheet(
            '#bt{min-width:25px; max-width:25px; icon-size:20px;}')

        self._led_sts = InjSysStbyLed(self)

        lay.addWidget(self._pb_off, 6, 1)
        lay.addWidget(self._pb_on, 6, 2)
        lay.addWidget(self._led_sts, 6, 3)

    @Slot(int)
    def _handle_cmdsts_buttons_enbl(self, new_sts):
        if new_sts == _Const.InjSysCmdSts.On:
            self._pb_on.setEnabled(False)
            self._pb_on.setIcon(
                qta.icon('fa5s.spinner', animation=qta.Spin(self._pb_on)))
            self._pb_off.setEnabled(False)
        elif new_sts == _Const.InjSysCmdSts.Off:
            self._pb_on.setEnabled(False)
            self._pb_off.setEnabled(False)
            self._pb_off.setIcon(
                qta.icon('fa5s.spinner', animation=qta.Spin(self._pb_off)))
        else:
            if not self._pb_on.isEnabled():
                self._pb_on.setEnabled(True)
                self._pb_off.setEnabled(True)
                self._pb_on.setIcon(self._icon_on)
                self._pb_off.setIcon(self._icon_off)

    @Slot(str)
    def _handle_cmdone_labels(self, new_done):
        for name in self._handler.DEF_ON_ORDER:
            lbl = self._labels_sts[name]
            if name in new_done:
                lbl.setPixmap(self._pixmap_check)
            elif self._ch_cmdsts.value == _Const.InjSysCmdSts.Idle:
                lbl.setPixmap(self._pixmap_not)

    @Slot(int)
    def _handle_cmdsts_labels(self, new_sts):
        if new_sts == _Const.InjSysCmdSts.On:
            self._last_comm = new_sts
            for name in self._handler.DEF_ON_ORDER:
                if self._ch_on_order_rb.value is None:
                    break
                lbl = self._labels_sts[name]
                if name in self._ch_on_order_rb.value:
                    icon = qta.icon('fa5s.spinner')
                    pixmap = icon.pixmap(icon.actualSize(QSize(16, 16)))
                    lbl.setPixmap(pixmap)
                else:
                    lbl.setPixmap(QPixmap())
        elif new_sts == _Const.InjSysCmdSts.Off:
            self._last_comm = new_sts
            for name in self._handler.DEF_OFF_ORDER:
                if self._ch_off_order_rb.value is None:
                    break
                lbl = self._labels_sts[name]
                if name in self._ch_off_order_rb.value:
                    icon = qta.icon('fa5s.spinner')
                    pixmap = icon.pixmap(icon.actualSize(QSize(16, 16)))
                    lbl.setPixmap(pixmap)
                else:
                    lbl.setPixmap(QPixmap())
        else:
            done = self._ch_cmdone.value
            for name in self._handler.DEF_ON_ORDER:
                if done is None or name in done:
                    continue
                lbl = self._labels_sts[name]
                if self._last_comm == _Const.InjSysCmdSts.On and \
                        name in self._ch_on_order_rb.value:
                    lbl.setPixmap(self._pixmap_not)
                elif self._last_comm == _Const.InjSysCmdSts.Off and \
                        name in self._ch_off_order_rb.value:
                    lbl.setPixmap(self._pixmap_not)
            self._last_comm = None

    @Slot()
    def _set_commands_order(self):
        if self._is_summary:
            if self.sender() in self.on_menu.actions():
                on_order = [
                    a.objectName() for a in self.on_menu.actions()
                    if a.isChecked()
                ]
                self._ch_on_order_sp.send_value_signal[str].emit(
                    ','.join(on_order))
            elif self.sender() in self.off_menu.actions():
                off_order = [
                    a.objectName() for a in self.off_menu.actions()
                    if a.isChecked()
                ]
                self._ch_off_order_sp.send_value_signal[str].emit(
                    ','.join(off_order))
        else:
            if self.sender() in self._checkbox_on.values():
                checked = [
                    w.objectName() for w in self._checkbox_on.values()
                    if w.isChecked()
                ]
                on_order = [
                    h for h in self._handler.DEF_ON_ORDER if h in checked
                ]
                self._ch_on_order_sp.send_value_signal[str].emit(
                    ','.join(on_order))
            elif self.sender() in self._checkbox_off.values():
                checked = [
                    w.objectName() for w in self._checkbox_off.values()
                    if w.isChecked()
                ]
                off_order = [
                    h for h in self._handler.DEF_OFF_ORDER if h in checked
                ]
                self._ch_off_order_sp.send_value_signal[str].emit(
                    ','.join(off_order))

    @Slot()
    def _reset_commands_order(self):
        self._ch_off_order_sp.send_value_signal[str].emit(','.join(
            self._handler.DEF_OFF_ORDER))
        self._ch_on_order_sp.send_value_signal[str].emit(','.join(
            self._handler.DEF_ON_ORDER))
        if self._is_summary:
            for menu in [self.off_menu, self.on_menu]:
                for act in menu.actions():
                    act.toggled.disconnect()
                    act.setChecked(True)
                    act.toggled.connect(self._set_commands_order)
        else:
            for group in [self._checkbox_off, self._checkbox_on]:
                for wid in group.values():
                    wid.toggled.disconnect()
                    wid.setChecked(True)
                    wid.toggled.connect(self._set_commands_order)

    @Slot()
    def _handle_buttons_color(self):
        off_color = 'yellow' if self._ch_off_order_rb.value != \
            ','.join(self._handler.DEF_OFF_ORDER) else 'white'
        self._pb_off.setStyleSheet(
            '#bt{min-width:25px; max-width:25px; icon-size:20px;'
            'background-color: ' + off_color + ';}')
        on_color = 'yellow' if self._ch_on_order_rb.value != \
            ','.join(self._handler.DEF_ON_ORDER) else 'white'
        self._pb_on.setStyleSheet(
            '#bt{min-width:25px; max-width:25px; icon-size:20px;'
            'background-color: ' + on_color + ';}')

    @Slot(str)
    def _handle_actions_state(self, sts):
        state = 'on' if 'On' in self.sender().address else 'off'
        channel = getattr(self, '_ch_' + state + '_order_rb')
        if channel.value is None:
            return

        if self._is_summary:
            group = getattr(self, state + '_menu').actions()
        else:
            group = getattr(self, '_checkbox_' + state).values()
        for obj in group:
            obj.disconnect()
            ost = obj.objectName() in sts
            obj.setChecked(ost)
            obj.toggled.connect(self._set_commands_order)

    def contextMenuEvent(self, event):
        """Show a custom context menu."""
        self.menu.popup(self.mapToGlobal(event.pos()))
Ejemplo n.º 3
0
class DataWriter(PyDMFrame):
    def __init__(self, parent=None, init_channel=None):
        PyDMFrame.__init__(self, parent, init_channel)
        self._node = None

    def connection_changed(self, connected):
        build = (self._node is None) and (self._connected != connected
                                          and connected is True)
        super(DataWriter, self).connection_changed(connected)

        if not build:
            return

        self._node = nodeFromAddress(self.channel)
        self._path = self.channel

        vb = QVBoxLayout()
        self.setLayout(vb)

        gb = QGroupBox('Data File Control ({}) '.format(self._node.name))
        vb.addWidget(gb)

        vb = QVBoxLayout()
        gb.setLayout(vb)

        fl = QFormLayout()
        fl.setRowWrapPolicy(QFormLayout.DontWrapRows)
        fl.setFormAlignment(Qt.AlignHCenter | Qt.AlignTop)
        fl.setLabelAlignment(Qt.AlignRight)
        vb.addLayout(fl)

        self._dataFile = PyRogueLineEdit(parent=None,
                                         init_channel=self._path + '.DataFile')
        self._dataFile.alarmSensitiveContent = False
        self._dataFile.alarmSensitiveBorder = True
        fl.addRow('Data File:', self._dataFile)

        hb = QHBoxLayout()
        vb.addLayout(hb)

        self._browsebutton = QPushButton('Browse')
        self._browsebutton.clicked.connect(self._browse)
        hb.addWidget(self._browsebutton)

        self._autonamebutton = PyDMPushButton(label='Auto Name',
                                              pressValue=1,
                                              init_channel=self._path +
                                              '.AutoName')
        hb.addWidget(self._autonamebutton)

        self._openbutton = PyDMPushButton(label='Open',
                                          pressValue=1,
                                          init_channel=self._path + '.Open')
        self._openbutton.clicked.connect(self._openDataFile)
        hb.addWidget(self._openbutton)

        self._closebutton = PyDMPushButton(label='Close',
                                           pressValue=1,
                                           init_channel=self._path + '.Close')
        self._closebutton.check_enable_state = lambda: None
        self._closebutton.clicked.connect(self._closeDataFile)
        self._closebutton.setEnabled(False)
        hb.addWidget(self._closebutton)

        hb = QHBoxLayout()
        vb.addLayout(hb)

        vbl = QVBoxLayout()
        hb.addLayout(vbl)

        fl = QFormLayout()
        fl.setRowWrapPolicy(QFormLayout.DontWrapRows)
        fl.setFormAlignment(Qt.AlignHCenter | Qt.AlignTop)
        fl.setLabelAlignment(Qt.AlignRight)
        vbl.addLayout(fl)

        w = PyRogueLineEdit(parent=None,
                            init_channel=self._path + '.BufferSize')
        w.alarmSensitiveContent = False
        w.alarmSensitiveBorder = True
        fl.addRow('Buffer Size:', w)

        w = PyDMLabel(parent=None, init_channel=self._path + '.IsOpen/disp')
        w.alarmSensitiveContent = False
        w.alarmSensitiveBorder = True
        fl.addRow('File Open:', w)

        w = PyDMLabel(parent=None, init_channel=self._path + '.CurrentSize')
        w.alarmSensitiveContent = False
        w.alarmSensitiveBorder = True
        fl.addRow('Current File Size:', w)

        vbr = QVBoxLayout()
        hb.addLayout(vbr)

        fl = QFormLayout()
        fl.setRowWrapPolicy(QFormLayout.DontWrapRows)
        fl.setFormAlignment(Qt.AlignHCenter | Qt.AlignTop)
        fl.setLabelAlignment(Qt.AlignRight)
        vbr.addLayout(fl)

        w = PyRogueLineEdit(parent=None,
                            init_channel=self._path + '.MaxFileSize')
        w.alarmSensitiveContent = False
        w.alarmSensitiveBorder = True
        fl.addRow('Max Size:', w)

        w = PyDMLabel(parent=None, init_channel=self._path + '.FrameCount')
        w.alarmSensitiveContent = False
        w.alarmSensitiveBorder = True
        fl.addRow('Frame Count:', w)

        w = PyDMLabel(parent=None, init_channel=self._path + '.TotalSize')
        w.alarmSensitiveContent = False
        w.alarmSensitiveBorder = True
        fl.addRow('Total File Size:', w)

    @Slot()
    def _closeDataFile(self):
        self._dataFile.setEnabled(True)
        self._browsebutton.setEnabled(True)
        self._openbutton.setEnabled(True)
        self._autonamebutton.setEnabled(True)
        self._closebutton.setEnabled(False)

    @Slot()
    def _openDataFile(self):
        self._dataFile.setEnabled(False)
        self._browsebutton.setEnabled(False)
        self._openbutton.setEnabled(False)
        self._autonamebutton.setEnabled(False)
        self._closebutton.setEnabled(True)

    @Slot()
    def _browse(self):
        dlg = QFileDialog()
        sug = datetime.datetime.now().strftime("data_%Y%m%d_%H%M%S.dat")

        dataFile = dlg.getSaveFileName(
            options=QFileDialog.DontConfirmOverwrite,
            directory=sug,
            caption='Select data file',
            filter='Data Files(*.dat);;All Files(*.*)')

        # Detect QT5 return
        if isinstance(dataFile, tuple):
            dataFile = dataFile[0]

        if dataFile != '':
            self._dataFile.setText(dataFile)
            self._dataFile.send_value()