Beispiel #1
0
 def on_list_itemClicked(self, item):
     self._clearDisplay()
     index = self.list.row(item)
     frm = QFrame(self)
     loadUi(frm, findResource('nicos_mlz/kws1/gui/sampleconf_one.ui'))
     frm.whatLbl.setText('Sample configuration')
     configToFrame(frm, self.configs[index])
     frm.addDevBtn.setVisible(False)
     frm.delDevBtn.setVisible(False)
     frm.readApBtn.setVisible(False)
     frm.readDevsBtn.setVisible(False)
     # frm.posTbl.setEditTriggers(QTableWidget.NoEditTriggers)
     frm.posTbl.setEnabled(False)
     for box in frm.findChildren(QLineEdit):
         # box.setReadOnly(True)
         box.setEnabled(False)
     layout = self.frame.layout()
     layout.addWidget(frm)
Beispiel #2
0
class LokiSamplePanel(LokiPanelBase):
    panelName = 'LoKI sample setup'

    def __init__(self, parent, client, options):
        LokiPanelBase.__init__(self, parent, client, options)
        loadUi(self, findResource('nicos_ess/loki/gui/ui_files/sampleconf.ui'))
        self.sampleGroup.setEnabled(False)
        self.frame.setLayout(QVBoxLayout())

        self.sample_frame = QFrame(self)
        loadUi(
            self.sample_frame,
            findResource('nicos_ess/loki/gui/ui_files/sampleconf_summary.ui'))

        layout = self.frame.layout()
        layout.addWidget(self.sample_frame)
        self.sample_frame.hide()

        self.sample_frame.posTbl.setEnabled(False)

        for box in self.sample_frame.findChildren(QLineEdit):
            box.setEnabled(False)

        menu = QMenu(self)
        menu.addAction(self.actionEmpty)
        menu.addAction(self.actionGenerate)
        self.createBtn.setMenu(menu)

        self.configs = []
        self.holder_info = options.get('holder_info', [])
        self.instrument = options.get('instrument', 'loki')
        self.unapplied_changes = False
        self.applyBtn.setEnabled(False)
        self.initialise_connection_status_listeners()

    def setViewOnly(self, viewonly):
        for control in [
                self.createBtn, self.retrieveBtn, self.openFileBtn,
                self.saveBtn, self.newBtn, self.editBtn, self.delBtn,
                self.frame, self.list
        ]:
            control.setEnabled(not viewonly)
        # Handle apply button separately.
        if viewonly:
            self.unapplied_changes = self.applyBtn.isEnabled()
            self.applyBtn.setEnabled(False)
        # If one toggles view only mode without applying changes, upon exiting
        # view-only mode, following ensures apply button is enabled.
        elif self.unapplied_changes:
            self.applyBtn.setEnabled(True)

    @pyqtSlot()
    def on_actionEmpty_triggered(self):
        self._clear_samples()
        self.sample_frame.hide()
        self.sampleGroup.setEnabled(True)
        self.on_newBtn_clicked()

    @pyqtSlot()
    def on_actionGenerate_triggered(self):
        def read_axes():
            ax1, ax2 = dlg._info[2], dlg._info[4]
            for (ax, box) in [(ax1, dlg.ax1Box), (ax2, dlg.ax2Box)]:
                if not ax:
                    continue
                x = self.client.eval('%s.read()' % ax, None)
                if x is None:
                    QMessageBox.warning(dlg, 'Error', f'Could not read {ax}.')
                    return
                box.setText(f'x:.1f')

        def btn_toggled(checked):
            if checked:
                dlg._info = dlg.sender()._info
                ax1, ax2 = dlg._info[2], dlg._info[4]
                for ax, lbl, box, revbox in [
                    (ax1, dlg.ax1Lbl, dlg.ax1Box, dlg.ax1RevBox),
                    (ax2, dlg.ax2Lbl, dlg.ax2Box, None)
                ]:
                    if ax:
                        lbl.setText(ax)
                        lbl.show()
                        box.show()
                        if revbox:
                            revbox.show()
                            revbox.setText(f'{ax} starts at far end')
                    else:
                        lbl.hide()
                        box.hide()
                        if revbox:
                            revbox.hide()

        if not self.holder_info:
            self.showError('Cannot auto-generate sample list as no sample '
                           'changers are defined')
            return

        dlg = dialogFromUi(
            self,
            findResource('nicos_ess/loki/gui/ui_files/sampleconf_gen.ui'))
        dlg.ax1Box.setValidator(DoubleValidator(self))
        dlg.ax2Box.setValidator(DoubleValidator(self))
        dlg.readBtn.clicked.connect(read_axes)
        n_rows = int(math.ceil(len(self.holder_info) / 2.0))
        row, col = 0, 0
        for name, info in self.holder_info:
            btn = QRadioButton(name, dlg)
            btn._info = info
            btn.toggled.connect(btn_toggled)
            dlg.optionFrame.layout().addWidget(btn, row, col)
            if (row, col) == (0, 0):
                btn.setChecked(True)
            row += 1
            if row == n_rows:
                row = 0
                col += 1
        if dlg.exec_() != QDialog.Accepted:
            return

        self._generate_configs(dlg)

        first_item = None
        for config in self.configs:
            new_item = QListWidgetItem(config['name'], self.list)
            first_item = first_item or new_item
        # select the first item
        self.list.setCurrentItem(first_item)
        self.on_list_itemClicked(first_item)

        self.sampleGroup.setEnabled(True)
        self.applyBtn.setEnabled(True)

    def _generate_configs(self, dlg):
        rows, levels, ax1, dax1, ax2, dax2 = dlg._info
        sax1 = float(dlg.ax1Box.text()) if ax1 else 0
        sax2 = float(dlg.ax2Box.text()) if ax2 else 0
        if dlg.ax1RevBox.isChecked():
            dax1 = -dax1

        self._clear_samples()
        n = 0
        for i in range(levels):
            for j in range(rows):
                n += 1
                position = {}
                if ax1:
                    position[ax1] = round(sax1 + j * dax1, 1)
                if ax2:
                    position[ax2] = round(sax2 + i * dax2, 1)
                config = dict(
                    name=str(n),
                    comment='',
                    detoffset=-335.0,
                    thickness=1.0,
                    aperture=(0, 0, 10, 10),
                    position=position,
                )
                self.configs.append(config)

    def _clear_samples(self):
        self.list.clear()
        self.configs.clear()

    @pyqtSlot()
    def on_retrieveBtn_clicked(self):
        sampleconf = self.client.eval('Exp.sample.samples', [])
        sampleconf = sorted(sampleconf.items())
        self.configs = [dict(c[1]) for c in sampleconf if 'thickness' in c[1]]
        # convert read-only dict to normal dict
        for config in self.configs:
            config['position'] = dict(config['position'].items())
        self.list.clear()
        last_item = None
        for config in self.configs:
            last_item = QListWidgetItem(config['name'], self.list)
        # select the last item
        if last_item:
            self.list.setCurrentItem(last_item)

        self.sampleGroup.setEnabled(True)
        self.applyBtn.setEnabled(False)

    @pyqtSlot()
    def on_openFileBtn_clicked(self):
        initial_dir = self.client.eval('session.experiment.scriptpath', '')
        filename = QFileDialog.getOpenFileName(self, 'Open sample file',
                                               initial_dir,
                                               'Sample files (*.py)')[0]
        if not filename:
            return
        try:
            self.configs = parse_sampleconf(filename)
        except Exception as err:
            self.showError(f'Could not read file: {err}\n\n'
                           'Are you sure this is a sample file?')
        else:
            self.list.clear()
            self.sampleGroup.setEnabled(True)
            new_item = None
            for config in self.configs:
                new_item = QListWidgetItem(config['name'], self.list)
            # select the last item
            if new_item:
                self.list.setCurrentItem(new_item)
            self.on_list_itemClicked(new_item)
            self.applyBtn.setEnabled(True)

    @pyqtSlot()
    def on_applyBtn_clicked(self):
        script = self._generate_script()
        self.client.run(script)
        self.showInfo('Sample info has been transferred to the daemon.')

        self.applyBtn.setEnabled(False)

    @pyqtSlot()
    def on_saveBtn_clicked(self):
        initial_dir = self.client.eval('session.experiment.scriptpath', '')
        filename = QFileDialog.getSaveFileName(self, 'Save sample file',
                                               initial_dir,
                                               'Sample files (*.py)')[0]
        if not filename:
            return False
        if not filename.endswith('.py'):
            filename += '.py'
        try:
            self._save_script(filename, self._generate_script())
        except Exception as err:
            self.showError(f'Could not write file: {err}')

    def on_list_currentItemChanged(self, item):
        self.on_list_itemClicked(item)

    def on_list_itemClicked(self, item):
        if not item:
            return
        if self.sample_frame.isHidden():
            self.sample_frame.show()
        index = self.list.row(item)
        configToFrame(self.sample_frame, self.configs[index])

    def on_list_itemDoubleClicked(self):
        self.on_editBtn_clicked()

    @pyqtSlot()
    def on_newBtn_clicked(self):
        dlg = ConfigEditDialog(self, self.client, self.instrument,
                               self.configs)
        if not dlg.exec_():
            return
        self.applyBtn.setEnabled(True)
        config = configFromFrame(dlg.frm)
        self.configs.append(config)
        new_item = QListWidgetItem(config['name'], self.list)
        self.list.setCurrentItem(new_item)

    @pyqtSlot()
    def on_editBtn_clicked(self):
        index = self.list.currentRow()
        if index < 0:
            return
        dlg = ConfigEditDialog(
            self, self.client, self.instrument,
            [config for (i, config) in enumerate(self.configs) if i != index],
            self.configs[index])
        if not dlg.exec_():
            return
        self.applyBtn.setEnabled(True)
        config = configFromFrame(dlg.frm)
        self.configs[index] = config
        list_item = self.list.item(index)
        list_item.setText(config['name'])
        self.on_list_itemClicked(list_item)

    @pyqtSlot()
    def on_delBtn_clicked(self):
        index = self.list.currentRow()
        if index < 0:
            return
        self.applyBtn.setEnabled(True)
        self.list.takeItem(index)
        del self.configs[index]
        if self.list.currentRow() != -1:
            self.on_list_itemClicked(self.list.item(self.list.currentRow()))
        else:
            self.sample_frame.hide()

    def _generate_script(self):
        script = [
            f'# LoKI sample file for NICOS\n',
            f'# Written: {time.asctime()}\n\n', f'ClearSamples()\n'
        ]
        for (i, config) in enumerate(self.configs, start=1):
            script.append(f"SetSample({i}, {repr(config['name'])}, ")
            for key in SAMPLE_KEYS:
                script.append(f"{key}={repr(config[key])}")
                script.append(', ')
            del script[-1]  # remove last comma
            script.append(')\n')
        return ''.join(script)

    @staticmethod
    def _save_script(filename, script):
        with open(filename, 'w') as fp:
            fp.writelines(script)