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)
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)