Ejemplo n.º 1
0
class MainLauncher(SiriusMainWindow):
    """Main Launcher."""

    showMonitor = Signal()
    showStatus = Signal()
    showEgun = Signal()

    def __init__(self, parent=None, prefix=VACA_PREFIX):
        """Init."""
        super().__init__(parent)
        self._prefix = prefix

        # window settings
        self.setObjectName('ASApp')
        self.setWindowTitle('Sirius Launcher')
        self.setWindowIcon(
            qta.icon('mdi.rocket', color=get_appropriate_color('AS')))

        screens = QApplication.screens()
        screen_idx = 3 if len(screens) == 8 else 0
        topleft = screens[screen_idx].geometry().topLeft()
        self.move(topleft.x(), topleft.y() + 20)
        self.setWindowFlags(Qt.WindowStaysOnTopHint)

        # menubar
        menubar = get_object(ismenubar=True)
        menubar.setNativeMenuBar(False)
        self.setMenuBar(menubar)
        self._setupUi()

        # connect window signals
        connect_newprocess(self,
                           'sirius-hla-as-ap-monitor.py',
                           parent=self,
                           signal=self.showMonitor)
        connect_newprocess(self,
                           'sirius-hla-si-ap-genstatus.py',
                           parent=self,
                           signal=self.showStatus)
        connect_newprocess(self,
                           'sirius-hla-li-eg-control.py',
                           parent=self,
                           signal=self.showEgun)

        # set focus policy
        self.setFocus(True)
        self.setFocusPolicy(Qt.StrongFocus)

    def _setupUi(self):
        # Machine Shift
        self.wid_shift = QGroupBox('Machine Shift')
        machshift_pvname = SiriusPVName(
            'AS-Glob:AP-MachShift:Mode-Sel').substitute(prefix=self._prefix)
        cbox_shift_mode = SiriusEnumComboBox(self, machshift_pvname)
        label_shift_mode = MachShiftLabel(self, self._prefix)
        label_shift_mode.label.setStyleSheet(
            'QLabel{max-height: 2em; min-width: 7em;}')
        lay_shift = QGridLayout(self.wid_shift)
        lay_shift.setVerticalSpacing(5)
        lay_shift.setAlignment(Qt.AlignCenter)
        lay_shift.addWidget(cbox_shift_mode, 1, 0)
        lay_shift.addWidget(label_shift_mode, 2, 0)

        # Injection System
        self.wid_injsys = QGroupBox('Inj.System')
        wid_injsys = InjSysStbyControlWidget(self,
                                             self._prefix,
                                             is_summary=True)
        lay_injsys = QGridLayout(self.wid_injsys)
        lay_injsys.setAlignment(Qt.AlignCenter)
        lay_injsys.setContentsMargins(0, 0, 0, 0)
        lay_injsys.addWidget(wid_injsys)

        # Egun triggers
        self.wid_egun = QGroupBox('Egun Trig.')
        self.wid_egun.setStyleSheet('min-width: 5em;')
        egun_dev = SiriusPVName('LI-01:EG-TriggerPS').substitute(
            prefix=self._prefix)
        but_egun_trigger = PyDMStateButton(
            self, egun_dev.substitute(propty_name='enable'))
        led_egun_trigger = SiriusLedState(
            self, egun_dev.substitute(propty_name='enablereal'))
        lay_egun = QGridLayout(self.wid_egun)
        lay_egun.setVerticalSpacing(5)
        lay_egun.addWidget(but_egun_trigger, 1, 0)
        lay_egun.addWidget(led_egun_trigger, 2, 0)

        # injection control
        injctrl_dev = SiriusPVName('AS-Glob:AP-InjCtrl')
        injctrl_dev = injctrl_dev.substitute(prefix=self._prefix)

        self.wid_inject = QGroupBox('Injection')
        self.ch_injmode = SiriusConnectionSignal(
            injctrl_dev.substitute(propty='Mode-Sts'))
        self.ch_injmode.new_value_signal[int].connect(
            self._handle_injmode_settings_vis)

        # # Settings
        label_sett = QLabel('<h4>Sett.</h4>', self, alignment=Qt.AlignCenter)
        led_sett = InjDiagLed(self)
        self.wid_injsett = QWidget()
        lay_injsett = QGridLayout(self.wid_injsett)
        lay_injsett.setContentsMargins(0, 0, 0, 0)
        lay_injsett.setAlignment(Qt.AlignTop)
        lay_injsett.addWidget(label_sett, 0, 0)
        lay_injsett.addWidget(led_sett, 1, 0)

        # # Auto Stop
        self.label_injauto = QLabel('<h4>AutoStop</h4>',
                                    self,
                                    alignment=Qt.AlignCenter)
        self.but_injauto = PyDMStateButton(
            self, injctrl_dev.substitute(propty='AutoStop-Sel'))
        self.led_injauto = SiriusLedState(
            self, injctrl_dev.substitute(propty='AutoStop-Sts'))
        self.wid_injauto = QWidget()
        self.wid_injauto.setObjectName('wid')
        self.wid_injauto.setStyleSheet("#wid{min-width: 8em; max-width: 8em;}")
        lay_injauto = QGridLayout(self.wid_injauto)
        lay_injauto.setContentsMargins(0, 0, 0, 0)
        lay_injauto.setAlignment(Qt.AlignTop)
        lay_injauto.addWidget(self.label_injauto, 0, 0)
        lay_injauto.addWidget(self.but_injauto, 1, 0)
        lay_injauto.addWidget(self.led_injauto, 2, 0)

        # # Top-up status
        label_tusts = QLabel('<h4>Status</h4>', self, alignment=Qt.AlignCenter)
        label_tunow = ClockLabel(self)
        label_tunow.setStyleSheet('max-height:2em;')
        label_tunxt = SiriusLabel(
            self, injctrl_dev.substitute(propty='TopUpNextInj-Mon'))
        label_tunxt.displayFormat = SiriusLabel.DisplayFormat.Time
        label_tunxt.setAlignment(Qt.AlignCenter)
        label_tunxt.setStyleSheet('max-height:2em;')
        but_round = PyDMPushButton(
            self, '', qta.icon('mdi.tilde'), 1, False,
            injctrl_dev.substitute(propty='TopUpNextInjRound-Cmd'))
        but_round.setObjectName('but')
        but_round.setStyleSheet(
            '#but{min-width:18px; max-width:18px; icon-size:16px;}')
        self.wid_tusts = QWidget()
        self.wid_tusts.setObjectName('wid')
        self.wid_tusts.setStyleSheet("#wid{min-width: 8em; max-width: 8em;}")
        lay_tusts = QGridLayout(self.wid_tusts)
        lay_tusts.setContentsMargins(0, 0, 0, 0)
        lay_tusts.setAlignment(Qt.AlignTop)
        lay_tusts.addWidget(label_tusts, 0, 0, 1, 2)
        lay_tusts.addWidget(QLabel('Now:', self), 1, 0)
        lay_tusts.addWidget(label_tunow, 1, 1)
        lay_tusts.addWidget(QLabel('Next:', self), 2, 0)
        lay_tusts.addWidget(label_tunxt, 2, 1)
        lay_tusts.addWidget(but_round, 2, 2)
        self.wid_tusts.setVisible(False)

        # # Control
        label_inj = QLabel('<h4>Control</h4>', self, alignment=Qt.AlignCenter)
        self.but_tiinj = EVGInjectionButton(self, self._prefix)
        self.but_topup = PyDMStateButton(
            self, injctrl_dev.substitute(propty='TopUpState-Sel'))
        self.but_topup.setVisible(False)
        lay_inject_sel = QGridLayout()
        lay_inject_sel.setAlignment(Qt.AlignCenter)
        lay_inject_sel.addWidget(self.but_tiinj, 0, 0)
        lay_inject_sel.addWidget(self.but_topup, 0, 0)
        led_injsts = EVGInjectionLed(self, self._prefix)
        label_injcnt = PyDMLabel(self)
        label_injcnt.setToolTip(
            'Count injection pulses when Egun Trigger is enabled.')
        label_injcnt.channel = SiriusPVName(
            'AS-Glob:AP-CurrInfo:InjCount-Mon').substitute(prefix=self._prefix)
        label_injcnt.setStyleSheet('QLabel{max-width: 3.5em;}')
        lay_inject_sts = QHBoxLayout()
        lay_inject_sts.setContentsMargins(0, 0, 0, 0)
        lay_inject_sts.setAlignment(Qt.AlignTop)
        lay_inject_sts.addWidget(led_injsts)
        lay_inject_sts.addWidget(label_injcnt)
        self.wid_injctrl = QWidget()
        lay_injctrl = QGridLayout(self.wid_injctrl)
        lay_injctrl.setContentsMargins(0, 0, 0, 0)
        lay_injctrl.setAlignment(Qt.AlignTop)
        lay_injctrl.addWidget(label_inj, 0, 2, alignment=Qt.AlignCenter)
        lay_injctrl.addLayout(lay_inject_sel, 1, 2, alignment=Qt.AlignCenter)
        lay_injctrl.addLayout(lay_inject_sts, 2, 2, alignment=Qt.AlignCenter)

        # # Injection Auxiliary section
        self.wid_injlog = QGroupBox('Injection Log')
        label_injlog = PyDMLogLabel(self,
                                    injctrl_dev.substitute(propty='Log-Mon'),
                                    replace=[
                                        'Remaining time',
                                    ])
        lay_injlog = QGridLayout(self.wid_injlog)
        lay_injlog.addWidget(label_injlog, 0, 0)
        self.wid_injlog.setVisible(False)

        self.wid_mon = MonitorSummaryWidget(self, self._prefix)
        self.wid_mon.setVisible(False)

        # # Target Current
        self._ld_currtgt = QLabel('<h4>Target Curr.</h4>',
                                  self,
                                  alignment=Qt.AlignCenter)
        self._sb_currtgt = SiriusSpinbox(
            self, injctrl_dev.substitute(propty='TargetCurrent-SP'))
        self._sb_currtgt.showStepExponent = False
        self._lb_currtgt = PyDMLabel(
            self, injctrl_dev.substitute(propty='TargetCurrent-RB'))
        self._lb_currtgt.showUnits = True
        self._wid_tcurr = QWidget()
        lay_tcurr = QGridLayout(self._wid_tcurr)
        lay_tcurr.setContentsMargins(0, 0, 0, 0)
        lay_tcurr.setAlignment(Qt.AlignTop)
        lay_tcurr.addWidget(self._ld_currtgt, 0, 0)
        lay_tcurr.addWidget(self._sb_currtgt, 1, 0)
        lay_tcurr.addWidget(self._lb_currtgt, 2, 0)

        # # Bucket List
        self._bucket_list = BucketList(self, prefix=self._prefix, min_size=15)

        self.wid_fill = QWidget()
        lay_fill = QGridLayout(self.wid_fill)
        lay_fill.setContentsMargins(0, 0, 0, 0)
        lay_fill.setHorizontalSpacing(9)
        lay_fill.addWidget(self._wid_tcurr, 0, 0)
        lay_fill.addWidget(self._bucket_list, 0, 1)
        self.wid_fill.setVisible(False)

        pbt_aux = QPushButton('v', self)
        pbt_aux.setToolTip('Show Injection Auxiliary section.')
        pbt_aux.clicked.connect(self._toggle_show_injaux)
        pbt_aux.setStyleSheet('QPushButton{max-width: 0.8em;}')
        pbt_bl = QPushButton('>', self)
        pbt_bl.setToolTip('Show bucket list and target current controls.')
        pbt_bl.clicked.connect(self._toggle_show_bucketlist)
        pbt_bl.setStyleSheet('QPushButton{max-width: 0.8em;}')

        lay_inj = QGridLayout(self.wid_inject)
        lay_inj.setAlignment(Qt.AlignTop)
        lay_inj.setVerticalSpacing(5)
        lay_inj.setHorizontalSpacing(12)
        lay_inj.addWidget(self.wid_injsett, 0, 0, 2, 1)
        lay_inj.addWidget(self.wid_injauto, 0, 1, 2, 1)
        lay_inj.addWidget(self.wid_tusts, 0, 1, 2, 1)
        lay_inj.addWidget(self.wid_injctrl, 0, 2, 2, 1)
        lay_inj.addWidget(pbt_bl, 0, 3, alignment=Qt.AlignTop)
        lay_inj.addWidget(pbt_aux, 1, 3, alignment=Qt.AlignBottom)
        lay_inj.addWidget(self.wid_fill, 0, 4, 2, 1)

        # Current
        curr_pvname = SiriusPVName(
            'SI-Glob:AP-CurrInfo:Current-Mon').substitute(prefix=self._prefix)
        self.label_curr = PyDMLabel(self, curr_pvname)
        self.label_curr.showUnits = True
        self.label_curr.setStyleSheet("""
            QLabel{
                font-size: 18pt; qproperty-alignment: AlignCenter;
                min-width: 6em; max-width: 6em;
            }""")
        self.wid_curr = QGroupBox('Current')
        lay_curr = QHBoxLayout(self.wid_curr)
        lay_curr.addWidget(self.label_curr)

        # RF Kill Beam
        self.wid_rfkill = QGroupBox('RF Kill Beam')
        self.wid_rfkill.setObjectName('RFKillBeam')
        rfkill_bt = RFKillBeamButton(self, self._prefix)
        rfkill_lay = QGridLayout(self.wid_rfkill)
        rfkill_lay.addWidget(rfkill_bt)

        # menu buttons
        self.wid_pbt = QPushButton('v', self)
        self.wid_pbt.clicked.connect(self._toggle_show_menubutton)
        self.wid_pbt.setStyleSheet('QPushButton{max-width: 0.8em;}')
        self._menubutton = get_object(ismenubar=False, parent=self)
        self._menubutton.layout().setContentsMargins(0, 0, 0, 0)
        self._menubutton.layout().setSpacing(4)
        self._menubutton.setVisible(False)

        hlay1 = QHBoxLayout()
        hlay1.setContentsMargins(0, 0, 0, 0)
        hlay1.addWidget(self.wid_shift)
        hlay1.addWidget(self.wid_injsys)
        hlay1.addWidget(self.wid_egun)
        hlay1.addWidget(self.wid_inject)
        hlay1.addWidget(self.wid_curr)
        hlay1.addWidget(self.wid_rfkill)

        hlay2 = QHBoxLayout()
        hlay2.setContentsMargins(0, 0, 0, 0)
        hlay2.addWidget(self.wid_injlog)
        hlay2.addWidget(self.wid_mon)

        cwid = QWidget(self)
        lay = QGridLayout(cwid)
        lay.addLayout(hlay1, 0, 0)
        lay.addLayout(hlay2, 1, 0)
        lay.addWidget(self._menubutton, 2, 0, 1, 2)
        lay.addWidget(self.wid_pbt,
                      0,
                      1,
                      2,
                      1,
                      alignment=Qt.AlignRight | Qt.AlignBottom)
        self.setCentralWidget(cwid)

    def _toggle_show_menubutton(self):
        self._menubutton.setVisible(self._menubutton.isHidden())
        text = 'v' if self._menubutton.isHidden() else '^'
        self.sender().setText(text)
        self.centralWidget().adjustSize()
        self.adjustSize()

    def _toggle_show_bucketlist(self):
        show = self.wid_fill.isHidden()
        self.wid_fill.setVisible(show)
        text = '<' if show else '>'
        tooltip = ('Hide' if show else 'Show') + ' bucket list controls.'
        self.sender().setText(text)
        self.sender().setToolTip(tooltip)
        self.sender().parent().adjustSize()
        self.centralWidget().adjustSize()
        self.adjustSize()

    def _toggle_show_injaux(self):
        show = self.wid_mon.isHidden()
        self.wid_mon.setVisible(show)
        self.wid_injlog.setVisible(show)
        text = '^' if show else 'v'
        tooltip = ('Hide'
                   if show else 'Show') + ' Injection Auxiliary section.'
        self.sender().setText(text)
        self.sender().setToolTip(tooltip)
        self.sender().parent().adjustSize()
        self.centralWidget().adjustSize()
        self.adjustSize()

    @Slot(int)
    def _handle_injmode_settings_vis(self, new_mode):
        is_topup = new_mode == _InjConst.InjMode.TopUp
        self.label_injauto.setVisible(not is_topup)
        self.but_injauto.setVisible(not is_topup)
        self.led_injauto.setVisible(not is_topup)
        self.wid_tusts.setVisible(is_topup)
        self.but_tiinj.setVisible(not is_topup)
        self.but_topup.setVisible(is_topup)

    def mouseDoubleClickEvent(self, event):
        """Implement mouseDoubleClickEvent."""
        if event.button() == Qt.LeftButton:
            if self.wid_curr.underMouse():
                self.showStatus.emit()
            elif self.wid_shift.underMouse():
                self.showStatus.emit()
            elif self.wid_egun.underMouse():
                self.showEgun.emit()
            elif self.wid_mon.underMouse():
                self.showMonitor.emit()
        super().mouseDoubleClickEvent(event)

    def changeEvent(self, event):
        """Implement changeEvent."""
        if event.type() == QEvent.FontChange:
            fontsize = self.app.font().pointSize()
            self.label_curr.setStyleSheet(
                'QLabel{'
                '    font-size: ' + str(fontsize + 8) + 'pt;'
                '    qproperty-alignment: AlignCenter;'
                '    min-width: 6em; max-width: 6em;'
                '}')
            self.ensurePolished()
Ejemplo n.º 2
0
class InjCtrlWindow(SiriusMainWindow):
    """InjCtrl Main Window."""

    showMonitor = Signal()
    showStatus = Signal()
    showEgun = Signal()

    def __init__(self, parent=None, prefix=''):
        """Init."""
        super().__init__(parent)
        self._prefix = prefix
        self._inj_dev = SiriusPVName('AS-Glob:AP-InjCtrl')
        self._inj_prefix = self._inj_dev.substitute(prefix=prefix)
        self.setWindowTitle('Injection Controls')
        self.setObjectName('ASApp')
        self.setWindowIcon(
            qta.icon('fa5s.syringe', color=get_appropriate_color('AS')))

        self._setupUi()

        self.setFocus(True)
        self.setFocusPolicy(Qt.StrongFocus)

    def _setupUi(self):
        self.title = QLabel('<h3>Injection Control<h3>',
                            self,
                            alignment=Qt.AlignCenter)
        self.title.setStyleSheet('QLabel{max-height:1.6em;}')

        self.wid_comm = self._setupMainBarWidget()
        self.wid_comm.setSizePolicy(QSzPlcy.Preferred, QSzPlcy.Fixed)

        self.wid_sett = self._setupSettingsWidget()
        self.wid_sett.setSizePolicy(QSzPlcy.Preferred,
                                    QSzPlcy.MinimumExpanding)

        self.wid_mon = self._setupMonitorWidget()
        self.wid_log = self._setupLogWidget()
        wid_row = QWidget()
        wid_row.setSizePolicy(QSzPlcy.Preferred, QSzPlcy.Fixed)
        hbox_row = QHBoxLayout(wid_row)
        hbox_row.setContentsMargins(0, 0, 0, 0)
        hbox_row.setStretch(0, 3)
        hbox_row.setStretch(1, 5)
        hbox_row.addWidget(self.wid_mon)
        hbox_row.addWidget(self.wid_log)

        wid = QWidget(self)
        lay = QVBoxLayout(wid)
        lay.addWidget(self.title)
        lay.addWidget(self.wid_comm)
        lay.addWidget(self.wid_comm)
        lay.addWidget(self.wid_sett)
        lay.addWidget(wid_row)
        lay.setStretch(1, 1)
        lay.setStretch(2, 3)
        lay.setStretch(3, 2)
        self.setCentralWidget(wid)

        self._ch_injmode = SiriusConnectionSignal(
            self._inj_prefix.substitute(propty='Mode-Sel'))
        self._ch_injmode.new_value_signal[int].connect(
            self._handle_injmode_settings_vis)

        # connect window signals
        connect_newprocess(self,
                           'sirius-hla-as-ap-monitor.py',
                           parent=self,
                           signal=self.showMonitor)
        connect_newprocess(self,
                           'sirius-hla-si-ap-genstatus.py',
                           parent=self,
                           signal=self.showStatus)
        connect_newprocess(self,
                           'sirius-hla-li-eg-control.py',
                           parent=self,
                           signal=self.showEgun)

    def _setupMainBarWidget(self):
        # Shift
        machshift_pvname = SiriusPVName(
            'AS-Glob:AP-MachShift:Mode-Sel').substitute(prefix=self._prefix)
        self._cb_shift = SiriusEnumComboBox(self, machshift_pvname)
        self._lb_shift = MachShiftLabel(self, prefix=self._prefix)
        self._lb_shift.setStyleSheet(
            'QLabel{max-height: 2em; min-width: 7em;}')
        self.wid_shift = QGroupBox('Mach.Shift', self)
        lay_shift = QVBoxLayout(self.wid_shift)
        lay_shift.addWidget(self._cb_shift)
        lay_shift.addWidget(self._lb_shift)

        # Injection System
        self.wid_is_summ = InjSysStbyControlWidget(self, is_summary=True)
        self.wid_injsys = QGroupBox('Inj.System', self)
        lay_injsys = QGridLayout(self.wid_injsys)
        lay_injsys.setContentsMargins(0, 0, 0, 0)
        lay_injsys.addWidget(self.wid_is_summ, 0, 0)
        # self.wid_is_full = InjSysStbyControlWidget(self, is_summary=False)
        # self.wid_is_full.setVisible(False)
        # lay_injsys.addWidget(self.wid_is_full, 0, 0)
        # self._icon_expd = qta.icon('fa5s.plus')
        # self._icon_comp = qta.icon('fa5s.minus')
        # self.bt_is_tgl = QPushButton(self._icon_expd, '', self)
        # self.bt_is_tgl.clicked.connect(self._handle_injsys_details_vis)
        # self.bt_is_tgl.setObjectName('bt')
        # self.bt_is_tgl.setStyleSheet("""
        #     #bt{
        #         min-width: 0.8em; max-width: 0.8em;
        #         min-height: 0.8em; max-height: 0.8em;
        #         icon-size:12px;}
        # """)
        # lay_injsys.addWidget(
        #     self.bt_is_tgl, 0, 1, alignment=Qt.AlignRight | Qt.AlignBottom)

        # EGun
        egun_dev = SiriusPVName('LI-01:EG-TriggerPS').substitute(
            prefix=self._prefix)
        self._sb_eguntrg = PyDMStateButton(
            self, egun_dev.substitute(propty_name='enable'))
        self._led_eguntrg = SiriusLedState(
            self, egun_dev.substitute(propty_name='enablereal'))
        self._led_eguntrg.setStyleSheet(
            'QLed{min-width: 1.29em; max-width: 1.29em;}')
        self.wid_egun = self._create_groupwidget('EGun Trig.', [
            self._sb_eguntrg,
        ], [
            self._led_eguntrg,
        ])

        # Injection
        self._pb_tiinj = EVGInjectionButton(self, self._prefix)
        self._pb_topup = PyDMStateButton(
            self,
            init_channel=self._inj_prefix.substitute(propty='TopUpState-Sel'))
        self._pb_topup.setVisible(False)
        self._led_injti = EVGInjectionLed(self, self._prefix)
        self._lb_injcnt = PyDMLabel(self)
        self._lb_injcnt.setToolTip(
            'Count injection pulses when Egun Trigger is enabled.')
        ch_injcnt = SiriusPVName(
            'AS-Glob:AP-CurrInfo:InjCount-Mon').substitute(prefix=self._prefix)
        self._lb_injcnt.channel = ch_injcnt
        self._lb_injcnt.setStyleSheet('QLabel{max-width: 3.5em;}')
        hbox_injsts = QHBoxLayout()
        hbox_injsts.setContentsMargins(0, 0, 0, 0)
        hbox_injsts.addWidget(self._led_injti)
        hbox_injsts.addWidget(self._lb_injcnt)
        self.wid_inj = QGroupBox('Injection', self)
        lay_inj = QGridLayout(self.wid_inj)
        lay_inj.setAlignment(Qt.AlignCenter)
        lay_inj.addWidget(self._pb_tiinj, 0, 0)
        lay_inj.addWidget(self._pb_topup, 0, 0)
        lay_inj.addLayout(hbox_injsts, 1, 0)

        # Current
        curr_pvname = SiriusPVName(
            'SI-Glob:AP-CurrInfo:Current-Mon').substitute(prefix=self._prefix)
        self._lb_curr = PyDMLabel(self, curr_pvname)
        self._lb_curr.showUnits = True
        self._lb_curr.setStyleSheet("""
            QLabel{
                font-size: 18pt; qproperty-alignment: AlignCenter;
                min-width: 5.5em; max-width: 5.5em;
        }""")
        self.wid_curr = QGroupBox('Current', self)
        lay_curr = QHBoxLayout(self.wid_curr)
        lay_curr.addWidget(self._lb_curr)

        # TopUp status
        self._lb_tusts = PyDMLabel(
            self, self._inj_prefix.substitute(propty='TopUpState-Sts'))
        self._lb_tusts.setAlignment(Qt.AlignCenter)
        self._lb_tusts.setStyleSheet('QLabel{max-height:2em;}')
        self._ld_tunow = QLabel('Now:',
                                self,
                                alignment=Qt.AlignRight | Qt.AlignVCenter)
        self._lb_tunow = ClockLabel(self)
        self._lb_tunow.setStyleSheet('QLabel{max-height:2em;}')
        self._ld_tunxt = QLabel('Next:',
                                self,
                                alignment=Qt.AlignRight | Qt.AlignVCenter)
        self._lb_tunxt = SiriusLabel(
            self, self._inj_prefix.substitute(propty='TopUpNextInj-Mon'))
        self._lb_tunxt.displayFormat = SiriusLabel.DisplayFormat.Time
        self._lb_tunxt.setAlignment(Qt.AlignCenter)
        self._lb_tunxt.setStyleSheet('QLabel{max-height:2em;}')
        self._pb_round = PyDMPushButton(
            self,
            label='',
            icon=qta.icon('mdi.tilde'),
            pressValue=1,
            init_channel=self._inj_prefix.substitute(
                propty='TopUpNextInjRound-Cmd'))
        self._pb_round.setObjectName('but')
        self._pb_round.setStyleSheet(
            '#but{min-width:18px; max-width:18px; icon-size:16px;}')
        self.wid_tusts = QGroupBox('Top-up status')
        self.wid_tusts.setVisible(False)
        lay_tusts = QGridLayout(self.wid_tusts)
        lay_tusts.addWidget(self._lb_tusts, 0, 0, 1, 2)
        lay_tusts.addWidget(self._ld_tunow, 1, 0)
        lay_tusts.addWidget(self._lb_tunow, 1, 1)
        lay_tusts.addWidget(self._ld_tunxt, 2, 0)
        lay_tusts.addWidget(self._lb_tunxt, 2, 1)
        lay_tusts.addWidget(self._pb_round, 2, 2)

        wid = QWidget()
        lay = QGridLayout(wid)
        lay.setContentsMargins(0, 0, 0, 0)
        lay.addWidget(self.wid_shift, 0, 0)
        lay.addWidget(self.wid_injsys, 0, 1)
        lay.addWidget(self.wid_egun, 0, 2)
        lay.addWidget(self.wid_inj, 0, 3)
        lay.addWidget(self.wid_tusts, 0, 4)
        lay.addWidget(self.wid_curr, 0, 5)
        lay.setColumnStretch(0, 3)
        lay.setColumnStretch(1, 2)
        lay.setColumnStretch(2, 2)
        lay.setColumnStretch(3, 2)
        lay.setColumnStretch(4, 4)
        lay.setColumnStretch(5, 3)
        wid.setStyleSheet('.QLabel{min-height: 1em; max-height: 1em;}')
        return wid

    def _setupSettingsWidget(self):
        # group of labels to set the same stylesheet
        labelsdesc, labelsmon = list(), list()

        # Mode
        self._ld_injmode = QLabel('Mode', self)
        labelsdesc.append(self._ld_injmode)
        self._cb_injmode = SiriusEnumComboBox(
            self, self._inj_prefix.substitute(propty='Mode-Sel'))
        self._lb_injmode = PyDMLabel(
            self, self._inj_prefix.substitute(propty='Mode-Sts'))
        self._lb_injmode.showUnits = True
        labelsmon.append(self._lb_injmode)

        # Target current
        self._ld_currtgt = QLabel('Target Curr.', self)
        labelsdesc.append(self._ld_currtgt)
        self._sb_currtgt = SiriusSpinbox(
            self, self._inj_prefix.substitute(propty='TargetCurrent-SP'))
        self._sb_currtgt.showStepExponent = False
        self._lb_currtgt = PyDMLabel(
            self, self._inj_prefix.substitute(propty='TargetCurrent-RB'))
        self._lb_currtgt.showUnits = True
        labelsmon.append(self._lb_currtgt)

        # mode specific configurations
        self.wid_dcdtls = self._setupDecayModeWidget()
        self.wid_tudtls = self._setupTopUpModeWidget()
        self.wid_tudtls.setVisible(False)

        # Mon
        self._ld_injset = QLabel('Setup ok', self)
        labelsdesc.append(self._ld_injset)
        self._led_injset = InjDiagLed(self)

        # Type
        self._ld_injtype = QLabel('Type', self)
        labelsdesc.append(self._ld_injtype)
        self._cb_injtype = SiriusEnumComboBox(
            self, self._inj_prefix.substitute(propty='Type-Sel'))
        self._lb_injtype = PyDMLabel(
            self, self._inj_prefix.substitute(propty='Type-Sts'))
        labelsmon.append(self._lb_injtype)
        self._lb_injtype_mon = PyDMLabel(
            self, self._inj_prefix.substitute(propty='Type-Mon'))
        labelsmon.append(self._lb_injtype_mon)
        self._ch_injtype = SiriusConnectionSignal(
            self._inj_prefix.substitute(propty='Type-Sel'))
        self._ch_injtype.new_value_signal[int].connect(
            self._handle_injtype_settings_vis)

        # Single bunch bias voltage
        self._ld_sbbias = QLabel('SB Bias Voltage', self)
        labelsdesc.append(self._ld_sbbias)
        self._sb_sbbias = SiriusSpinbox(
            self, self._inj_prefix.substitute(propty='SglBunBiasVolt-SP'))
        self._sb_sbbias.showStepExponent = False
        self._lb_sbbias = PyDMLabel(
            self, self._inj_prefix.substitute(propty='SglBunBiasVolt-RB'))
        self._lb_sbbias.showUnits = True
        labelsmon.append(self._lb_sbbias)
        self._ld_sbbias.setVisible(False)
        self._sb_sbbias.setVisible(False)
        self._lb_sbbias.setVisible(False)

        # Multi bunch bias voltage
        self._ld_mbbias = QLabel('MB Bias Volt.', self)
        labelsdesc.append(self._ld_mbbias)
        self._sb_mbbias = SiriusSpinbox(
            self, self._inj_prefix.substitute(propty='MultBunBiasVolt-SP'))
        self._sb_mbbias.showStepExponent = False
        self._lb_mbbias = PyDMLabel(
            self, self._inj_prefix.substitute(propty='MultBunBiasVolt-RB'))
        self._lb_mbbias.showUnits = True
        labelsmon.append(self._lb_mbbias)

        # bias voltage mon
        ch_bias_mon = SiriusPVName('LI-01:EG-BiasPS').substitute(
            prefix=self._prefix, propty_name='voltinsoft')
        self._lb_bias_mon = PyDMLabel(self, ch_bias_mon)
        self._lb_bias_mon.showUnits = True
        labelsmon.append(self._lb_bias_mon)

        # Filament current op value
        self._ld_filaopcurr = QLabel('Fila.Op. Curr.', self)
        labelsdesc.append(self._ld_filaopcurr)
        self._sb_filaopcurr = SiriusSpinbox(
            self, self._inj_prefix.substitute(propty='FilaOpCurr-SP'))
        self._sb_filaopcurr.showStepExponent = False
        self._lb_filaopcurr = PyDMLabel(
            self, self._inj_prefix.substitute(propty='FilaOpCurr-RB'))
        self._lb_filaopcurr.showUnits = True
        labelsmon.append(self._lb_filaopcurr)
        ch_filacurr_mon = SiriusPVName('LI-01:EG-FilaPS').substitute(
            prefix=self._prefix, propty_name='currentinsoft')
        self._lb_filaopcurr_mon = PyDMLabel(self, ch_filacurr_mon)
        self._lb_filaopcurr_mon.showUnits = True
        labelsmon.append(self._lb_filaopcurr_mon)

        # High voltage op value
        self._ld_hvopvolt = QLabel('HV.Op. Volt.', self)
        labelsdesc.append(self._ld_hvopvolt)
        self._sb_hvopvolt = SiriusSpinbox(
            self, self._inj_prefix.substitute(propty='HVOpVolt-SP'))
        self._sb_hvopvolt.showStepExponent = False
        self._lb_hvopvolt = PyDMLabel(
            self, self._inj_prefix.substitute(propty='HVOpVolt-RB'))
        self._lb_hvopvolt.showUnits = True
        labelsmon.append(self._lb_hvopvolt)
        ch_hvvolt_mon = SiriusPVName('LI-01:EG-HVPS').substitute(
            prefix=self._prefix, propty_name='voltinsoft')
        self._lb_hvopvolt_mon = PyDMLabel(self, ch_hvvolt_mon)
        self._lb_hvopvolt_mon.showUnits = True
        labelsmon.append(self._lb_hvopvolt_mon)

        # header
        ld_sp = QLabel('<h4>SP</h4>', self, alignment=Qt.AlignCenter)
        ld_rb = QLabel('<h4>RB</h4>', self, alignment=Qt.AlignCenter)
        ld_mon = QLabel('<h4>Mon</h4>', self, alignment=Qt.AlignCenter)

        # Bucket list
        self._wid_bl = BucketList(self,
                                  prefix=self._prefix,
                                  min_size=15,
                                  show_graph=True)
        self._wid_bl.setSizePolicy(QSzPlcy.Preferred, QSzPlcy.MinimumExpanding)

        wid1 = QWidget()
        wid1.setSizePolicy(QSzPlcy.Preferred, QSzPlcy.Fixed)
        glay1 = QGridLayout(wid1)
        glay1.setAlignment(Qt.AlignTop)
        glay1.addWidget(self._ld_injset, 0, 0)
        glay1.addWidget(self._led_injset, 0, 1)
        glay1.addWidget(self._ld_injmode, 1, 0)
        glay1.addWidget(self._cb_injmode, 1, 1)
        glay1.addWidget(self._lb_injmode, 1, 2)
        glay1.addWidget(self._ld_currtgt, 2, 0)
        glay1.addWidget(self._sb_currtgt, 2, 1)
        glay1.addWidget(self._lb_currtgt, 2, 2)
        glay1.addWidget(self.wid_tudtls, 3, 0, 2, 3)
        glay1.addWidget(self.wid_dcdtls, 3, 0, 2, 3)
        glay1.setColumnStretch(0, 3)
        glay1.setColumnStretch(1, 2)
        glay1.setColumnStretch(2, 2)

        wid2 = QWidget()
        wid2.setSizePolicy(QSzPlcy.Preferred, QSzPlcy.Fixed)
        glay2 = QGridLayout(wid2)
        glay2.setAlignment(Qt.AlignTop)
        glay2.addWidget(ld_sp, 0, 1)
        glay2.addWidget(ld_rb, 0, 2)
        glay2.addWidget(ld_mon, 0, 3)
        glay2.addWidget(self._ld_injtype, 1, 0)
        glay2.addWidget(self._cb_injtype, 1, 1)
        glay2.addWidget(self._lb_injtype, 1, 2)
        glay2.addWidget(self._lb_injtype_mon, 1, 3)
        glay2.addWidget(self._ld_sbbias, 2, 0)
        glay2.addWidget(self._sb_sbbias, 2, 1)
        glay2.addWidget(self._lb_sbbias, 2, 2)
        glay2.addWidget(self._ld_mbbias, 2, 0)
        glay2.addWidget(self._sb_mbbias, 2, 1)
        glay2.addWidget(self._lb_mbbias, 2, 2)
        glay2.addWidget(self._lb_bias_mon, 2, 3)
        glay2.addWidget(self._ld_filaopcurr, 4, 0)
        glay2.addWidget(self._sb_filaopcurr, 4, 1)
        glay2.addWidget(self._lb_filaopcurr, 4, 2)
        glay2.addWidget(self._lb_filaopcurr_mon, 4, 3)
        glay2.addWidget(self._ld_hvopvolt, 5, 0)
        glay2.addWidget(self._sb_hvopvolt, 5, 1)
        glay2.addWidget(self._lb_hvopvolt, 5, 2)
        glay2.addWidget(self._lb_hvopvolt_mon, 5, 3)
        glay2.setColumnStretch(0, 3)
        glay2.setColumnStretch(1, 2)
        glay2.setColumnStretch(2, 2)
        glay2.setColumnStretch(3, 2)

        wid = QGroupBox('Settings')
        lay = QGridLayout(wid)
        lay.addWidget(wid1, 0, 0, alignment=Qt.AlignTop)
        lay.addWidget(wid2, 0, 1, alignment=Qt.AlignTop)
        lay.addWidget(self._wid_bl, 1, 0, 1, 2)
        lay.setColumnStretch(0, 3)
        lay.setColumnStretch(1, 4)

        for lbl in labelsdesc:
            lbl.setStyleSheet("""
                QLabel{
                    min-width: 6.5em; max-width: 6.5em; min-height: 1.5em;
                    qproperty-alignment: 'AlignRight | AlignVCenter';
                }""")
        for lbl in labelsmon:
            lbl.setStyleSheet("PyDMLabel{qproperty-alignment: AlignCenter;}")

        return wid

    def _setupTopUpModeWidget(self):
        self._ld_tuperd = QLabel('Period', self)
        self._sb_tuperd = SiriusSpinbox(
            self, self._inj_prefix.substitute(propty='TopUpPeriod-SP'))
        self._sb_tuperd.showStepExponent = False
        self._lb_tuperd = PyDMLabel(
            self, self._inj_prefix.substitute(propty='TopUpPeriod-RB'))
        self._lb_tuperd.showUnits = True

        self._ld_tumaxpu = QLabel('Max.Nr.Pulses', self)
        self._sb_tumaxpu = SiriusSpinbox(
            self, self._inj_prefix.substitute(propty='TopUpMaxNrPulses-SP'))
        self._sb_tumaxpu.showStepExponent = False
        self._lb_tumaxpu = PyDMLabel(
            self, self._inj_prefix.substitute(propty='TopUpMaxNrPulses-RB'))
        self._lb_tumaxpu.showUnits = True

        wid = QWidget()
        lay = QGridLayout(wid)
        lay.setContentsMargins(0, 6, 0, 0)
        lay.setAlignment(Qt.AlignTop)
        lay.addWidget(self._ld_tuperd, 0, 0)
        lay.addWidget(self._sb_tuperd, 0, 1)
        lay.addWidget(self._lb_tuperd, 0, 2)
        lay.addWidget(self._ld_tumaxpu, 1, 0)
        lay.addWidget(self._sb_tumaxpu, 1, 1)
        lay.addWidget(self._lb_tumaxpu, 1, 2)
        lay.setColumnStretch(0, 3)
        lay.setColumnStretch(1, 2)
        lay.setColumnStretch(2, 2)

        wid.setStyleSheet("""
            .QLabel{
                min-width: 6.5em; max-width: 6.5em; min-height: 1.5em;
                qproperty-alignment: 'AlignRight | AlignVCenter';
            }
            PyDMLabel{
                qproperty-alignment: AlignCenter;
            }""")
        return wid

    def _setupDecayModeWidget(self):
        self._ld_autostop = QLabel('Auto Stop', self)
        self._cb_autostop = PyDMStateButton(
            self, self._inj_prefix.substitute(propty='AutoStop-Sel'))
        self._cb_autostop.shape = 1
        self._led_autostop = SiriusLedState(
            self, self._inj_prefix.substitute(propty='AutoStop-Sts'))

        wid = QWidget()
        lay = QGridLayout(wid)
        lay.setAlignment(Qt.AlignTop)
        lay.setContentsMargins(0, 6, 0, 0)
        lay.addWidget(self._ld_autostop, 0, 0)
        lay.addWidget(self._cb_autostop, 0, 1)
        lay.addWidget(self._led_autostop, 0, 2)
        lay.setColumnStretch(0, 3)
        lay.setColumnStretch(1, 2)
        lay.setColumnStretch(2, 2)

        wid.setStyleSheet("""
            .QLabel{
                min-width: 6.5em; max-width: 6.5em; min-height: 1.5em;
                qproperty-alignment: 'AlignRight | AlignVCenter';
            }
            PyDMLabel{
                qproperty-alignment: AlignCenter;
            }""")
        return wid

    def _setupLogWidget(self):
        self._log = PyDMLogLabel(self,
                                 self._inj_prefix.substitute(propty='Log-Mon'),
                                 [
                                     'Remaining time',
                                 ])

        wid = QGroupBox('Log')
        lay = QHBoxLayout(wid)
        lay.addWidget(self._log)
        return wid

    def _setupMonitorWidget(self):
        self.wid_mon = MonitorSummaryWidget(self)

        wid = QWidget(self)
        lay = QGridLayout(wid)
        lay.setContentsMargins(0, 0, 0, 0)
        lay.addWidget(self.wid_mon, 0, 0)
        return wid

    # ---- auxiliary commands ----

    @Slot(int)
    def _handle_injtype_settings_vis(self, new_type):
        is_sb = new_type == _Const.InjType.SingleBunch
        self._ld_sbbias.setVisible(is_sb)
        self._sb_sbbias.setVisible(is_sb)
        self._lb_sbbias.setVisible(is_sb)
        self._ld_mbbias.setVisible(not is_sb)
        self._sb_mbbias.setVisible(not is_sb)
        self._lb_mbbias.setVisible(not is_sb)
        self.centralWidget().adjustSize()
        self.adjustSize()

    @Slot(int)
    def _handle_injmode_settings_vis(self, new_mode):
        is_topoup = new_mode == _Const.InjMode.TopUp
        self.wid_tudtls.setVisible(is_topoup)
        self._pb_topup.setVisible(is_topoup)
        self.wid_dcdtls.setVisible(not is_topoup)
        self._pb_tiinj.setVisible(not is_topoup)
        self.wid_tusts.setVisible(is_topoup)

    def _handle_injsys_details_vis(self):
        exp = self.wid_is_summ.isVisible()
        icon = self._icon_comp if exp else self._icon_expd
        self.sender().setIcon(icon)
        self.wid_is_summ.setVisible(not exp)
        self.wid_is_full.setVisible(exp)
        self.centralWidget().adjustSize()
        self.adjustSize()

    def _create_groupwidget(self, title, sp_wids, rb_wids, aux_wids=None):
        hbox_sp = QHBoxLayout()
        hbox_sp.setAlignment(Qt.AlignCenter)
        hbox_sp.setContentsMargins(0, 0, 0, 0)
        for wid in sp_wids:
            hbox_sp.addWidget(wid)

        hbox_rb = QHBoxLayout()
        hbox_rb.setAlignment(Qt.AlignCenter)
        hbox_rb.setContentsMargins(0, 0, 0, 0)
        for wid in rb_wids:
            hbox_rb.addWidget(wid)

        box = QGroupBox(title, self) if title else QWidget(self)
        lay = QVBoxLayout(box)
        lay.setAlignment(Qt.AlignCenter)
        if not isinstance(box, QGroupBox):
            lay.setContentsMargins(0, 0, 0, 0)
        lay.addLayout(hbox_sp)
        lay.addLayout(hbox_rb)

        if aux_wids:
            hbox_aux = QHBoxLayout()
            hbox_aux.setAlignment(Qt.AlignCenter)
            hbox_aux.setContentsMargins(0, 0, 0, 0)
            for wid in aux_wids:
                hbox_aux.addWidget(wid)
            lay.addLayout(hbox_aux)
        return box

    # ---- events ----

    def mouseDoubleClickEvent(self, event):
        """Implement mouseDoubleClickEvent."""
        if event.button() == Qt.LeftButton:
            if self.wid_curr.underMouse():
                self.showStatus.emit()
            elif self.wid_shift.underMouse():
                self.showStatus.emit()
            elif self.wid_egun.underMouse():
                self.showEgun.emit()
            elif self.wid_mon.underMouse():
                self.showMonitor.emit()
        super().mouseDoubleClickEvent(event)

    def changeEvent(self, event):
        """Implement changeEvent."""
        if event.type() == QEvent.FontChange:
            fontsize = self.app.font().pointSize()
            self._lb_curr.setStyleSheet('QLabel{'
                                        '    font-size: ' + str(fontsize + 8) +
                                        'pt;'
                                        '    qproperty-alignment: AlignCenter;'
                                        '    min-width: 6em; max-width: 6em;'
                                        '}')
            self.ensurePolished()