class ImportAsWidget(QWidget): def __init__(self, parent, sourceWidget: QLineEdit): super().__init__(parent) self.sourceWidget = sourceWidget self.shouldImport = QCheckBox(_("Import As")) self.shouldImport.setCheckState(Qt.Checked) self.shouldImport.stateChanged.connect(self.activateName) self.nameEdit = ImportNameEdit(self) sourceWidget.textChanged.connect(self.syncText) self.layout = QHBoxLayout(self) self.layout.addWidget(self.shouldImport) self.layout.addWidget(self.nameEdit) self.layout.setContentsMargins(0, 0, 0, 0) # https://forum.qt.io/topic/87226/synchronize-2-qlineedit def syncText(self, name): if self.shouldImport.isChecked() and self.nameEdit.synced: self.nameEdit.setText(name) def activateName(self, state): if state: self.nameEdit.setReadOnly(False) self.nameEdit.setEnabled(True) else: self.nameEdit.setReadOnly(True) self.nameEdit.setEnabled(False)
class DxfOutputDialog(OutputDialog): """Dialog for DXF format.""" format_name = "DXF" format_icon = "dxf.png" assembly_description = "The sketch of the parts will include in the file." frame_description = "There is only wire frame will be generated." def __init__(self, *args): """Type name: "DXF module".""" super(DxfOutputDialog, self).__init__(*args) # DXF version option version_label = QLabel("DXF version:", self) self.version_option = QComboBox(self) self.version_option.addItems( sorted((f"{name} - {DXF_VERSIONS_MAP[name]}" for name in DXF_VERSIONS), key=lambda v: v.split()[-1])) self.version_option.setCurrentIndex(self.version_option.count() - 1) self.version_option.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) layout = QHBoxLayout() layout.addWidget(version_label) layout.addWidget(self.version_option) self.main_layout.insertLayout(3, layout) # Parts interval self.use_interval = QCheckBox("Parts interval:", self) self.use_interval.setCheckState(Qt.Checked) self.use_interval.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred) self.interval_option = QDoubleSpinBox(self) self.interval_option.setValue(10) self.use_interval.stateChanged.connect(self.interval_option.setEnabled) layout = QHBoxLayout() layout.addWidget(self.use_interval) layout.addWidget(self.interval_option) layout.addItem( QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Preferred)) self.assembly_layout.insertLayout(2, layout) def do(self, dir_str: QDir) -> bool: """Output types: + Boundary + Frame """ file_name = dir_str.filePath(_get_name(self.filename_edit) + '.dxf') if isfile(file_name) and self.warn_radio.isChecked(): self.exist_warning(file_name) return False version = self.version_option.currentText().split()[0] if self.frame_radio.isChecked(): # Frame dxf_frame(self.vpoints, self.v_to_slvs, version, file_name) elif self.assembly_radio.isChecked(): # Boundary dxf_boundary( self.vpoints, self.link_radius.value(), self.interval_option.value() if self.use_interval.isChecked() else 0., version, file_name) return True
def __init__(self, theme='dark', emphasized=False): super().__init__(None) self.setProperty('emphasized', emphasized) self.setStyleSheet(template(raw_stylesheet, **palettes[theme])) lay = QVBoxLayout() self.setLayout(lay) lay.addWidget(QPushButton('push button')) box = QComboBox() box.addItems(['a', 'b', 'c', 'cd']) lay.addWidget(box) lay.addWidget(QFontComboBox()) hbox = QHBoxLayout() chk = QCheckBox('tristate') chk.setToolTip('I am a tooltip') chk.setTristate(True) chk.setCheckState(Qt.PartiallyChecked) chk3 = QCheckBox('checked') chk3.setChecked(True) hbox.addWidget(QCheckBox('unchecked')) hbox.addWidget(chk) hbox.addWidget(chk3) lay.addLayout(hbox) lay.addWidget(TabDemo(emphasized=emphasized)) sld = QSlider(Qt.Horizontal) sld.setValue(50) lay.addWidget(sld) scroll = QScrollBar(Qt.Horizontal) scroll.setValue(50) lay.addWidget(scroll) lay.addWidget(QHRangeSlider(parent=self)) text = QTextEdit() text.setMaximumHeight(100) text.setHtml(blurb) lay.addWidget(text) lay.addWidget(QTimeEdit()) edit = QLineEdit() edit.setPlaceholderText('LineEdit placeholder...') lay.addWidget(edit) lay.addWidget(QLabel('label')) prog = QProgressBar() prog.setValue(50) lay.addWidget(prog) groupBox = QGroupBox("Exclusive Radio Buttons") radio1 = QRadioButton("&Radio button 1") radio2 = QRadioButton("R&adio button 2") radio3 = QRadioButton("Ra&dio button 3") radio1.setChecked(True) hbox = QHBoxLayout() hbox.addWidget(radio1) hbox.addWidget(radio2) hbox.addWidget(radio3) hbox.addStretch(1) groupBox.setLayout(hbox) lay.addWidget(groupBox)
def add_new_row(self, _metadata, row=0): self.main_window.postprocessing_ui.table.insertRow(row) _layout = QHBoxLayout() _widget = QCheckBox() _widget.setEnabled(True) _layout.addWidget(_widget) _layout.addStretch() _new_widget = QWidget() _new_widget.setLayout(_layout) _widget.stateChanged.connect(lambda state=0, row=row: self.parent.table_select_state_changed(state, row)) self.main_window_postprocessing_ui.table.setCellWidget(row, 0, _new_widget) _item = QTableWidgetItem(_metadata['name']) self.main_window_postprocessing_ui.table.setItem(row, 1, _item) _item = QTableWidgetItem(_metadata['runs']) self.main_window_postprocessing_ui.table.setItem(row, 2, _item) if not _metadata['sample_formula']: _item = QTableWidgetItem(_metadata['sample_formula']) self.main_window_postprocessing_ui.table.setItem(row, 3, _item) if not _metadata['mass_density']: _item = QTableWidgetItem(_metadata['mass_density']) self.main_window_postprocessing_ui.table.setItem(row, 4, _item) if not _metadata['radius']: _item = QTableWidgetItem(_metadata['radius']) self.main_window_postprocessing_ui.table.setItem(row, 5, _item) if not _metadata['packing_fraction']: _item = QTableWidgetItem(_metadata['packing_fraction']) self.main_window_postprocessing_ui.table.setItem(row, 6, _item) _widget = QComboBox() _widget.addItem("cylindrical") _widget.addItem("spherical") if _metadata['sample_shape'] == 'spherical': _widget.setCurrentIndex(1) self.main_window_postprocessing_ui.table.setCellWidget(row, 7, _widget) _layout = QHBoxLayout() _widget = QCheckBox() if _metadata['do_abs_correction'] == 'go': _widget.setCheckState(Qt.Checked) _widget.setStyleSheet("border: 2px; solid-black") _widget.setEnabled(True) _layout.addStretch() _layout.addWidget(_widget) _layout.addStretch() _new_widget = QWidget() _new_widget.setLayout(_layout) self.main_window_postprocessing_ui.table.setCellWidget(row, 8, _new_widget)
def add_new_row(self, _metadata, row=0): self.parent.ui.table.insertRow(row) _layout = QHBoxLayout() _widget = QCheckBox() _widget.setEnabled(True) _layout.addWidget(_widget) _layout.addStretch() _new_widget = QWidget() _new_widget.setLayout(_layout) _widget.stateChanged.connect(lambda state=0, row=row: self.parent. table_select_state_changed(state, row)) self.parent.ui.table.setCellWidget(row, 0, _new_widget) _item = QTableWidgetItem(_metadata['name']) self.parent.ui.table.setItem(row, 1, _item) _item = QTableWidgetItem(_metadata['runs']) self.parent.ui.table.setItem(row, 2, _item) if not _metadata['sample_formula']: _item = QTableWidgetItem(_metadata['sample_formula']) self.parent.ui.table.setItem(row, 3, _item) if not _metadata['mass_density']: _item = QTableWidgetItem(_metadata['mass_density']) self.parent.ui.table.setItem(row, 4, _item) if not _metadata['radius']: _item = QTableWidgetItem(_metadata['radius']) self.parent.ui.table.setItem(row, 5, _item) if not _metadata['packing_fraction']: _item = QTableWidgetItem(_metadata['packing_fraction']) self.parent.ui.table.setItem(row, 6, _item) _widget = QComboBox() _widget.addItem("cylindrical") _widget.addItem("spherical") if _metadata['sample_shape'] == 'spherical': _widget.setCurrentIndex(1) self.parent.ui.table.setCellWidget(row, 7, _widget) _layout = QHBoxLayout() _widget = QCheckBox() if _metadata['do_abs_correction'] == 'go': _widget.setCheckState(Qt.Checked) _widget.setStyleSheet("border: 2px; solid-black") _widget.setEnabled(True) _layout.addStretch() _layout.addWidget(_widget) _layout.addStretch() _new_widget = QWidget() _new_widget.setLayout(_layout) self.parent.ui.table.setCellWidget(row, 8, _new_widget)
class EFMtoolDialog(QDialog): """A dialog to set up EFM calculation""" def __init__(self, appdata: CnaData, centralwidget): QDialog.__init__(self) self.setWindowTitle("Elementary Flux Mode Computation") self.appdata = appdata self.centralwidget = centralwidget self.layout = QVBoxLayout() l1 = QHBoxLayout() self.constraints = QCheckBox("consider 0 in current scenario as off") self.constraints.setCheckState(Qt.Checked) l1.addWidget(self.constraints) self.layout.addItem(l1) lx = QHBoxLayout() self.button = QPushButton("Compute") self.cancel = QPushButton("Close") lx.addWidget(self.button) lx.addWidget(self.cancel) self.layout.addItem(lx) self.setLayout(self.layout) # Connecting the signal self.cancel.clicked.connect(self.reject) self.button.clicked.connect(self.compute) def compute(self): self.setCursor(Qt.BusyCursor) (ems, scenario) = cnapy.core.efm_computation( self.appdata.project.cobra_py_model, self.appdata.project.scen_values, self.constraints.checkState() == Qt.Checked) self.setCursor(Qt.ArrowCursor) if ems is None: QMessageBox.information(self, 'No modes', 'An error occured and modes have not been calculated.') else: if len(ems) == 0: QMessageBox.information(self, 'No modes', 'No elementary modes exist.') else: print(scenario) self.appdata.project.modes = ems self.centralwidget.mode_navigator.current = 0 self.centralwidget.mode_navigator.scenario = scenario self.centralwidget.mode_navigator.title.setText( "Mode Navigation") self.centralwidget.update_mode()
def createTopLeftGroupBox(self): self.topLeftGroupBox = QGroupBox("Group 1") radioButton1 = QRadioButton("Radio button 1") radioButton2 = QRadioButton("Radio button 2") radioButton3 = QRadioButton("Radio button 3") radioButton1.setChecked(True) checkBox = QCheckBox("Tri-state check box") checkBox.setTristate(True) checkBox.setCheckState(Qt.PartiallyChecked) layout = QVBoxLayout() layout.addWidget(radioButton1) layout.addWidget(radioButton2) layout.addWidget(radioButton3) layout.addWidget(checkBox) layout.addStretch(1) self.topLeftGroupBox.setLayout(layout)
class ImportNamesDialog(QDialog): def __init__(self, parent=None): QDialog.__init__( self, parent, flags=Qt.WindowSystemMenuHint | Qt.WindowTitleHint) self.setWindowTitle('Import Names') self.treeview = parent self.setAttribute(Qt.WA_DeleteOnClose) self.importSelected = QCheckBox(_("Import selected"), self) self.importSelected.setCheckState(Qt.Checked) self.importChildren = QCheckBox(_("Import children"), self) self.importChildren.setCheckState(Qt.Checked) self.replaceExisting = QCheckBox(_("Replace existing names"), self) self.replaceExisting.setCheckState(Qt.Checked) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons( QDialogButtonBox.Cancel|QDialogButtonBox.Ok) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) mainLayout = QGridLayout(self) mainLayout.addWidget(self.importSelected) mainLayout.addWidget(self.importChildren) mainLayout.addWidget(self.replaceExisting) mainLayout.addWidget(self.buttonBox) self.setLayout(mainLayout) def accept(self) -> None: reply = { 'accepted': True, 'import_selected': self.importSelected.isChecked(), 'import_children': self.importChildren.isChecked(), 'replace_existing': self.replaceExisting.isChecked() } self.treeview.reply = reply super().accept() def reject(self) -> None: self.treeview.reply = {'accepted': False} super().reject()
class EFMDialog(QDialog): """A dialog to set up EFM calculation""" def __init__(self, appdata: CnaData, centralwidget): QDialog.__init__(self) self.setWindowTitle("Elementary Flux Mode Computation") self.appdata = appdata self.centralwidget = centralwidget self.eng = appdata.engine self.out = io.StringIO() self.err = io.StringIO() self.layout = QVBoxLayout() l1 = QHBoxLayout() self.constraints = QCheckBox("consider 0 in current scenario as off") self.constraints.setCheckState(Qt.Checked) l1.addWidget(self.constraints) self.layout.addItem(l1) l2 = QHBoxLayout() self.flux_bounds = QGroupBox( "use flux bounds to calculate elementary flux vectors") self.flux_bounds.setCheckable(True) self.flux_bounds.setChecked(False) vbox = QVBoxLayout() label = QLabel("Threshold for bounds to be unconstrained") vbox.addWidget(label) self.threshold = QLineEdit("100") validator = QIntValidator() validator.setBottom(0) self.threshold.setValidator(validator) vbox.addWidget(self.threshold) self.flux_bounds.setLayout(vbox) l2.addWidget(self.flux_bounds) self.layout.addItem(l2) l3 = QHBoxLayout() self.check_reversibility = QCheckBox("check reversibility") self.check_reversibility.setCheckState(Qt.Checked) l3.addWidget(self.check_reversibility) self.layout.addItem(l3) l4 = QHBoxLayout() self.convex_basis = QCheckBox("only convex basis") l4.addWidget(self.convex_basis) self.layout.addItem(l4) l5 = QHBoxLayout() self.isozymes = QCheckBox("consider isozymes only once") l5.addWidget(self.isozymes) self.layout.addItem(l5) # TODO: choose solver l7 = QHBoxLayout() self.rational_numbers = QCheckBox("use rational numbers") l7.addWidget(self.rational_numbers) self.layout.addItem(l7) lx = QHBoxLayout() self.button = QPushButton("Compute") self.cancel = QPushButton("Close") lx.addWidget(self.button) lx.addWidget(self.cancel) self.layout.addItem(lx) self.setLayout(self.layout) # Connecting the signal self.cancel.clicked.connect(self.reject) self.button.clicked.connect(self.compute) def compute(self): # create CobraModel for matlab self.appdata.create_cobra_model() legacy.read_cnapy_model(self.eng) # get some data reac_id = self.eng.get_reacID() # setting parameters a = self.eng.eval("constraints = {};", nargout=0, stdout=self.out, stderr=self.err) scenario = {} if self.constraints.checkState( ) == Qt.Checked or self.flux_bounds.isChecked(): onoff_str = "" for r in reac_id: if r in self.appdata.project.scen_values.keys(): (vl, vu) = self.appdata.project.scen_values[r] if vl == vu: if vl > 0: onoff_str = onoff_str + " NaN" # efmtool does not support 1 elif vl == 0: scenario[r] = (0, 0) onoff_str = onoff_str + " 0" else: onoff_str = onoff_str + " NaN" print("WARN: negative value in scenario") else: onoff_str = onoff_str + " NaN" print("WARN: not fixed value in scenario") else: onoff_str = onoff_str + " NaN" onoff_str = "reaconoff = [" + onoff_str + "];" a = self.eng.eval(onoff_str, nargout=0, stdout=self.out, stderr=self.err) a = self.eng.eval("constraints.reaconoff = reaconoff;", nargout=0, stdout=self.out, stderr=self.err) if self.flux_bounds.isChecked(): threshold = float(self.threshold.text()) lb_str = "" ub_str = "" for r in reac_id: c_reaction = self.appdata.project.cobra_py_model.reactions.get_by_id( r) if r in self.appdata.project.scen_values: (vl, vu) = self.appdata.project.scen_values[r] else: vl = c_reaction.lower_bound vu = c_reaction.upper_bound if vl <= -threshold: vl = "NaN" if vu >= threshold: vu = "NaN" if vl == 0 and vu == 0: # already in reaconoff, can be skipped here vl = "NaN" vu = "NaN" lb_str = lb_str + " " + str(vl) ub_str = ub_str + " " + str(vu) lb_str = "lb = [" + lb_str + "];" a = self.eng.eval(lb_str, nargout=0, stdout=self.out, stderr=self.err) a = self.eng.eval("constraints.lb = lb;", nargout=0, stdout=self.out, stderr=self.err) ub_str = "ub = [" + ub_str + "];" a = self.eng.eval(ub_str, nargout=0, stdout=self.out, stderr=self.err) a = self.eng.eval("constraints.ub = ub;", nargout=0, stdout=self.out, stderr=self.err) # TODO set solver 4 = EFMTool 3 = MetaTool, 1 = cna Mex file, 0 = cna functions a = self.eng.eval("solver = 4;", nargout=0, stdout=self.out, stderr=self.err) if self.check_reversibility.checkState() == Qt.Checked: a = self.eng.eval("irrev_flag = 1;", nargout=0, stdout=self.out, stderr=self.err) else: a = self.eng.eval("irrev_flag = 0;", nargout=0, stdout=self.out, stderr=self.err) # convex basis computation is only possible with METATOOL solver=3 if self.convex_basis.checkState() == Qt.Checked: a = self.eng.eval("conv_basis_flag = 1; solver = 3;", nargout=0, stdout=self.out, stderr=self.err) else: a = self.eng.eval("conv_basis_flag = 0;", nargout=0, stdout=self.out, stderr=self.err) if self.isozymes.checkState() == Qt.Checked: a = self.eng.eval("iso_flag = 1;", nargout=0, stdout=self.out, stderr=self.err) else: a = self.eng.eval("iso_flag = 0;", nargout=0, stdout=self.out, stderr=self.err) # default we have no macromolecules and display is et to ALL a = self.eng.eval("c_macro=[]; display= 'ALL';", nargout=0, stdout=self.out, stderr=self.err) if self.rational_numbers.checkState() == Qt.Checked: a = self.eng.eval( "efmtool_options = {'arithmetic', 'fractional'};", nargout=0, stdout=self.out, stderr=self.err) else: a = self.eng.eval("efmtool_options = {};", nargout=0, stdout=self.out, stderr=self.err) if self.appdata.is_matlab_set(): try: a = self.eng.eval( "[ems, irrev_ems, ems_idx, ray] = CNAcomputeEFM(cnap, constraints,solver,irrev_flag,conv_basis_flag,iso_flag,c_macro,display,efmtool_options);", nargout=0) except Exception: output = io.StringIO() traceback.print_exc(file=output) exstr = output.getvalue() print(exstr) QMessageBox.warning( self, 'Unknown exception occured!', exstr + '\nPlease report the problem to:\n\ \nhttps://github.com/cnapy-org/CNApy/issues' ) return else: ems = self.eng.workspace['ems'] idx = self.eng.workspace['ems_idx'] irreversible = numpy.squeeze(self.eng.workspace['irrev_ems']) unbounded = numpy.squeeze(self.eng.workspace['ray']) ems = numpy.array(ems) self.result2ui(ems, idx, reac_id, irreversible, unbounded, scenario) self.accept() elif self.appdata.is_octave_ready(): a = self.eng.eval( "[ems, irrev_ems, ems_idx, ray] = CNAcomputeEFM(cnap, constraints,solver,irrev_flag,conv_basis_flag,iso_flag,c_macro,display,efmtool_options);", nargout=0) ems = self.eng.pull('ems') idx = self.eng.pull('ems_idx') irreversible = numpy.squeeze(self.eng.pull('irrev_ems')) unbounded = numpy.squeeze(self.eng.pull('ray')) self.result2ui(ems, idx, reac_id, irreversible, unbounded, scenario) def result2ui(self, ems, idx, reac_id, irreversible, unbounded, scenario): if len(ems) == 0: QMessageBox.information( self, 'No modes', 'Modes have not been calculated or do not exist.') else: self.appdata.project.modes = FluxVectorContainer( ems, [reac_id[int(i) - 1] for i in idx[0]], irreversible, unbounded) self.centralwidget.mode_navigator.current = 0 self.centralwidget.mode_navigator.scenario = scenario self.centralwidget.mode_navigator.title.setText("Mode Navigation") self.centralwidget.update_mode()
class WorkflowWidget(QWidget): sigAddFunction = Signal(object) sigRunWorkflow = Signal() # TODO -- emit Workflow from sigRunWorkflow def __init__(self, workflowview: QAbstractItemView, operation_filter: Callable[[OperationPlugin], bool] = None, workflows: Dict[Workflow, str] = None): super(WorkflowWidget, self).__init__() self.operation_filter = operation_filter self.view = workflowview self.autorun_checkbox = QCheckBox("Run Automatically") self.autorun_checkbox.setCheckState(Qt.Unchecked) self.autorun_checkbox.stateChanged.connect(self._autorun_state_changed) self.run_button = QPushButton("Run Workflow") self.run_button.clicked.connect(self.sigRunWorkflow.emit) self.view.model().workflow.attach(self._autorun) # TODO -- actually hook up the auto run OR dependent class needs to connect (see SAXSGUIPlugin) self.toolbar = QToolBar() self.addfunctionmenu = QToolButton() self.addfunctionmenu.setIcon(QIcon(path("icons/addfunction.png"))) self.addfunctionmenu.setText("Add Function") self.addfunctionmenu.setToolTip("Add Operation") self.addfunctionmenu.setWhatsThis( "This button can be used to add a new operation to the end of a workflow. " "A menu to select operations will be populated based on the installed " "operations' categories.") # Defer menu population to once the plugins have been loaded; otherwise, the menu may not contain anything # if this widget is init'd before all plugins have been loaded. self.functionmenu = QMenu() self.functionmenu.aboutToShow.connect(self.populateFunctionMenu) self.addfunctionmenu.setMenu(self.functionmenu) self.addfunctionmenu.setPopupMode(QToolButton.InstantPopup) self.workflows = WorkflowDict(workflows or {}) self.workflow_menu = QMenu() self.workflow_menu.aboutToShow.connect(self.populateWorkflowMenu) self.workflow_selector = QToolButton() self.workflow_selector.setIcon(QIcon(path("icons/bookshelf.png"))) self.workflow_selector.setText("Select Workflow") self.workflow_selector.setToolTip("Workflow Library") self.workflow_selector.setWhatsThis( "This button allows switching between any stored workflows. " "(Stored workflows are typically defined programmatically " "in a GUI Plugin's modules.)") self.workflow_selector.setMenu(self.workflow_menu) self.workflow_selector.setPopupMode(QToolButton.InstantPopup) self.toolbar.addWidget(self.workflow_selector) self.toolbar.addWidget(self.addfunctionmenu) # self.toolbar.addAction(QIcon(path('icons/up.png')), 'Move Up') # self.toolbar.addAction(QIcon(path('icons/down.png')), 'Move Down') action = self.toolbar.addAction(QIcon(path("icons/save.png")), "Export Workflow") action.setEnabled(False) # FIXME: implement export workflow feature action = self.toolbar.addAction(QIcon(path("icons/folder.png")), "Import Workflow") action.setEnabled(False) # FIXME: implement import workflow feature action = self.toolbar.addAction(QIcon(path("icons/trash.png")), "Delete Operation", self.deleteOperation) action.setWhatsThis("This button removes the currently selected operation from the workflow. "\ "(The currently selected operation is highlighted. "\ "An operation is selected when its text is clicked in the workflow editor.") v = QVBoxLayout() v.addWidget(self.view) h = QHBoxLayout() h.addWidget(self.autorun_checkbox) h.addWidget(self.run_button) v.addLayout(h) v.addWidget(self.toolbar) v.setContentsMargins(0, 0, 0, 0) self.setLayout(v) def _autorun_state_changed(self, state): if state == Qt.Checked: self.run_button.setDisabled(True) else: self.run_button.setDisabled(False) def _autorun(self): if self.autorun_checkbox.isChecked(): self.sigRunWorkflow.emit() def populateFunctionMenu(self): self.functionmenu.clear() sortingDict = MenuDict() operations = pluginmanager.get_plugins_of_type("OperationPlugin") if self.operation_filter is not None: operations = filter(self.operation_filter, operations) for operation in operations: categories = operation.categories if not categories: categories = [("Uncategorized", ) ] # put found operations into a default category for categories_tuple in categories: if isinstance(categories_tuple, str): categories_tuple = (categories_tuple, ) submenu = sortingDict categories_list = list(categories_tuple) while categories_list: category = categories_list.pop(0) submenu = submenu[category] submenu['___'].append(operation) self._mkMenu(sortingDict) def populateWorkflowMenu(self): self.workflow_menu.clear() for workflow, workflow_name in self.workflows.items(): self.workflow_menu.addAction(workflow_name, partial(self.setWorkflow, workflow)) def _mkMenu(self, sorting_dict, menu=None): if menu is None: menu = self.functionmenu menu.clear() for key in sorting_dict: if key == '___': menu.addSeparator() for operation in sorting_dict['___']: menu.addAction( operation.name, partial(self.addOperation, operation, autoconnectall=True)) else: submenu = QMenu(title=key, parent=menu) menu.addMenu(submenu) self._mkMenu(sorting_dict[key], submenu) def setWorkflow(self, workflow: Workflow): self.view.model().workflow = workflow def addWorkflow(self, workflow: Workflow, name: str = None): if name is None: name = workflow.name if name in self.workflows: raise ValueError( f'A workflow already exists in this editor with the name "{name}"' ) self.workflows[name] = workflow def removeWorkflow(self, workflow): for name, match_workflow in self.workflows.items(): if workflow == match_workflow: del self.workflows[name] def addOperation(self, operation: OperationPlugin, autoconnectall=True): self.view.model().workflow.add_operation(operation()) if autoconnectall: self.view.model().workflow.auto_connect_all() print("selected new row:", self.view.model().rowCount() - 1) self.view.setCurrentIndex(self.view.model().index( self.view.model().rowCount() - 1, 0)) def deleteOperation(self): index = self.view.currentIndex() operation = self.view.model().workflow.operations[index.row()] self.view.model().workflow.remove_operation(operation) self.view.setCurrentIndex(QModelIndex())
class FindReplace(QWidget): """Find widget""" STYLE = {False: "background-color:rgb(255, 175, 90);", True: ""} visibility_changed = Signal(bool) def __init__(self, parent, enable_replace=False): QWidget.__init__(self, parent) self.enable_replace = enable_replace self.editor = None self.is_code_editor = None glayout = QGridLayout() glayout.setContentsMargins(0, 0, 0, 0) self.setLayout(glayout) self.close_button = create_toolbutton(self, triggered=self.hide, icon=ima.icon('DialogCloseButton')) glayout.addWidget(self.close_button, 0, 0) # Find layout self.search_text = PatternComboBox(self, tip=_("Search string"), adjust_to_minimum=False) self.search_text.valid.connect( lambda state: self.find(changed=False, forward=True, rehighlight=False)) self.search_text.lineEdit().textEdited.connect( self.text_has_been_edited) self.previous_button = create_toolbutton(self, triggered=self.find_previous, icon=ima.icon('ArrowUp')) self.next_button = create_toolbutton(self, triggered=self.find_next, icon=ima.icon('ArrowDown')) self.next_button.clicked.connect(self.update_search_combo) self.previous_button.clicked.connect(self.update_search_combo) self.re_button = create_toolbutton(self, icon=ima.icon('advanced'), tip=_("Regular expression")) self.re_button.setCheckable(True) self.re_button.toggled.connect(lambda state: self.find()) self.case_button = create_toolbutton(self, icon=get_icon("upper_lower.png"), tip=_("Case Sensitive")) self.case_button.setCheckable(True) self.case_button.toggled.connect(lambda state: self.find()) self.words_button = create_toolbutton(self, icon=get_icon("whole_words.png"), tip=_("Whole words")) self.words_button.setCheckable(True) self.words_button.toggled.connect(lambda state: self.find()) self.highlight_button = create_toolbutton(self, icon=get_icon("highlight.png"), tip=_("Highlight matches")) self.highlight_button.setCheckable(True) self.highlight_button.toggled.connect(self.toggle_highlighting) hlayout = QHBoxLayout() self.widgets = [self.close_button, self.search_text, self.previous_button, self.next_button, self.re_button, self.case_button, self.words_button, self.highlight_button] for widget in self.widgets[1:]: hlayout.addWidget(widget) glayout.addLayout(hlayout, 0, 1) # Replace layout replace_with = QLabel(_("Replace with:")) self.replace_text = PatternComboBox(self, adjust_to_minimum=False, tip=_('Replace string')) self.replace_button = create_toolbutton(self, text=_('Replace/find'), icon=ima.icon('DialogApplyButton'), triggered=self.replace_find, text_beside_icon=True) self.replace_button.clicked.connect(self.update_replace_combo) self.replace_button.clicked.connect(self.update_search_combo) self.all_check = QCheckBox(_("Replace all")) self.replace_layout = QHBoxLayout() widgets = [replace_with, self.replace_text, self.replace_button, self.all_check] for widget in widgets: self.replace_layout.addWidget(widget) glayout.addLayout(self.replace_layout, 1, 1) self.widgets.extend(widgets) self.replace_widgets = widgets self.hide_replace() self.search_text.setTabOrder(self.search_text, self.replace_text) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) self.shortcuts = self.create_shortcuts(parent) self.highlight_timer = QTimer(self) self.highlight_timer.setSingleShot(True) self.highlight_timer.setInterval(1000) self.highlight_timer.timeout.connect(self.highlight_matches) def create_shortcuts(self, parent): """Create shortcuts for this widget""" # Configurable findnext = config_shortcut(self.find_next, context='_', name='Find next', parent=parent) findprev = config_shortcut(self.find_previous, context='_', name='Find previous', parent=parent) togglefind = config_shortcut(self.show, context='_', name='Find text', parent=parent) togglereplace = config_shortcut(self.toggle_replace_widgets, context='_', name='Replace text', parent=parent) # Fixed fixed_shortcut("Escape", self, self.hide) return [findnext, findprev, togglefind, togglereplace] def get_shortcut_data(self): """ Returns shortcut data, a list of tuples (shortcut, text, default) shortcut (QShortcut or QAction instance) text (string): action/shortcut description default (string): default key sequence """ return [sc.data for sc in self.shortcuts] def update_search_combo(self): self.search_text.lineEdit().returnPressed.emit() def update_replace_combo(self): self.replace_text.lineEdit().returnPressed.emit() def toggle_replace_widgets(self): if self.enable_replace: # Toggle replace widgets if self.replace_widgets[0].isVisible(): self.hide_replace() self.hide() else: self.show_replace() self.replace_text.setFocus() @Slot(bool) def toggle_highlighting(self, state): """Toggle the 'highlight all results' feature""" if self.editor is not None: if state: self.highlight_matches() else: self.clear_matches() def show(self): """Overrides Qt Method""" QWidget.show(self) self.visibility_changed.emit(True) if self.editor is not None: text = self.editor.get_selected_text() # If no text is highlighted for search, use whatever word is under the cursor if not text: cursor = self.editor.textCursor() cursor.select(QTextCursor.WordUnderCursor) text = to_text_string(cursor.selectedText()) # Now that text value is sorted out, use it for the search if text: self.search_text.setEditText(text) self.search_text.lineEdit().selectAll() self.refresh() else: self.search_text.lineEdit().selectAll() self.search_text.setFocus() @Slot() def hide(self): """Overrides Qt Method""" for widget in self.replace_widgets: widget.hide() QWidget.hide(self) self.visibility_changed.emit(False) if self.editor is not None: self.editor.setFocus() self.clear_matches() def show_replace(self): """Show replace widgets""" self.show() for widget in self.replace_widgets: widget.show() def hide_replace(self): """Hide replace widgets""" for widget in self.replace_widgets: widget.hide() def refresh(self): """Refresh widget""" if self.isHidden(): if self.editor is not None: self.clear_matches() return state = self.editor is not None for widget in self.widgets: widget.setEnabled(state) if state: self.find() def set_editor(self, editor, refresh=True): """ Set associated editor/web page: codeeditor.base.TextEditBaseWidget browser.WebView """ self.editor = editor # Note: This is necessary to test widgets/editor.py # in Qt builds that don't have web widgets try: from qtpy.QtWebEngineWidgets import QWebEngineView except ImportError: QWebEngineView = type(None) self.words_button.setVisible(not isinstance(editor, QWebEngineView)) self.re_button.setVisible(not isinstance(editor, QWebEngineView)) from spyderlib.widgets.sourcecode.codeeditor import CodeEditor self.is_code_editor = isinstance(editor, CodeEditor) self.highlight_button.setVisible(self.is_code_editor) if refresh: self.refresh() if self.isHidden() and editor is not None: self.clear_matches() @Slot() def find_next(self): """Find next occurrence""" state = self.find(changed=False, forward=True, rehighlight=False) self.editor.setFocus() self.search_text.add_current_text() return state @Slot() def find_previous(self): """Find previous occurrence""" state = self.find(changed=False, forward=False, rehighlight=False) self.editor.setFocus() return state def text_has_been_edited(self, text): """Find text has been edited (this slot won't be triggered when setting the search pattern combo box text programmatically""" self.find(changed=True, forward=True, start_highlight_timer=True) def highlight_matches(self): """Highlight found results""" if self.is_code_editor and self.highlight_button.isChecked(): text = self.search_text.currentText() words = self.words_button.isChecked() regexp = self.re_button.isChecked() self.editor.highlight_found_results(text, words=words, regexp=regexp) def clear_matches(self): """Clear all highlighted matches""" if self.is_code_editor: self.editor.clear_found_results() def find(self, changed=True, forward=True, rehighlight=True, start_highlight_timer=False): """Call the find function""" text = self.search_text.currentText() if len(text) == 0: self.search_text.lineEdit().setStyleSheet("") return None else: case = self.case_button.isChecked() words = self.words_button.isChecked() regexp = self.re_button.isChecked() found = self.editor.find_text(text, changed, forward, case=case, words=words, regexp=regexp) self.search_text.lineEdit().setStyleSheet(self.STYLE[found]) if self.is_code_editor and found: if rehighlight or not self.editor.found_results: self.highlight_timer.stop() if start_highlight_timer: self.highlight_timer.start() else: self.highlight_matches() else: self.clear_matches() return found @Slot() def replace_find(self): """Replace and find""" if (self.editor is not None): replace_text = to_text_string(self.replace_text.currentText()) search_text = to_text_string(self.search_text.currentText()) pattern = search_text if self.re_button.isChecked() else None case = self.case_button.isChecked() first = True cursor = None while True: if first: # First found seltxt = to_text_string(self.editor.get_selected_text()) cmptxt1 = search_text if case else search_text.lower() cmptxt2 = seltxt if case else seltxt.lower() if self.editor.has_selected_text() and cmptxt1 == cmptxt2: # Text was already found, do nothing pass else: if not self.find(changed=False, forward=True, rehighlight=False): break first = False wrapped = False position = self.editor.get_position('cursor') position0 = position cursor = self.editor.textCursor() cursor.beginEditBlock() else: position1 = self.editor.get_position('cursor') if is_position_inf(position1, position0 + len(replace_text) - len(search_text) + 1): # Identify wrapping even when the replace string # includes part of the search string wrapped = True if wrapped: if position1 == position or \ is_position_sup(position1, position): # Avoid infinite loop: replace string includes # part of the search string break if position1 == position0: # Avoid infinite loop: single found occurrence break position0 = position1 if pattern is None: cursor.removeSelectedText() cursor.insertText(replace_text) else: seltxt = to_text_string(cursor.selectedText()) cursor.removeSelectedText() cursor.insertText(re.sub(pattern, replace_text, seltxt)) if self.find_next(): found_cursor = self.editor.textCursor() cursor.setPosition(found_cursor.selectionStart(), QTextCursor.MoveAnchor) cursor.setPosition(found_cursor.selectionEnd(), QTextCursor.KeepAnchor) else: break if not self.all_check.isChecked(): break self.all_check.setCheckState(Qt.Unchecked) if cursor is not None: cursor.endEditBlock()
class QtLabelsControls(QtLayerControls): """Qt view and controls for the napari Labels layer. Parameters ---------- layer : napari.layers.Labels An instance of a napari Labels layer. Attributes ---------- button_group : qtpy.QtWidgets.QButtonGroup Button group of labels layer modes: PAN_ZOOM, PICKER, PAINT, ERASE, or FILL. colormapUpdate : qtpy.QtWidgets.QPushButton Button to update colormap of label layer. contigCheckBox : qtpy.QtWidgets.QCheckBox Checkbox to control if label layer is contiguous. fill_button : qtpy.QtWidgets.QtModeRadioButton Button to select FILL mode on Labels layer. grid_layout : qtpy.QtWidgets.QGridLayout Layout of Qt widget controls for the layer. layer : napari.layers.Labels An instance of a napari Labels layer. ndimSpinBox : qtpy.QtWidgets.QSpinBox Spinbox to control the number of editable dimensions of label layer. paint_button : qtpy.QtWidgets.QtModeRadioButton Button to select PAINT mode on Labels layer. panzoom_button : qtpy.QtWidgets.QtModeRadioButton Button to select PAN_ZOOM mode on Labels layer. pick_button : qtpy.QtWidgets.QtModeRadioButton Button to select PICKER mode on Labels layer. erase_button : qtpy.QtWidgets.QtModeRadioButton Button to select ERASE mode on Labels layer. selectionSpinBox : superqt.QLargeIntSpinBox Widget to select a specific label by its index. N.B. cannot represent labels > 2**53. Raises ------ ValueError Raise error if label mode is not PAN_ZOOM, PICKER, PAINT, ERASE, or FILL. """ def __init__(self, layer): super().__init__(layer) self.layer.events.mode.connect(self._on_mode_change) self.layer.events._ndisplay.connect(self._on_ndisplay_change) self.layer.events.rendering.connect(self._on_rendering_change) self.layer.events.selected_label.connect( self._on_selected_label_change) self.layer.events.brush_size.connect(self._on_brush_size_change) self.layer.events.contiguous.connect(self._on_contiguous_change) self.layer.events.n_edit_dimensions.connect( self._on_n_edit_dimensions_change) self.layer.events.contour.connect(self._on_contour_change) self.layer.events.editable.connect(self._on_editable_change) self.layer.events.preserve_labels.connect( self._on_preserve_labels_change) self.layer.events.color_mode.connect(self._on_color_mode_change) # selection spinbox self.selectionSpinBox = QLargeIntSpinBox() dtype_lims = get_dtype_limits(get_dtype(layer)) self.selectionSpinBox.setRange(*dtype_lims) self.selectionSpinBox.setKeyboardTracking(False) self.selectionSpinBox.valueChanged.connect(self.changeSelection) self.selectionSpinBox.setAlignment(Qt.AlignCenter) self._on_selected_label_change() self.maskSelectionCheckBox = QCheckBox() self.maskSelectionCheckBox.setCheckState(Qt.CheckState.Unchecked) self.maskSelectionCheckBox.stateChanged.connect(self.maskSelection) sld = QSlider(Qt.Horizontal) sld.setFocusPolicy(Qt.NoFocus) sld.setMinimum(1) sld.setMaximum(40) sld.setSingleStep(1) sld.valueChanged.connect(self.changeSize) self.brushSizeSlider = sld self._on_brush_size_change() contig_cb = QCheckBox() contig_cb.setToolTip(trans._('contiguous editing')) contig_cb.stateChanged.connect(self.change_contig) self.contigCheckBox = contig_cb self._on_contiguous_change() ndim_sb = QSpinBox() self.ndimSpinBox = ndim_sb ndim_sb.setToolTip(trans._('number of dimensions for label editing')) ndim_sb.valueChanged.connect(self.change_n_edit_dim) ndim_sb.setMinimum(2) ndim_sb.setMaximum(self.layer.ndim) ndim_sb.setSingleStep(1) ndim_sb.setAlignment(Qt.AlignCenter) self._on_n_edit_dimensions_change() self.contourSpinBox = QLargeIntSpinBox() self.contourSpinBox.setRange(*dtype_lims) self.contourSpinBox.setToolTip(trans._('display contours of labels')) self.contourSpinBox.valueChanged.connect(self.change_contour) self.contourSpinBox.setKeyboardTracking(False) self.contourSpinBox.setAlignment(Qt.AlignCenter) self._on_contour_change() preserve_labels_cb = QCheckBox() preserve_labels_cb.setToolTip( trans._('preserve existing labels while painting')) preserve_labels_cb.stateChanged.connect(self.change_preserve_labels) self.preserveLabelsCheckBox = preserve_labels_cb self._on_preserve_labels_change() selectedColorCheckbox = QCheckBox() selectedColorCheckbox.setToolTip( trans._("Display only selected label")) selectedColorCheckbox.stateChanged.connect(self.toggle_selected_mode) self.selectedColorCheckbox = selectedColorCheckbox # shuffle colormap button self.colormapUpdate = QtModePushButton( None, 'shuffle', slot=self.changeColor, tooltip=trans._('shuffle colors'), ) self.panzoom_button = QtModeRadioButton( layer, 'zoom', Mode.PAN_ZOOM, checked=True, ) action_manager.bind_button('napari:activate_label_pan_zoom_mode', self.panzoom_button) self.pick_button = QtModeRadioButton(layer, 'picker', Mode.PICK) action_manager.bind_button('napari:activate_label_picker_mode', self.pick_button) self.paint_button = QtModeRadioButton(layer, 'paint', Mode.PAINT) action_manager.bind_button('napari:activate_paint_mode', self.paint_button) self.fill_button = QtModeRadioButton( layer, 'fill', Mode.FILL, ) action_manager.bind_button( 'napari:activate_fill_mode', self.fill_button, extra_tooltip_text=trans._( "Toggle with {shortcut}", shortcut=Shortcut("Control"), ), ) self.erase_button = QtModeRadioButton( layer, 'erase', Mode.ERASE, ) action_manager.bind_button( 'napari:activate_label_erase_mode', self.erase_button, extra_tooltip_text=trans._( "Toggle with {shortcut}", shortcut=Shortcut("Alt"), ), ) # don't bind with action manager as this would remove "Toggle with {shortcut}" self.button_group = QButtonGroup(self) self.button_group.addButton(self.panzoom_button) self.button_group.addButton(self.paint_button) self.button_group.addButton(self.pick_button) self.button_group.addButton(self.fill_button) self.button_group.addButton(self.erase_button) self._on_editable_change() button_row = QHBoxLayout() button_row.addStretch(1) button_row.addWidget(self.colormapUpdate) button_row.addWidget(self.erase_button) button_row.addWidget(self.paint_button) button_row.addWidget(self.fill_button) button_row.addWidget(self.pick_button) button_row.addWidget(self.panzoom_button) button_row.setSpacing(4) button_row.setContentsMargins(0, 0, 0, 5) renderComboBox = QComboBox(self) rendering_options = [i.value for i in LabelsRendering] renderComboBox.addItems(rendering_options) index = renderComboBox.findText(self.layer.rendering, Qt.MatchFixedString) renderComboBox.setCurrentIndex(index) renderComboBox.activated[str].connect(self.changeRendering) self.renderComboBox = renderComboBox self.renderLabel = QLabel(trans._('rendering:')) self._on_ndisplay_change() color_mode_comboBox = QComboBox(self) for index, (data, text) in enumerate(LABEL_COLOR_MODE_TRANSLATIONS.items()): data = data.value color_mode_comboBox.addItem(text, data) if self.layer.color_mode == data: color_mode_comboBox.setCurrentIndex(index) color_mode_comboBox.activated.connect(self.change_color_mode) self.colorModeComboBox = color_mode_comboBox self._on_color_mode_change() color_layout = QHBoxLayout() self.colorBox = QtColorBox(layer) color_layout.addWidget(self.colorBox) color_layout.addWidget(self.selectionSpinBox) # grid_layout created in QtLayerControls # addWidget(widget, row, column, [row_span, column_span]) self.grid_layout.addLayout(button_row, 0, 0, 1, 4) self.grid_layout.addWidget(QLabel(trans._('label:')), 1, 0, 1, 1) self.grid_layout.addWidget(self.maskSelectionCheckBox, 1, 1, 1, 1) self.grid_layout.addLayout(color_layout, 1, 2, 1, 2) self.grid_layout.addWidget(QLabel(trans._('opacity:')), 2, 0, 1, 1) self.grid_layout.addWidget(self.opacitySlider, 2, 1, 1, 3) self.grid_layout.addWidget(QLabel(trans._('brush size:')), 3, 0, 1, 1) self.grid_layout.addWidget(self.brushSizeSlider, 3, 1, 1, 3) self.grid_layout.addWidget(QLabel(trans._('blending:')), 5, 0, 1, 1) self.grid_layout.addWidget(self.blendComboBox, 5, 1, 1, 3) self.grid_layout.addWidget(self.renderLabel, 6, 0, 1, 1) self.grid_layout.addWidget(self.renderComboBox, 6, 1, 1, 3) self.grid_layout.addWidget(QLabel(trans._('color mode:')), 7, 0, 1, 1) self.grid_layout.addWidget(self.colorModeComboBox, 7, 1, 1, 3) self.grid_layout.addWidget(QLabel(trans._('contour:')), 8, 0, 1, 1) self.grid_layout.addWidget(self.contourSpinBox, 8, 1, 1, 1) self.grid_layout.addWidget(QLabel(trans._('n edit dim:')), 9, 0, 1, 1) self.grid_layout.addWidget(self.ndimSpinBox, 9, 1, 1, 1) self.grid_layout.addWidget(QLabel(trans._('contiguous:')), 10, 0, 1, 1) self.grid_layout.addWidget(self.contigCheckBox, 10, 1, 1, 1) self.grid_layout.addWidget(QLabel(trans._('preserve\nlabels:')), 11, 0, 1, 2) self.grid_layout.addWidget(self.preserveLabelsCheckBox, 11, 1, 1, 1) self.grid_layout.addWidget(QLabel(trans._('show\nselected:')), 11, 2, 1, 1) self.grid_layout.addWidget(self.selectedColorCheckbox, 11, 3, 1, 1) self.grid_layout.setRowStretch(12, 1) self.grid_layout.setColumnStretch(1, 1) self.grid_layout.setSpacing(4) def _on_mode_change(self, event): """Receive layer model mode change event and update checkbox ticks. Parameters ---------- event : napari.utils.event.Event The napari event that triggered this method. Raises ------ ValueError Raise error if event.mode is not PAN_ZOOM, PICK, PAINT, ERASE, or FILL """ mode = event.mode if mode == Mode.PAN_ZOOM: self.panzoom_button.setChecked(True) elif mode == Mode.PICK: self.pick_button.setChecked(True) elif mode == Mode.PAINT: self.paint_button.setChecked(True) elif mode == Mode.FILL: self.fill_button.setChecked(True) elif mode == Mode.ERASE: self.erase_button.setChecked(True) elif mode == Mode.TRANSFORM: pass else: raise ValueError(trans._("Mode not recognized")) def changeRendering(self, text): """Change rendering mode for image display. Parameters ---------- text : str Rendering mode used by vispy. Selects a preset rendering mode in vispy that determines how volume is displayed: * translucent: voxel colors are blended along the view ray until the result is opaque. * iso_categorical: isosurface for categorical data (e.g., labels). Cast a ray until a value greater than zero is encountered. At that location, lighning calculations are performed to give the visual appearance of a surface. """ self.layer.rendering = text def changeColor(self): """Change colormap of the label layer.""" self.layer.new_colormap() def maskSelection(self, state): """Mask the selected label Parameters ---------- state : int State of the checkbox. """ if state == Qt.CheckState.Unchecked: self.selectionSpinBox.setMaskLineEdit(False) if state == Qt.CheckState.Checked: self.selectionSpinBox.setMaskLineEdit(True) def changeSelection(self, value): """Change currently selected label. Parameters ---------- value : int Index of label to select. """ self.layer.selected_label = value self.selectionSpinBox.clearFocus() self.setFocus() def toggle_selected_mode(self, state): if state == Qt.Checked: self.layer.show_selected_label = True else: self.layer.show_selected_label = False def changeSize(self, value): """Change paint brush size. Parameters ---------- value : float Size of the paint brush. """ self.layer.brush_size = value def change_contig(self, state): """Toggle contiguous state of label layer. Parameters ---------- state : QCheckBox Checkbox indicating if labels are contiguous. """ if state == Qt.Checked: self.layer.contiguous = True else: self.layer.contiguous = False def change_n_edit_dim(self, value): """Change the number of editable dimensions of label layer. Parameters ---------- value : int The number of editable dimensions to set. """ self.layer.n_edit_dimensions = value self.ndimSpinBox.clearFocus() self.setFocus() def change_contour(self, value): """Change contour thickness. Parameters ---------- value : int Thickness of contour. """ self.layer.contour = value self.contourSpinBox.clearFocus() self.setFocus() def change_preserve_labels(self, state): """Toggle preserve_labels state of label layer. Parameters ---------- state : QCheckBox Checkbox indicating if overwriting label is enabled. """ self.layer.preserve_labels = state == Qt.Checked def change_color_mode(self): """Change color mode of label layer""" self.layer.color_mode = self.colorModeComboBox.currentData() def _on_contour_change(self): """Receive layer model contour value change event and update spinbox.""" with self.layer.events.contour.blocker(): value = self.layer.contour self.contourSpinBox.setValue(value) def _on_selected_label_change(self): """Receive layer model label selection change event and update spinbox.""" with self.layer.events.selected_label.blocker(): value = self.layer.selected_label self.selectionSpinBox.setValue(value) def _on_brush_size_change(self): """Receive layer model brush size change event and update the slider.""" with self.layer.events.brush_size.blocker(): value = self.layer.brush_size value = np.maximum(1, int(value)) if value > self.brushSizeSlider.maximum(): self.brushSizeSlider.setMaximum(int(value)) self.brushSizeSlider.setValue(value) def _on_n_edit_dimensions_change(self): """Receive layer model n-dim mode change event and update the checkbox.""" with self.layer.events.n_edit_dimensions.blocker(): value = self.layer.n_edit_dimensions self.ndimSpinBox.setValue(int(value)) def _on_contiguous_change(self): """Receive layer model contiguous change event and update the checkbox.""" with self.layer.events.contiguous.blocker(): self.contigCheckBox.setChecked(self.layer.contiguous) def _on_preserve_labels_change(self): """Receive layer model preserve_labels event and update the checkbox.""" with self.layer.events.preserve_labels.blocker(): self.preserveLabelsCheckBox.setChecked(self.layer.preserve_labels) def _on_color_mode_change(self): """Receive layer model color.""" with self.layer.events.color_mode.blocker(): self.colorModeComboBox.setCurrentIndex( self.colorModeComboBox.findData(self.layer.color_mode)) def _on_editable_change(self): """Receive layer model editable change event & enable/disable buttons.""" # In 3D mode, we need to disable all buttons other than picking # (only picking works in 3D) widget_list = [ 'pick_button', 'fill_button', 'paint_button', 'erase_button', ] widgets_to_toggle = { (2, True): widget_list, (2, False): widget_list, (3, True): widget_list, (3, False): widget_list, } disable_with_opacity( self, widgets_to_toggle[(self.layer._ndisplay, self.layer.editable)], self.layer.editable, ) def _on_rendering_change(self): """Receive layer model rendering change event and update dropdown menu.""" with self.layer.events.rendering.blocker(): index = self.renderComboBox.findText(self.layer.rendering, Qt.MatchFixedString) self.renderComboBox.setCurrentIndex(index) def _on_ndisplay_change(self): """Toggle between 2D and 3D visualization modes.""" if self.layer._ndisplay == 2: self.renderComboBox.hide() self.renderLabel.hide() else: self.renderComboBox.show() self.renderLabel.show() self._on_editable_change() def deleteLater(self): disconnect_events(self.layer.events, self.colorBox) super().deleteLater()
class WorkflowWidget(QWidget): sigAddFunction = Signal(object) sigRunWorkflow = Signal(object) # TODO -- emit Workflow from sigRunWorkflow def __init__(self, workflowview: QAbstractItemView): super(WorkflowWidget, self).__init__() self.view = workflowview self.autorun_checkbox = QCheckBox("Run Automatically") self.autorun_checkbox.setCheckState(Qt.Unchecked) self.autorun_checkbox.stateChanged.connect(self._autorun_state_changed) self.run_button = QPushButton("Run Workflow") self.run_button.clicked.connect(self.sigRunWorkflow.emit) # TODO -- actually hook up the auto run OR dependent class needs to connect (see SAXSGUIPlugin) self.toolbar = QToolBar() self.addfunctionmenu = QToolButton() self.addfunctionmenu.setIcon(QIcon(path("icons/addfunction.png"))) self.addfunctionmenu.setText("Add Function") # Defer menu population to once the plugins have been loaded; otherwise, the menu may not contain anything # if this widget is init'd before all plugins have been loaded. self.functionmenu = QMenu() self.functionmenu.aboutToShow.connect(self.populateFunctionMenu) self.addfunctionmenu.setMenu(self.functionmenu) self.addfunctionmenu.setPopupMode(QToolButton.InstantPopup) self.toolbar.addWidget(self.addfunctionmenu) # self.toolbar.addAction(QIcon(path('icons/up.png')), 'Move Up') # self.toolbar.addAction(QIcon(path('icons/down.png')), 'Move Down') self.toolbar.addAction(QIcon(path("icons/folder.png")), "Load Workflow") self.toolbar.addAction(QIcon(path("icons/trash.png")), "Delete Operation", self.deleteOperation) v = QVBoxLayout() v.addWidget(self.view) h = QHBoxLayout() h.addWidget(self.autorun_checkbox) h.addWidget(self.run_button) v.addLayout(h) v.addWidget(self.toolbar) v.setContentsMargins(0, 0, 0, 0) self.setLayout(v) def _autorun_state_changed(self, state): if state == Qt.Checked: self.run_button.setDisabled(True) else: self.run_button.setDisabled(False) def _run_workflow(self, _): self._workflow def populateFunctionMenu(self): self.functionmenu.clear() sortingDict = {} for plugin in pluginmanager.get_plugins_of_type("OperationPlugin"): typeOfOperationPlugin = plugin.categories # TODO : should OperationPlugin be responsible for initializing categories # to some placeholder value (instead of [])? if typeOfOperationPlugin == []: typeOfOperationPlugin = "uncategorized" # put found operations into a default category if not typeOfOperationPlugin in sortingDict.keys(): sortingDict[typeOfOperationPlugin] = [] sortingDict[typeOfOperationPlugin].append(plugin) for key in sortingDict.keys(): self.functionmenu.addSeparator() self.functionmenu.addAction(key) self.functionmenu.addSeparator() for plugin in sortingDict[key]: self.functionmenu.addAction( plugin.name, partial(self.addOperation, plugin, autoconnectall=True)) def addOperation(self, operation: OperationPlugin, autoconnectall=True): self.view.model().workflow.add_operation(operation()) if autoconnectall: self.view.model().workflow.auto_connect_all() print("selected new row:", self.view.model().rowCount() - 1) self.view.setCurrentIndex(self.view.model().index( self.view.model().rowCount() - 1, 0)) def deleteOperation(self): for index in self.view.selectedIndexes(): operation = self.view.model().workflow.operations[index.row()] self.view.model().workflow.remove_operation(operation)
class WorkflowWidget(QWidget): sigAddFunction = Signal(object) sigRunWorkflow = Signal() # TODO -- emit Workflow from sigRunWorkflow def __init__(self, workflowview: QAbstractItemView, operation_filter: Callable[[OperationPlugin], bool] = None): super(WorkflowWidget, self).__init__() self.operation_filter = operation_filter self.view = workflowview self.autorun_checkbox = QCheckBox("Run Automatically") self.autorun_checkbox.setCheckState(Qt.Unchecked) self.autorun_checkbox.stateChanged.connect(self._autorun_state_changed) self.run_button = QPushButton("Run Workflow") self.run_button.clicked.connect(self.sigRunWorkflow.emit) self.view.model().workflow.attach(self._autorun) # TODO -- actually hook up the auto run OR dependent class needs to connect (see SAXSGUIPlugin) self.toolbar = QToolBar() self.addfunctionmenu = QToolButton() self.addfunctionmenu.setIcon(QIcon(path("icons/addfunction.png"))) self.addfunctionmenu.setText("Add Function") # Defer menu population to once the plugins have been loaded; otherwise, the menu may not contain anything # if this widget is init'd before all plugins have been loaded. self.functionmenu = QMenu() self.functionmenu.aboutToShow.connect(self.populateFunctionMenu) self.addfunctionmenu.setMenu(self.functionmenu) self.addfunctionmenu.setPopupMode(QToolButton.InstantPopup) self.toolbar.addWidget(self.addfunctionmenu) # self.toolbar.addAction(QIcon(path('icons/up.png')), 'Move Up') # self.toolbar.addAction(QIcon(path('icons/down.png')), 'Move Down') self.toolbar.addAction(QIcon(path("icons/folder.png")), "Load Workflow") self.toolbar.addAction(QIcon(path("icons/trash.png")), "Delete Operation", self.deleteOperation) v = QVBoxLayout() v.addWidget(self.view) h = QHBoxLayout() h.addWidget(self.autorun_checkbox) h.addWidget(self.run_button) v.addLayout(h) v.addWidget(self.toolbar) v.setContentsMargins(0, 0, 0, 0) self.setLayout(v) def _autorun_state_changed(self, state): if state == Qt.Checked: self.run_button.setDisabled(True) else: self.run_button.setDisabled(False) def _autorun(self): if self.autorun_checkbox.isChecked(): self.sigRunWorkflow.emit() def populateFunctionMenu(self): self.functionmenu.clear() sortingDict = MenuDict() operations = pluginmanager.get_plugins_of_type("OperationPlugin") if self.operation_filter is not None: operations = filter(self.operation_filter, operations) for operation in operations: categories = operation.categories if not categories: categories = [("Uncategorized", ) ] # put found operations into a default category for categories_tuple in categories: if isinstance(categories_tuple, str): categories_tuple = (categories_tuple, ) submenu = sortingDict categories_list = list(categories_tuple) while categories_list: category = categories_list.pop(0) submenu = submenu[category] submenu['___'].append(operation) self._mkMenu(sortingDict) def _mkMenu(self, sorting_dict, menu=None): if menu is None: menu = self.functionmenu menu.clear() for key in sorting_dict: if key == '___': menu.addSeparator() for operation in sorting_dict['___']: menu.addAction( operation.name, partial(self.addOperation, operation, autoconnectall=True)) else: submenu = QMenu(title=key, parent=menu) menu.addMenu(submenu) self._mkMenu(sorting_dict[key], submenu) def addOperation(self, operation: OperationPlugin, autoconnectall=True): self.view.model().workflow.add_operation(operation()) if autoconnectall: self.view.model().workflow.auto_connect_all() print("selected new row:", self.view.model().rowCount() - 1) self.view.setCurrentIndex(self.view.model().index( self.view.model().rowCount() - 1, 0)) def deleteOperation(self): index = self.view.currentIndex() operation = self.view.model().workflow.operations[index.row()] self.view.model().workflow.remove_operation(operation) self.view.setCurrentIndex(QModelIndex())
class WriteModelDialog(QDialog): def __init__(self, parent=None): QDialog.__init__( self, parent, flags=Qt.WindowSystemMenuHint | Qt.WindowTitleHint) self.setWindowTitle('Write Model') self.treeview = parent self.setAttribute(Qt.WA_DeleteOnClose) fixed_dir_layout = QHBoxLayout() browse_btn = QPushButton(ima.icon('DirOpenIcon'), '', self) browse_btn.setToolTip(_("Select model directory")) browse_btn.clicked.connect(self.select_directory) self.wd_edit = QLineEdit() fixed_dir_layout.addWidget(self.wd_edit) fixed_dir_layout.addWidget(browse_btn) fixed_dir_layout.setContentsMargins(0, 0, 0, 0) namelabel = QLabel(_("Folder Name")) self.nameEdit = QLineEdit(self) self.backupCheck = QCheckBox(_("Back up old folder")) self.backupCheck.setCheckState(Qt.Checked) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons( QDialogButtonBox.Cancel|QDialogButtonBox.Ok) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) mainLayout = QGridLayout(self) mainLayout.addLayout(fixed_dir_layout, 0, 0, 1, 2) mainLayout.addWidget(namelabel, 1, 0) mainLayout.addWidget(self.nameEdit, 1, 1) mainLayout.addWidget(self.backupCheck, 2, 0, 1, 2) mainLayout.addWidget(self.buttonBox, 3, 0, 1, 2) # mainLayout.setContentsMargins(0, 0, 0, 0) self.setLayout(mainLayout) def accept(self) -> None: reply = { 'accepted': True, 'directory': self.wd_edit.text(), 'name': self.nameEdit.text(), 'backup': self.backupCheck.isChecked() } self.treeview.reply = reply super().accept() def reject(self) -> None: self.treeview.reply = {'accepted': False} super().reject() def select_directory(self): """Select directory""" basedir = to_text_string(self.wd_edit.text()) if not os.path.isdir(basedir): basedir = getcwd_or_home() directory = getexistingdirectory(self, _("Select directory"), basedir) if directory: self.wd_edit.setText(directory)
def populate_gui(self): _contain_parsed = self.contain_parsed for _row, _entry in enumerate(_contain_parsed): if _entry == ['']: continue self.parent.ui.table.insertRow(_row) # select _layout = QHBoxLayout() _widget = QCheckBox() _widget.setEnabled(True) _layout.addWidget(_widget) _layout.addStretch() _new_widget = QWidget() _new_widget.setLayout(_layout) _widget.stateChanged.connect( lambda state=0, row=_row: self.parent. table_select_state_changed(state, row)) self.parent.ui.table.setCellWidget(_row, 0, _new_widget) # name _item = QTableWidgetItem(_entry[1]) self.parent.ui.table.setItem(_row, 1, _item) # runs _item = QTableWidgetItem(_entry[2]) self.parent.ui.table.setItem(_row, 2, _item) # Sample formula if _entry[3]: _item = QTableWidgetItem(_entry[3]) else: _item = QTableWidgetItem("") self.parent.ui.table.setItem(_row, 3, _item) # mass density if _entry[4]: _item = QTableWidgetItem(_entry[4]) else: _item = QTableWidgetItem("") self.parent.ui.table.setItem(_row, 4, _item) # radius if _entry[5]: _item = QTableWidgetItem(_entry[5]) else: _item = QTableWidgetItem("") self.parent.ui.table.setItem(_row, 5, _item) # packing fraction if _entry[6]: _item = QTableWidgetItem(_entry[6]) else: _item = QTableWidgetItem("") self.parent.ui.table.setItem(_row, 6, _item) # sample shape _widget = QComboBox() _widget.addItem("cylindrical") _widget.addItem("spherical") if _entry[7] == "spherical": _widget.setCurrentIndex(1) self.parent.ui.table.setCellWidget(_row, 7, _widget) # do abs corr _layout = QHBoxLayout() _widget = QCheckBox() if _entry[8] == "True": _widget.setCheckState(Qt.Checked) _widget.setStyleSheet("border: 2px; solid-black") _widget.setEnabled(True) _layout.addStretch() _layout.addWidget(_widget) _layout.addStretch() _new_widget = QWidget() _new_widget.setLayout(_layout) self.parent.ui.table.setCellWidget(_row, 8, _new_widget) for _row, _entry in enumerate(_contain_parsed): if _entry == ['']: continue # select _widget = self.parent.ui.table.cellWidget(_row, 0).children()[1] if _entry[0] == "True": _widget.setChecked(True)
class WndLoadQuantitativeCalibration(SecondaryWindow): signal_quantitative_calibration_changed = Signal() def __init__(self, *, gpc, gui_vars): super().__init__() # Global processing classes self.gpc = gpc # Global GUI variables (used for control of GUI state) self.gui_vars = gui_vars self.initialize() def initialize(self): self.table_header_display_names = False self.setWindowTitle("PyXRF: Load Quantitative Calibration") self.setMinimumWidth(750) self.setMinimumHeight(400) self.resize(750, 600) self.pb_load_calib = QPushButton("Load Calibration ...") self.pb_load_calib.clicked.connect(self.pb_load_calib_clicked) self._changes_exist = False self._auto_update = True self.cb_auto_update = QCheckBox("Auto") self.cb_auto_update.setCheckState( Qt.Checked if self._auto_update else Qt.Unchecked) self.cb_auto_update.stateChanged.connect( self.cb_auto_update_state_changed) self.pb_update_plots = QPushButton("Update Plots") self.pb_update_plots.clicked.connect(self.pb_update_plots_clicked) self.grp_current_scan = QGroupBox( "Parameters of Currently Processed Scan") self._distance_to_sample = 0.0 self.le_distance_to_sample = LineEditExtended() le_dist_validator = QDoubleValidator() le_dist_validator.setBottom(0) self.le_distance_to_sample.setValidator(le_dist_validator) self._set_distance_to_sample() self.le_distance_to_sample.editingFinished.connect( self.le_distance_to_sample_editing_finished) self.le_distance_to_sample.focusOut.connect( self.le_distance_to_sample_focus_out) hbox = QHBoxLayout() hbox.addWidget(QLabel("Distance-to-sample:")) hbox.addWidget(self.le_distance_to_sample) hbox.addStretch(1) self.grp_current_scan.setLayout(hbox) self.eline_rb_exclusive = [ ] # Holds the list of groups of exclusive radio buttons self._setup_tab_widget() vbox = QVBoxLayout() hbox = QHBoxLayout() hbox.addWidget(self.pb_load_calib) hbox.addStretch(1) hbox.addWidget(self.cb_auto_update) hbox.addWidget(self.pb_update_plots) vbox.addLayout(hbox) vbox.addWidget(self.tab_widget) vbox.addWidget(self.grp_current_scan) self.setLayout(vbox) # Display data self.update_all_data() self._set_tooltips() def _setup_tab_widget(self): self.tab_widget = QTabWidget() self.loaded_standards = QWidget() # self.display_loaded_standards() self.scroll = QScrollArea() self.scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.scroll.setWidget(self.loaded_standards) self.tab_widget.addTab(self.scroll, "Loaded Standards") self.combo_set_table_header = QComboBox() self.combo_set_table_header.addItems( ["Standard Serial #", "Standard Name"]) self.combo_set_table_header.currentIndexChanged.connect( self.combo_set_table_header_index_changed) vbox = QVBoxLayout() vbox.addSpacing(5) hbox = QHBoxLayout() hbox.addWidget(QLabel("Display in table header:")) hbox.addWidget(self.combo_set_table_header) hbox.addStretch(1) vbox.addLayout(hbox) self.table = QTableWidget() self.table.verticalHeader().hide() self.table.setSelectionMode(QTableWidget.NoSelection) self.table.horizontalHeader().setSectionResizeMode( QHeaderView.ResizeToContents) self.table.horizontalHeader().setMinimumSectionSize(150) vbox.addWidget(self.table) self.table.setStyleSheet("QTableWidget::item{color: black;}") frame = QFrame() vbox.setContentsMargins(0, 0, 0, 0) frame.setLayout(vbox) self.tab_widget.addTab(frame, "Selected Emission Lines") def display_loaded_standards(self): calib_data = self.gpc.get_quant_calibration_data() calib_settings = self.gpc.get_quant_calibration_settings() # Create the new widget (this deletes the old widget) self.loaded_standards = QWidget() self.loaded_standards.setMinimumWidth(700) # Also delete references to all components self.frames_calib_data = [] self.pbs_view = [] self.pbs_remove = [] # All 'View' buttons are added to the group in order to be connected to the same slot self.group_view = QButtonGroup() self.group_view.setExclusive(False) self.group_view.buttonClicked.connect(self.pb_view_clicked) # The same for the 'Remove' buttons self.group_remove = QButtonGroup() self.group_remove.setExclusive(False) self.group_remove.buttonClicked.connect(self.pb_remove_clicked) vbox = QVBoxLayout() class _LabelBlack(QLabel): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.setStyleSheet("color: black") for cdata, csettings in zip(calib_data, calib_settings): frame = QFrame() frame.setFrameStyle(QFrame.StyledPanel) frame.setStyleSheet( get_background_css((200, 255, 200), widget="QFrame")) _vbox = QVBoxLayout() name = cdata["name"] # Standard name (can be arbitrary string # If name is long, then print it in a separate line _name_is_long = len(name) > 30 pb_view = QPushButton("View ...") self.group_view.addButton(pb_view) pb_remove = QPushButton("Remove") self.group_remove.addButton(pb_remove) # Row 1: serial, name serial = cdata["serial"] _hbox = QHBoxLayout() _hbox.addWidget(_LabelBlack(f"<b>Standard</b> #{serial}")) if not _name_is_long: _hbox.addWidget(_LabelBlack(f"'{name}'")) _hbox.addStretch(1) _hbox.addWidget(pb_view) _hbox.addWidget(pb_remove) _vbox.addLayout(_hbox) # Optional row if _name_is_long: # Wrap name if it is extemely long name = textwrap.fill(name, width=80) _hbox = QHBoxLayout() _hbox.addWidget(_LabelBlack("<b>Name:</b> "), 0, Qt.AlignTop) _hbox.addWidget(_LabelBlack(name), 0, Qt.AlignTop) _hbox.addStretch(1) _vbox.addLayout(_hbox) # Row 2: description description = textwrap.fill(cdata["description"], width=80) _hbox = QHBoxLayout() _hbox.addWidget(_LabelBlack("<b>Description:</b>"), 0, Qt.AlignTop) _hbox.addWidget(_LabelBlack(f"{description}"), 0, Qt.AlignTop) _hbox.addStretch(1) _vbox.addLayout(_hbox) # Row 3: incident_energy = cdata["incident_energy"] scaler = cdata["scaler_name"] detector_channel = cdata["detector_channel"] distance_to_sample = cdata["distance_to_sample"] _hbox = QHBoxLayout() _hbox.addWidget( _LabelBlack(f"<b>Incident energy, keV:</b> {incident_energy}")) _hbox.addWidget(_LabelBlack(f" <b>Scaler:</b> {scaler}")) _hbox.addWidget( _LabelBlack(f" <b>Detector channel:</b> {detector_channel}")) _hbox.addWidget( _LabelBlack( f" <b>Distance-to-sample:</b> {distance_to_sample}")) _hbox.addStretch(1) _vbox.addLayout(_hbox) # Row 4: file name fln = textwrap.fill(csettings["file_path"], width=80) _hbox = QHBoxLayout() _hbox.addWidget(_LabelBlack("<b>Source file:</b>"), 0, Qt.AlignTop) _hbox.addWidget(_LabelBlack(fln), 0, Qt.AlignTop) _hbox.addStretch(1) _vbox.addLayout(_hbox) frame.setLayout(_vbox) # Now the group box is added to the upper level layout vbox.addWidget(frame) vbox.addSpacing(5) self.frames_calib_data.append(frame) self.pbs_view.append(pb_view) self.pbs_remove.append(pb_remove) # Add the layout to the widget self.loaded_standards.setLayout(vbox) # ... and put the widget inside the scroll area. This will update the # contents of the scroll area. self.scroll.setWidget(self.loaded_standards) def display_table_header(self): calib_data = self.gpc.get_quant_calibration_data() header_by_name = self.table_header_display_names tbl_labels = ["Lines"] for n, cdata in enumerate(calib_data): if header_by_name: txt = cdata["name"] else: txt = cdata["serial"] txt = textwrap.fill(txt, width=20) tbl_labels.append(txt) self.table.setHorizontalHeaderLabels(tbl_labels) def display_standard_selection_table(self): calib_data = self.gpc.get_quant_calibration_data() self._quant_file_paths = self.gpc.get_quant_calibration_file_path_list( ) brightness = 220 table_colors = [(255, brightness, brightness), (brightness, 255, brightness)] # Disconnect all radio button signals before clearing the table for bgroup in self.eline_rb_exclusive: bgroup.buttonToggled.disconnect(self.rb_selection_toggled) # This list will hold radio button groups for horizontal rows # Those are exclusive groups. They are not going to be # used directly, but they must be kept alive in order # for the radiobuttons to work properly. Most of the groups # will contain only 1 radiobutton, which will always remain checked. self.eline_rb_exclusive = [] # The following list will contain the list of radio buttons for each # row. If there is no radiobutton in a position, then the element is # set to None. # N rows: the number of emission lines, N cols: the number of standards self.eline_rb_lists = [] self.table.clear() if not calib_data: self.table.setRowCount(0) self.table.setColumnCount(0) else: # Create the sorted list of available element lines line_set = set() for cdata in calib_data: ks = list(cdata["element_lines"].keys()) line_set.update(list(ks)) self.eline_list = list(line_set) self.eline_list.sort() for n in range(len(self.eline_list)): self.eline_rb_exclusive.append(QButtonGroup()) self.eline_rb_lists.append([None] * len(calib_data)) self.table.setColumnCount(len(calib_data) + 1) self.table.setRowCount(len(self.eline_list)) self.display_table_header() for n, eline in enumerate(self.eline_list): rgb = table_colors[n % 2] item = QTableWidgetItem(eline) item.setTextAlignment(Qt.AlignCenter) item.setFlags(item.flags() & ~Qt.ItemIsEditable) item.setBackground(QBrush(QColor(*rgb))) self.table.setItem(n, 0, item) for ns, cdata in enumerate(calib_data): q_file_path = self._quant_file_paths[ ns] # Used to identify standard if eline in cdata["element_lines"]: rb = QRadioButton() if self.gpc.get_quant_calibration_is_eline_selected( eline, q_file_path): rb.setChecked(True) rb.setStyleSheet("color: black") self.eline_rb_lists[n][ns] = rb # self.eline_rb_by_standard[ns].addButton(rb) self.eline_rb_exclusive[n].addButton(rb) item = QWidget() item_hbox = QHBoxLayout(item) item_hbox.addWidget(rb) item_hbox.setAlignment(Qt.AlignCenter) item_hbox.setContentsMargins(0, 0, 0, 0) item.setStyleSheet(get_background_css(rgb)) # Generate tooltip density = cdata["element_lines"][eline]["density"] fluorescence = cdata["element_lines"][eline][ "fluorescence"] ttip = f"Fluorescence (F): {fluorescence:12g}\nDensity (D): {density:12g}\n" # Avoid very small values of density (probably zero) if abs(density) > 1e-30: ttip += f"F/D: {fluorescence/density:12g}" item.setToolTip(ttip) self.table.setCellWidget(n, ns + 1, item) else: # There is no radio button, but we still need to fill the cell item = QTableWidgetItem("") item.setFlags(item.flags() & ~Qt.ItemIsEditable) item.setBackground(QBrush(QColor(*rgb))) self.table.setItem(n, ns + 1, item) # Now the table is set (specifically radio buttons). # So we can connect the button groups with the event processing function for bgroup in self.eline_rb_exclusive: bgroup.buttonToggled.connect(self.rb_selection_toggled) @Slot() def update_all_data(self): self.display_loaded_standards() self.display_standard_selection_table() self._set_distance_to_sample() def _set_distance_to_sample(self): """Set 'le_distance_to_sample` without updating maps""" distance_to_sample = self.gpc.get_quant_calibration_distance_to_sample( ) if distance_to_sample is None: distance_to_sample = 0.0 self._distance_to_sample = distance_to_sample self._set_le_distance_to_sample(distance_to_sample) def _set_tooltips(self): set_tooltip(self.pb_load_calib, "Load <b>calibration data</b> from JSON file.") set_tooltip( self.cb_auto_update, "Automatically <b>update the plots</b> when changes are made. " "If unchecked, then button <b>Update Plots</b> must be pressed " "to update the plots. Automatic update is often undesirable " "when large maps are displayed and multiple changes to parameters " "are made.", ) set_tooltip( self.pb_update_plots, "<b>Update plots</b> based on currently selected parameters.") set_tooltip( self.le_distance_to_sample, "Distance between <b>the sample and the detector</b>. The ratio between of the distances " "during calibration and measurement is used to scale computed concentrations. " "If distance-to-sample is 0 for calibration or measurement, then no scaling is performed.", ) set_tooltip( self.combo_set_table_header, "Use <b>Serial Number</b> or <b>Name</b> of the calibration standard in the header of the table", ) set_tooltip( self.table, "Use Radio Buttons to select the <b>source of calibration data</b> for each emission line. " "This feature is needed if multiple loaded calibration files have data on the same " "emission line.", ) def update_widget_state(self, condition=None): # Update the state of the menu bar state = not self.gui_vars["gui_state"]["running_computations"] self.setEnabled(state) # Hide the window if required by the program state state_xrf_map_exists = self.gui_vars["gui_state"][ "state_xrf_map_exists"] if not state_xrf_map_exists: self.hide() if condition == "tooltips": self._set_tooltips() def cb_auto_update_state_changed(self, state): self._auto_update = state self.pb_update_plots.setEnabled(not state) # If changes were made, apply the changes while switching to 'auto' mode if state and self._changes_exist: self._update_maps_auto() def pb_update_plots_clicked(self): self._update_maps() def pb_load_calib_clicked(self): current_dir = self.gpc.get_current_working_directory() file_name = QFileDialog.getOpenFileName( self, "Select File with Quantitative Calibration Data", current_dir, "JSON (*.json);; All (*)") file_name = file_name[0] if file_name: try: logger.debug( f"Loading quantitative calibration from file: '{file_name}'" ) self.gpc.load_quantitative_calibration_data(file_name) self.update_all_data() self._update_maps_auto() except Exception: msg = "The selected JSON file has incorrect format. Select a different file." msgbox = QMessageBox(QMessageBox.Critical, "Data Loading Error", msg, QMessageBox.Ok, parent=self) msgbox.exec() def pb_view_clicked(self, button): try: n_standard = self.pbs_view.index(button) calib_settings = self.gpc.get_quant_calibration_settings() file_path = calib_settings[n_standard]["file_path"] calib_preview = self.gpc.get_quant_calibration_text_preview( file_path) dlg = DialogViewCalibStandard(None, file_path=file_path, calib_preview=calib_preview) dlg.exec() except ValueError: logger.error( "'View' button was pressed, but not found in the list of buttons" ) def pb_remove_clicked(self, button): try: n_standard = self.pbs_remove.index(button) calib_settings = self.gpc.get_quant_calibration_settings() file_path = calib_settings[n_standard]["file_path"] self.gpc.quant_calibration_remove_entry(file_path) self.update_all_data() self._update_maps_auto() except ValueError: logger.error( "'Remove' button was pressed, but not found in the list of buttons" ) def rb_selection_toggled(self, button, checked): if checked: # Find the button in 2D list 'self.eline_rb_lists' button_found = False for nr, rb_list in enumerate(self.eline_rb_lists): try: nc = rb_list.index(button) button_found = True break except ValueError: pass if button_found: eline = self.eline_list[nr] n_standard = nc file_path = self._quant_file_paths[n_standard] self.gpc.set_quant_calibration_select_eline(eline, file_path) self._update_maps_auto() else: # This should never happen logger.error( "Selection radio button was pressed, but not found in the list" ) def combo_set_table_header_index_changed(self, index): self.table_header_display_names = bool(index) self.display_table_header() def le_distance_to_sample_editing_finished(self): distance_to_sample = float(self.le_distance_to_sample.text()) if distance_to_sample != self._distance_to_sample: self._distance_to_sample = distance_to_sample self.gpc.set_quant_calibration_distance_to_sample( distance_to_sample) self._update_maps_auto() def le_distance_to_sample_focus_out(self): try: float(self.le_distance_to_sample.text()) except ValueError: # If the text can not be interpreted to float, then replace the text with the old value self._set_le_distance_to_sample(self._distance_to_sample) def _set_le_distance_to_sample(self, distance_to_sample): self.le_distance_to_sample.setText(f"{distance_to_sample:.12g}") def _update_maps_auto(self): """Update maps only if 'auto' update is ON. Used as a 'filter' to prevent extra plot updates.""" self._changes_exist = True if self._auto_update: self._update_maps() def _update_maps(self): """Upload the selections (limit table) and update plot""" self._changes_exist = False self._redraw_maps() # Emit signal only after the maps are redrawn. This should change # ranges in the respective controls for the plots self.signal_quantitative_calibration_changed.emit() def _redraw_maps(self): # We don't emit any signals here, but we don't really need to. logger.debug("Redrawing RGB XRF Maps") self.gpc.compute_map_ranges() self.gpc.redraw_maps() self.gpc.compute_rgb_map_ranges() self.gpc.redraw_rgb_maps()
def populate_gui(self): _contain_parsed = self.contain_parsed for _row, _entry in enumerate(_contain_parsed): if _entry == ['']: continue self.parent.ui.table.insertRow(_row) # select _layout = QHBoxLayout() _widget = QCheckBox() _widget.setEnabled(True) _layout.addWidget(_widget) _layout.addStretch() _new_widget = QWidget() _new_widget.setLayout(_layout) _widget.stateChanged.connect(lambda state=0, row=_row: self.parent.table_select_state_changed(state, row)) self.parent.ui.table.setCellWidget(_row, 0, _new_widget) # name _item = QTableWidgetItem(_entry[1]) self.parent.ui.table.setItem(_row, 1, _item) # runs _item = QTableWidgetItem(_entry[2]) self.parent.ui.table.setItem(_row, 2, _item) # Sample formula if _entry[3]: _item = QTableWidgetItem(_entry[3]) else: _item = QTableWidgetItem("") self.parent.ui.table.setItem(_row, 3, _item) # mass density if _entry[4]: _item = QTableWidgetItem(_entry[4]) else: _item = QTableWidgetItem("") self.parent.ui.table.setItem(_row, 4, _item) # radius if _entry[5]: _item = QTableWidgetItem(_entry[5]) else: _item = QTableWidgetItem("") self.parent.ui.table.setItem(_row, 5, _item) # packing fraction if _entry[6]: _item = QTableWidgetItem(_entry[6]) else: _item = QTableWidgetItem("") self.parent.ui.table.setItem(_row, 6, _item) # sample shape _widget = QComboBox() _widget.addItem("cylindrical") _widget.addItem("spherical") if _entry[7] == "spherical": _widget.setCurrentIndex(1) self.parent.ui.table.setCellWidget(_row, 7, _widget) # do abs corr _layout = QHBoxLayout() _widget = QCheckBox() if _entry[8] == "True": _widget.setCheckState(Qt.Checked) _widget.setStyleSheet("border: 2px; solid-black") _widget.setEnabled(True) _layout.addStretch() _layout.addWidget(_widget) _layout.addStretch() _new_widget = QWidget() _new_widget.setLayout(_layout) self.parent.ui.table.setCellWidget(_row, 8, _new_widget) for _row, _entry in enumerate(_contain_parsed): if _entry == ['']: continue # select _widget = self.parent.ui.table.cellWidget(_row, 0).children()[1] if _entry[0] == "True": _widget.setChecked(True)
def insert_row(self, row=-1, title='', sample_runs='', sample_mass_density='N/A', sample_chemical_formula='N/A', packing_fraction='N/A', align_and_focus_args={}, sample_placzek_arguments={}, normalization_placzek_arguments={}): self.table_ui.insertRow(row) self.set_row_height(row, COLUMN_DEFAULT_HEIGHT) _list_ui_to_unlock = [self.table_ui] _dimension_widgets = {'label': None, 'value': 'N/A', 'units': None} _full_dimension_widgets = {'radius': copy.deepcopy(_dimension_widgets), 'radius2': copy.deepcopy(_dimension_widgets), 'height': copy.deepcopy(_dimension_widgets)} _text_button = {'text': None, 'button': None} _mass_density_options = {'value': "N/A", "selected": False} _mass_density_infos = {'number_density': copy.deepcopy(_mass_density_options), 'mass_density': copy.deepcopy(_mass_density_options), 'mass': copy.deepcopy(_mass_density_options), 'molecular_mass': np.NaN, 'total_number_of_atoms': np.NaN, } _material_infos = {'mantid_format': None, 'addie_format': None} _mass_density_infos['mass_density']["selected"] = True _master_table_row_ui = {'active': None, 'title': None, 'sample': {'runs': None, 'background': {'runs': None, 'background': None, }, 'material': copy.deepcopy(_text_button), 'material_infos': copy.deepcopy(_material_infos), 'mass_density': copy.deepcopy(_text_button), 'mass_density_infos': copy.deepcopy(_mass_density_infos), 'packing_fraction': None, 'geometry': copy.deepcopy(_full_dimension_widgets), 'shape': None, 'abs_correction': None, 'mult_scat_correction': None, 'inelastic_correction': None, 'placzek_button': None, 'placzek_infos': None, }, 'normalization': {'runs': None, 'background': {'runs': None, 'background': None, }, 'material': copy.deepcopy(_text_button), 'material_infos': copy.deepcopy(_material_infos), 'mass_density': copy.deepcopy(_text_button), 'mass_density_infos': copy.deepcopy(_mass_density_infos), 'packing_fraction': None, 'geometry': copy.deepcopy(_full_dimension_widgets), 'shape': None, 'abs_correction': None, 'mult_scat_correction': None, 'inelastic_correction': None, 'placzek_button': None, 'placzek_infos': None, }, 'align_and_focus_args_button': None, 'align_and_focus_args_infos': {}, } random_key = self.generate_random_key() self.key = random_key # block main table events self.table_ui.blockSignals(True) # column 0 (active or not checkBox) _layout = QHBoxLayout() _widget = QCheckBox() _widget.setCheckState(QtCore.Qt.Checked) _widget.setEnabled(True) _master_table_row_ui['active'] = _widget _spacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) _layout.addItem(_spacer) _layout.addWidget(_widget) _spacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) _layout.addItem(_spacer) _layout.addStretch() _new_widget = QWidget() _new_widget.setLayout(_layout) _widget.stateChanged.connect(lambda state=0, key=random_key: self.main_window.master_table_select_state_changed(state, key)) column = 0 self.table_ui.setCellWidget(row, column, _new_widget) # sample column += 1 # column 1 - title _item = QTableWidgetItem(title) _master_table_row_ui['title'] = _item self.table_ui.setItem(row, column, _item) # column 2 - sample runs column += 1 _item = QTableWidgetItem(sample_runs) _master_table_row_ui['sample']['runs'] = _item self.table_ui.setItem(row, column, _item) # column 3 - background runs column += 1 _item = QTableWidgetItem("") _master_table_row_ui['sample']['background']['runs'] = _item self.table_ui.setItem(row, column, _item) # column 4 - background background column += 1 _item = QTableWidgetItem("") _master_table_row_ui['sample']['background']['background'] = _item self.table_ui.setItem(row, column, _item) # column 5 - material (chemical formula) column += 1 clean_sample_chemical_formula = format_chemical_formula_equation(sample_chemical_formula) _material_text = QLineEdit(clean_sample_chemical_formula) _material_text = QLabel(clean_sample_chemical_formula) _material_button = QPushButton("...") _material_button.setFixedHeight(CONFIG_BUTTON_HEIGHT) _material_button.setFixedWidth(CONFIG_BUTTON_WIDTH) _material_button.pressed.connect(lambda key=random_key: self.main_window.master_table_sample_material_button_pressed(key)) _verti_layout = QVBoxLayout() _verti_layout.addWidget(_material_text) _verti_layout.addWidget(_material_button) _material_widget = QWidget() _material_widget.setLayout(_verti_layout) self.table_ui.setCellWidget(row, column, _material_widget) _master_table_row_ui['sample']['material']['text'] = _material_text _master_table_row_ui['sample']['material']['button'] = _material_button # column 6 - mass density column += 1 _mass_text = QLineEdit(sample_mass_density) _mass_text.returnPressed.connect(lambda key=random_key: self.main_window.master_table_sample_mass_density_line_edit_entered(key)) _mass_units = QLabel("g/cc") _top_widget = QWidget() _top_layout = QHBoxLayout() _top_layout.addWidget(_mass_text) _top_layout.addWidget(_mass_units) _top_widget.setLayout(_top_layout) _mass_button = QPushButton("...") _mass_button.setFixedHeight(CONFIG_BUTTON_HEIGHT) _mass_button.setFixedWidth(CONFIG_BUTTON_WIDTH) _mass_button.pressed.connect(lambda key=random_key: self.main_window.master_table_sample_mass_density_button_pressed(key)) _verti_layout = QVBoxLayout() _verti_layout.addWidget(_top_widget) _verti_layout.addWidget(_mass_button) _mass_widget = QWidget() _mass_widget.setLayout(_verti_layout) self.table_ui.setCellWidget(row, column, _mass_widget) _master_table_row_ui['sample']['mass_density']['text'] = _mass_text _master_table_row_ui['sample']['mass_density']['button'] = _mass_button # column 7 - packing fraction column += 1 if packing_fraction == "N/A": packing_fraction = "{}".format(self.main_window.packing_fraction) _item = QTableWidgetItem(packing_fraction) _master_table_row_ui['sample']['packing_fraction'] = _item self.table_ui.setItem(row, column, _item) # column 8 - shape (cylindrical or spherical) column += 1 _layout = QHBoxLayout() _layout.setContentsMargins(0, 0, 0, 0) _widget = QComboBox() _shape_default_index = 0 _widget.currentIndexChanged.connect(lambda index=_shape_default_index, key=random_key: self.main_window.master_table_sample_shape_changed(index, key)) _list_ui_to_unlock.append(_widget) _widget.blockSignals(True) _widget.addItem("cylindrical") _widget.addItem("spherical") _widget.addItem("hollow cylinder") _master_table_row_ui['sample']['shape'] = _widget _layout.addWidget(_widget) _w = QWidget() _w.setLayout(_layout) self.table_ui.setCellWidget(row, column, _w) # column 9 - dimensions column += 1 # layout 1 _grid_layout = QGridLayout() _label1 = QLabel("Radius:") _grid_layout.addWidget(_label1, 1, 0) _value1 = QLabel("N/A") _grid_layout.addWidget(_value1, 1, 1) _dim1 = QLabel("cm") _grid_layout.addWidget(_dim1, 1, 2) _label2 = QLabel("Radius:") _label2.setVisible(False) _grid_layout.addWidget(_label2, 2, 0) _value2 = QLabel("N/A") _value2.setVisible(False) _grid_layout.addWidget(_value2, 2, 1) _dim2 = QLabel("cm") _dim2.setVisible(False) _grid_layout.addWidget(_dim2, 2, 2) _label3 = QLabel("Height:") _grid_layout.addWidget(_label3, 3, 0) _value3 = QLabel("N/A") _grid_layout.addWidget(_value3, 3, 1) _dim3 = QLabel("cm") _grid_layout.addWidget(_dim3, 3, 2) _master_table_row_ui['sample']['geometry']['radius']['value'] = _value1 _master_table_row_ui['sample']['geometry']['radius2']['value'] = _value2 _master_table_row_ui['sample']['geometry']['height']['value'] = _value3 _master_table_row_ui['sample']['geometry']['radius']['label'] = _label1 _master_table_row_ui['sample']['geometry']['radius2']['label'] = _label2 _master_table_row_ui['sample']['geometry']['height']['label'] = _label3 _master_table_row_ui['sample']['geometry']['radius']['units'] = _dim1 _master_table_row_ui['sample']['geometry']['radius2']['units'] = _dim2 _master_table_row_ui['sample']['geometry']['height']['units'] = _dim3 _geometry_widget = QWidget() _geometry_widget.setLayout(_grid_layout) _set_dimensions_button = QPushButton("...") _set_dimensions_button.setFixedHeight(CONFIG_BUTTON_HEIGHT) _set_dimensions_button.setFixedWidth(CONFIG_BUTTON_WIDTH) _verti_layout = QVBoxLayout() _verti_layout.addWidget(_geometry_widget) _verti_layout.addWidget(_set_dimensions_button) _verti_widget = QWidget() _verti_widget.setLayout(_verti_layout) _set_dimensions_button.pressed.connect(lambda key=random_key: self.main_window.master_table_sample_dimensions_setter_button_pressed(key)) self.table_ui.setCellWidget(row, column, _verti_widget) # column 10 - abs. correction column += 1 _layout = QHBoxLayout() _layout.setContentsMargins(0, 0, 0, 0) _widget = QComboBox() _shape_default_value = 0 list_abs_correction = self.get_absorption_correction_list(shape=_shape_default_value) _widget.currentIndexChanged.connect(lambda value=list_abs_correction[0], key = random_key: self.main_window.master_table_sample_abs_correction_changed(value, key)) _widget.blockSignals(True) _list_ui_to_unlock.append(_widget) for _item in list_abs_correction: _widget.addItem(_item) _master_table_row_ui['sample']['abs_correction'] = _widget _layout.addWidget(_widget) _w = QWidget() _w.setLayout(_layout) self.table_ui.setCellWidget(row, column, _w) # column 11 - multi. scattering correction column += 1 _layout = QHBoxLayout() _layout.setContentsMargins(0, 0, 0, 0) _widget = QComboBox() list_multi_scat_correction = self.get_multi_scat_correction_list(shape=_shape_default_value) _widget.currentIndexChanged.connect(lambda value=list_multi_scat_correction[0], key=random_key: self.main_window.master_table_sample_multi_scattering_correction_changed(value, key)) _widget.blockSignals(True) _list_ui_to_unlock.append(_widget) for _item in list_multi_scat_correction: _widget.addItem(_item) _master_table_row_ui['sample']['mult_scat_correction'] = _widget _layout.addWidget(_widget) _w = QWidget() _w.setLayout(_layout) self.table_ui.setCellWidget(row, column, _w) # column 12 - inelastic correction column += 1 _layout = QHBoxLayout() _layout.setContentsMargins(0, 0, 0, 0) _widget1 = QComboBox() _widget1.setMinimumHeight(20) list_inelastic_correction = self.get_inelastic_scattering_list(shape=_shape_default_value) for _item in list_inelastic_correction: _widget1.addItem(_item) _master_table_row_ui['sample']['inelastic_correction'] = _widget1 _button = QPushButton("...") _button.setFixedHeight(CONFIG_BUTTON_HEIGHT) _button.setFixedWidth(CONFIG_BUTTON_WIDTH) _button.pressed.connect(lambda key=random_key: self.main_window.master_table_sample_placzek_button_pressed(key)) _master_table_row_ui['sample']['placzek_button'] = _button _button.setVisible(False) _master_table_row_ui['sample']['placzek_button'] = _button _layout.addWidget(_widget1) _layout.addWidget(_button) _widget = QWidget() _widget.setLayout(_layout) _default_value = 'None' _widget1.currentIndexChanged.connect(lambda value=_default_value, key=random_key: self.main_window.master_table_sample_inelastic_correction_changed(value, key)) _widget.blockSignals(True) _list_ui_to_unlock.append(_widget) self.table_ui.setCellWidget(row, column, _widget) # save default placzek settings _sample_formated_placzek_default = self.formated_placzek_default(sample_placzek_arguments) _master_table_row_ui['sample']['placzek_infos'] = _sample_formated_placzek_default ## normalization # column 13 - sample runs column += 1 _item = QTableWidgetItem("") self.table_ui.setItem(row, column, _item) # column 14 - background runs column += 1 _item = QTableWidgetItem("") self.table_ui.setItem(row, column, _item) # column 15 - background background column += 1 _item = QTableWidgetItem("") self.table_ui.setItem(row, column, _item) # column 16 - material (chemical formula) column += 1 #_material_text = QLineEdit("") _material_text = QLabel("N/A") _material_button = QPushButton("...") _material_button.setFixedHeight(CONFIG_BUTTON_HEIGHT) _material_button.setFixedWidth(CONFIG_BUTTON_WIDTH) _material_button.pressed.connect(lambda key=random_key: self.main_window.master_table_normalization_material_button_pressed(key)) _verti_layout = QVBoxLayout() _verti_layout.addWidget(_material_text) _verti_layout.addWidget(_material_button) _material_widget = QWidget() _material_widget.setLayout(_verti_layout) self.table_ui.setCellWidget(row, column, _material_widget) _master_table_row_ui['normalization']['material']['text'] = _material_text _master_table_row_ui['normalization']['material']['button'] = _material_button # column 17 - mass density column += 1 _mass_text = QLineEdit("N/A") _mass_text.returnPressed.connect(lambda key=random_key: self.main_window.master_table_normalization_mass_density_line_edit_entered(key)) _mass_units = QLabel("g/cc") _top_widget = QWidget() _top_layout = QHBoxLayout() _top_layout.addWidget(_mass_text) _top_layout.addWidget(_mass_units) _top_widget.setLayout(_top_layout) _mass_button = QPushButton("...") _mass_button.setFixedWidth(CONFIG_BUTTON_WIDTH) _mass_button.setFixedHeight(CONFIG_BUTTON_HEIGHT) _mass_button.pressed.connect(lambda key=random_key: self.main_window.master_table_normalization_mass_density_button_pressed(key)) _verti_layout = QVBoxLayout() _verti_layout.addWidget(_top_widget) _verti_layout.addWidget(_mass_button) _mass_widget = QWidget() _mass_widget.setLayout(_verti_layout) self.table_ui.setCellWidget(row, column, _mass_widget) _master_table_row_ui['normalization']['mass_density']['text'] = _mass_text _master_table_row_ui['normalization']['mass_density']['button'] = _mass_button # column 18 - packing fraction column += 1 _item = QTableWidgetItem("") self.table_ui.setItem(row, column, _item) # column 19 - shape (cylindrical or spherical) column += 1 _layout = QHBoxLayout() _layout.setContentsMargins(0, 0, 0, 0) _widget = QComboBox() _widget.currentIndexChanged.connect(lambda value=_shape_default_value, key=random_key: self.main_window.master_table_normalization_shape_changed(value, key)) _widget.blockSignals(True) _list_ui_to_unlock.append(_widget) _widget.addItem("cylindrical") _widget.addItem("spherical") _widget.addItem("hollow cylinder") _master_table_row_ui['normalization']['shape'] = _widget _layout.addWidget(_widget) _w = QWidget() _w.setLayout(_layout) self.table_ui.setCellWidget(row, column, _w) # column 20 - dimensions column += 1 # layout 1 _grid_layout = QGridLayout() _label1 = QLabel("Radius:") _grid_layout.addWidget(_label1, 1, 0) _value1 = QLabel("N/A") _grid_layout.addWidget(_value1, 1, 1) _dim1 = QLabel("cm") _grid_layout.addWidget(_dim1, 1, 2) _label2 = QLabel("Radius:") _label2.setVisible(False) _grid_layout.addWidget(_label2, 2, 0) _value2 = QLabel("N/A") _value2.setVisible(False) _grid_layout.addWidget(_value2, 2, 1) _dim2 = QLabel("cm") _dim2.setVisible(False) _grid_layout.addWidget(_dim2, 2, 2) _label3 = QLabel("Height:") _grid_layout.addWidget(_label3, 3, 0) _value3 = QLabel("N/A") _grid_layout.addWidget(_value3, 3, 1) _dim3 = QLabel("cm") _grid_layout.addWidget(_dim3, 3, 2) _master_table_row_ui['normalization']['geometry']['radius']['value'] = _value1 _master_table_row_ui['normalization']['geometry']['radius2']['value'] = _value2 _master_table_row_ui['normalization']['geometry']['height']['value'] = _value3 _master_table_row_ui['normalization']['geometry']['radius']['label'] = _label1 _master_table_row_ui['normalization']['geometry']['radius2']['label'] = _label2 _master_table_row_ui['normalization']['geometry']['height']['label'] = _label3 _master_table_row_ui['normalization']['geometry']['radius']['units'] = _dim1 _master_table_row_ui['normalization']['geometry']['radius2']['units'] = _dim2 _master_table_row_ui['normalization']['geometry']['height']['units'] = _dim3 _geometry_widget = QWidget() _geometry_widget.setLayout(_grid_layout) _set_dimensions_button = QPushButton("...") _set_dimensions_button.setFixedHeight(CONFIG_BUTTON_HEIGHT) _set_dimensions_button.setFixedWidth(CONFIG_BUTTON_WIDTH) _verti_layout = QVBoxLayout() _verti_layout.addWidget(_geometry_widget) _verti_layout.addWidget(_set_dimensions_button) _verti_widget = QWidget() _verti_widget.setLayout(_verti_layout) _set_dimensions_button.pressed.connect(lambda key=random_key: self.main_window.master_table_normalization_dimensions_setter_button_pressed(key)) # noqa self.table_ui.setCellWidget(row, column, _verti_widget) # column 21 - abs. correction column += 1 _layout = QHBoxLayout() _layout.setContentsMargins(0, 0, 0, 0) _widget = QComboBox() _widget.currentIndexChanged.connect(lambda value=list_abs_correction[0], key=random_key: self.main_window.master_table_normalization_abs_correction_changed(value, key)) # noqa _widget.blockSignals(True) _list_ui_to_unlock.append(_widget) for _item in list_abs_correction: _widget.addItem(_item) _widget.setCurrentIndex(0) _master_table_row_ui['normalization']['abs_correction'] = _widget _layout.addWidget(_widget) _w = QWidget() _w.setLayout(_layout) self.table_ui.setCellWidget(row, column, _w) # column 24 - multi. scattering correction column += 1 _layout = QHBoxLayout() _layout.setContentsMargins(0, 0, 0, 0) _widget = QComboBox() _widget.currentIndexChanged.connect(lambda value=list_multi_scat_correction[0], key=random_key: self.main_window.master_table_normalization_multi_scattering_correction_changed(value, key)) # noqa _widget.blockSignals(True) _list_ui_to_unlock.append(_widget) for _item in list_multi_scat_correction: _widget.addItem(_item) _widget.setCurrentIndex(0) _master_table_row_ui['normalization']['mult_scat_correction'] = _widget _layout.addWidget(_widget) _w = QWidget() _w.setLayout(_layout) self.table_ui.setCellWidget(row, column, _w) # column 22 - inelastic correction column += 1 _layout = QHBoxLayout() _layout.setContentsMargins(0, 0, 0, 0) _widget1 = QComboBox() _widget1.setMinimumHeight(20) list_inelastic_correction = self.get_inelastic_scattering_list(shape=_shape_default_value) for _item in list_inelastic_correction: _widget1.addItem(_item) _widget1.setCurrentIndex(0) _master_table_row_ui['normalization']['inelastic_correction'] = _widget1 _button = QPushButton("...") _button.setFixedWidth(CONFIG_BUTTON_WIDTH) _button.setFixedHeight(CONFIG_BUTTON_HEIGHT) _button.pressed.connect(lambda key=random_key: self.main_window.master_table_normalization_placzek_button_pressed(key)) _master_table_row_ui['normalization']['placzek_button'] = _button _button.setVisible(False) _layout.addWidget(_widget1) _layout.addWidget(_button) _widget = QWidget() _widget.setLayout(_layout) _default_value = 'None' _widget1.currentIndexChanged.connect( lambda value=_default_value, key=random_key: self.main_window.master_table_normalization_inelastic_correction_changed(value, key)) # noqa _widget.blockSignals(True) _list_ui_to_unlock.append(_widget) self.table_ui.setCellWidget(row, column, _widget) # automatically populate placzek infos with default values _norm_formated_placzek_default = self.formated_placzek_default(normalization_placzek_arguments) _master_table_row_ui['normalization']['placzek_infos'] = _norm_formated_placzek_default # column 23 - key/value pair column += 1 _layout = QHBoxLayout() _spacer_kv1 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) _layout.addItem(_spacer_kv1) _button = QPushButton("...") _layout.addWidget(_button) _button.setFixedWidth(CONFIG_BUTTON_WIDTH) _button.setFixedHeight(CONFIG_BUTTON_HEIGHT) _button.pressed.connect(lambda key=random_key: self.main_window.master_table_keyvalue_button_pressed(key)) _new_widget = QWidget() _new_widget.setLayout(_layout) self.table_ui.setCellWidget(row, column, _new_widget) _master_table_row_ui['align_and_focus_args_button'] = _button _spacer_kv2 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) _layout.addItem(_spacer_kv2) _layout.addStretch() _master_table_row_ui['align_and_focus_args_infos'] = align_and_focus_args ## recap self.main_window.master_table_list_ui[random_key] = _master_table_row_ui self.unlock_signals_ui(list_ui=_list_ui_to_unlock) self.main_window.check_status_of_right_click_buttons()
def insert_row(self, row=-1, title='', sample_runs='', sample_mass_density='N/A', sample_chemical_formula='N/A', packing_fraction='N/A', align_and_focus_args={}, sample_placzek_arguments={}, normalization_placzek_arguments={}): self.table_ui.insertRow(row) self.set_row_height(row, COLUMN_DEFAULT_HEIGHT) _list_ui_to_unlock = [self.table_ui] _dimension_widgets = {'label': None, 'value': 'N/A', 'units': None} _full_dimension_widgets = { 'radius': copy.deepcopy(_dimension_widgets), 'radius2': copy.deepcopy(_dimension_widgets), 'height': copy.deepcopy(_dimension_widgets) } _text_button = {'text': None, 'button': None} _mass_density_options = {'value': "N/A", "selected": False} _mass_density_infos = { 'number_density': copy.deepcopy(_mass_density_options), 'mass_density': copy.deepcopy(_mass_density_options), 'mass': copy.deepcopy(_mass_density_options), 'molecular_mass': np.NaN, 'total_number_of_atoms': np.NaN, } _material_infos = {'mantid_format': None, 'addie_format': None} _mass_density_infos['mass_density']["selected"] = True _master_table_row_ui = { 'active': None, 'title': None, 'sample': { 'runs': None, 'background': { 'runs': None, 'background': None, }, 'material': copy.deepcopy(_text_button), 'material_infos': copy.deepcopy(_material_infos), 'mass_density': copy.deepcopy(_text_button), 'mass_density_infos': copy.deepcopy(_mass_density_infos), 'packing_fraction': None, 'geometry': copy.deepcopy(_full_dimension_widgets), 'shape': None, 'abs_correction': None, 'mult_scat_correction': None, 'inelastic_correction': None, 'placzek_button': None, 'placzek_infos': None, }, 'normalization': { 'runs': None, 'background': { 'runs': None, 'background': None, }, 'material': copy.deepcopy(_text_button), 'material_infos': copy.deepcopy(_material_infos), 'mass_density': copy.deepcopy(_text_button), 'mass_density_infos': copy.deepcopy(_mass_density_infos), 'packing_fraction': None, 'geometry': copy.deepcopy(_full_dimension_widgets), 'shape': None, 'abs_correction': None, 'mult_scat_correction': None, 'inelastic_correction': None, 'placzek_button': None, 'placzek_infos': None, }, 'align_and_focus_args_button': None, 'align_and_focus_args_infos': {}, 'align_and_focus_args_use_global': True, } random_key = self.generate_random_key() self.key = random_key # block main table events self.table_ui.blockSignals(True) # column 0 (active or not checkBox) _layout = QHBoxLayout() _widget = QCheckBox() _widget.setCheckState(QtCore.Qt.Checked) _widget.setEnabled(True) _master_table_row_ui['active'] = _widget _spacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) _layout.addItem(_spacer) _layout.addWidget(_widget) _spacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) _layout.addItem(_spacer) _layout.addStretch() _new_widget = QWidget() _new_widget.setLayout(_layout) _widget.stateChanged.connect( lambda state=0, key=random_key: self.main_window. master_table_select_state_changed(state, key)) column = 0 self.table_ui.setCellWidget(row, column, _new_widget) # sample column += 1 # column 1 - title _item = QTableWidgetItem(title) _master_table_row_ui['title'] = _item self.table_ui.setItem(row, column, _item) # column 2 - sample runs column += 1 _item = QTableWidgetItem(sample_runs) _master_table_row_ui['sample']['runs'] = _item self.table_ui.setItem(row, column, _item) # column 3 - background runs column += 1 _item = QTableWidgetItem("") _master_table_row_ui['sample']['background']['runs'] = _item self.table_ui.setItem(row, column, _item) # column 4 - background background column += 1 _item = QTableWidgetItem("") _master_table_row_ui['sample']['background']['background'] = _item self.table_ui.setItem(row, column, _item) # column 5 - material (chemical formula) column += 1 clean_sample_chemical_formula = format_chemical_formula_equation( sample_chemical_formula) _material_text = QLineEdit(clean_sample_chemical_formula) _material_text = QLabel(clean_sample_chemical_formula) _material_button = QPushButton("...") _material_button.setFixedHeight(CONFIG_BUTTON_HEIGHT) _material_button.setFixedWidth(CONFIG_BUTTON_WIDTH) _material_button.pressed.connect( lambda key=random_key: self.main_window. master_table_sample_material_button_pressed(key)) _verti_layout = QVBoxLayout() _verti_layout.addWidget(_material_text) _verti_layout.addWidget(_material_button) _material_widget = QWidget() _material_widget.setLayout(_verti_layout) self.table_ui.setCellWidget(row, column, _material_widget) _master_table_row_ui['sample']['material']['text'] = _material_text _master_table_row_ui['sample']['material']['button'] = _material_button # column 6 - mass density column += 1 _mass_text = QLineEdit(sample_mass_density) _mass_text.returnPressed.connect( lambda key=random_key: self.main_window. master_table_sample_mass_density_line_edit_entered(key)) _mass_units = QLabel("g/cc") _top_widget = QWidget() _top_layout = QHBoxLayout() _top_layout.addWidget(_mass_text) _top_layout.addWidget(_mass_units) _top_widget.setLayout(_top_layout) _mass_button = QPushButton("...") _mass_button.setFixedHeight(CONFIG_BUTTON_HEIGHT) _mass_button.setFixedWidth(CONFIG_BUTTON_WIDTH) _mass_button.pressed.connect( lambda key=random_key: self.main_window. master_table_sample_mass_density_button_pressed(key)) _verti_layout = QVBoxLayout() _verti_layout.addWidget(_top_widget) _verti_layout.addWidget(_mass_button) _mass_widget = QWidget() _mass_widget.setLayout(_verti_layout) self.table_ui.setCellWidget(row, column, _mass_widget) _master_table_row_ui['sample']['mass_density']['text'] = _mass_text _master_table_row_ui['sample']['mass_density']['button'] = _mass_button # column 7 - packing fraction column += 1 if packing_fraction == "N/A": packing_fraction = "{}".format(self.main_window.packing_fraction) _item = QTableWidgetItem(packing_fraction) _master_table_row_ui['sample']['packing_fraction'] = _item self.table_ui.setItem(row, column, _item) # column 8 - shape (cylinder or sphere) column += 1 _layout = QHBoxLayout() _layout.setContentsMargins(0, 0, 0, 0) _widget = QComboBox() _shape_default_index = 0 _widget.currentIndexChanged.connect( lambda index=_shape_default_index, key=random_key: self.main_window .master_table_sample_shape_changed(index, key)) _list_ui_to_unlock.append(_widget) _widget.blockSignals(True) _widget.addItem("Cylinder") _widget.addItem("Sphere") _widget.addItem("Hollow Cylinder") _master_table_row_ui['sample']['shape'] = _widget _layout.addWidget(_widget) _w = QWidget() _w.setLayout(_layout) self.table_ui.setCellWidget(row, column, _w) # column 9 - dimensions column += 1 # layout 1 _grid_layout = QGridLayout() _label1 = QLabel("Radius:") _grid_layout.addWidget(_label1, 1, 0) _value1 = QLabel("N/A") _grid_layout.addWidget(_value1, 1, 1) _dim1 = QLabel("cm") _grid_layout.addWidget(_dim1, 1, 2) _label2 = QLabel("Radius:") _label2.setVisible(False) _grid_layout.addWidget(_label2, 2, 0) _value2 = QLabel("N/A") _value2.setVisible(False) _grid_layout.addWidget(_value2, 2, 1) _dim2 = QLabel("cm") _dim2.setVisible(False) _grid_layout.addWidget(_dim2, 2, 2) _label3 = QLabel("Height:") _grid_layout.addWidget(_label3, 3, 0) _value3 = QLabel("N/A") _grid_layout.addWidget(_value3, 3, 1) _dim3 = QLabel("cm") _grid_layout.addWidget(_dim3, 3, 2) _master_table_row_ui['sample']['geometry']['radius']['value'] = _value1 _master_table_row_ui['sample']['geometry']['radius2'][ 'value'] = _value2 _master_table_row_ui['sample']['geometry']['height']['value'] = _value3 _master_table_row_ui['sample']['geometry']['radius']['label'] = _label1 _master_table_row_ui['sample']['geometry']['radius2'][ 'label'] = _label2 _master_table_row_ui['sample']['geometry']['height']['label'] = _label3 _master_table_row_ui['sample']['geometry']['radius']['units'] = _dim1 _master_table_row_ui['sample']['geometry']['radius2']['units'] = _dim2 _master_table_row_ui['sample']['geometry']['height']['units'] = _dim3 _geometry_widget = QWidget() _geometry_widget.setLayout(_grid_layout) _set_dimensions_button = QPushButton("...") _set_dimensions_button.setFixedHeight(CONFIG_BUTTON_HEIGHT) _set_dimensions_button.setFixedWidth(CONFIG_BUTTON_WIDTH) _verti_layout = QVBoxLayout() _verti_layout.addWidget(_geometry_widget) _verti_layout.addWidget(_set_dimensions_button) _verti_widget = QWidget() _verti_widget.setLayout(_verti_layout) _set_dimensions_button.pressed.connect( lambda key=random_key: self.main_window. master_table_sample_dimensions_setter_button_pressed(key)) self.table_ui.setCellWidget(row, column, _verti_widget) # column 10 - abs. correction column += 1 _layout = QHBoxLayout() _layout.setContentsMargins(0, 0, 0, 0) _widget = QComboBox() _shape_default_value = 0 list_abs_correction = self.get_absorption_correction_list( shape=_shape_default_value) _widget.currentIndexChanged.connect( lambda value=list_abs_correction[0], key=random_key: self. main_window.master_table_sample_abs_correction_changed(value, key)) _widget.blockSignals(True) _list_ui_to_unlock.append(_widget) for _item in list_abs_correction: _widget.addItem(_item) _master_table_row_ui['sample']['abs_correction'] = _widget _layout.addWidget(_widget) _w = QWidget() _w.setLayout(_layout) self.table_ui.setCellWidget(row, column, _w) # column 11 - multi. scattering correction column += 1 _layout = QHBoxLayout() _layout.setContentsMargins(0, 0, 0, 0) _widget = QComboBox() list_multi_scat_correction = self.get_multi_scat_correction_list( shape=_shape_default_value) _widget.currentIndexChanged.connect( lambda value=list_multi_scat_correction[ 0], key=random_key: self.main_window. master_table_sample_multi_scattering_correction_changed( value, key)) _widget.blockSignals(True) _list_ui_to_unlock.append(_widget) for _item in list_multi_scat_correction: _widget.addItem(_item) _master_table_row_ui['sample']['mult_scat_correction'] = _widget _layout.addWidget(_widget) _w = QWidget() _w.setLayout(_layout) self.table_ui.setCellWidget(row, column, _w) # column 12 - inelastic correction column += 1 _layout = QHBoxLayout() _layout.setContentsMargins(0, 0, 0, 0) _widget1 = QComboBox() _widget1.setMinimumHeight(20) list_inelastic_correction = self.get_inelastic_scattering_list( shape=_shape_default_value) for _item in list_inelastic_correction: _widget1.addItem(_item) _master_table_row_ui['sample']['inelastic_correction'] = _widget1 _button = QPushButton("...") _button.setFixedHeight(CONFIG_BUTTON_HEIGHT) _button.setFixedWidth(CONFIG_BUTTON_WIDTH) _button.pressed.connect( lambda key=random_key: self.main_window. master_table_sample_placzek_button_pressed(key)) _master_table_row_ui['sample']['placzek_button'] = _button _button.setVisible(False) _master_table_row_ui['sample']['placzek_button'] = _button _layout.addWidget(_widget1) _layout.addWidget(_button) _widget = QWidget() _widget.setLayout(_layout) _default_value = 'None' _widget1.currentIndexChanged.connect( lambda value=_default_value, key=random_key: self.main_window. master_table_sample_inelastic_correction_changed(value, key)) _widget.blockSignals(True) _list_ui_to_unlock.append(_widget) self.table_ui.setCellWidget(row, column, _widget) # save default placzek settings _sample_formated_placzek_default = self.formated_placzek_default( sample_placzek_arguments) _master_table_row_ui['sample'][ 'placzek_infos'] = _sample_formated_placzek_default ## normalization # column 13 - sample runs column += 1 _item = QTableWidgetItem("") self.table_ui.setItem(row, column, _item) # column 14 - background runs column += 1 _item = QTableWidgetItem("") self.table_ui.setItem(row, column, _item) # column 15 - background background column += 1 _item = QTableWidgetItem("") self.table_ui.setItem(row, column, _item) # column 16 - material (chemical formula) column += 1 #_material_text = QLineEdit("") _material_text = QLabel("N/A") _material_button = QPushButton("...") _material_button.setFixedHeight(CONFIG_BUTTON_HEIGHT) _material_button.setFixedWidth(CONFIG_BUTTON_WIDTH) _material_button.pressed.connect( lambda key=random_key: self.main_window. master_table_normalization_material_button_pressed(key)) _verti_layout = QVBoxLayout() _verti_layout.addWidget(_material_text) _verti_layout.addWidget(_material_button) _material_widget = QWidget() _material_widget.setLayout(_verti_layout) self.table_ui.setCellWidget(row, column, _material_widget) _master_table_row_ui['normalization']['material'][ 'text'] = _material_text _master_table_row_ui['normalization']['material'][ 'button'] = _material_button # column 17 - mass density column += 1 _mass_text = QLineEdit("N/A") _mass_text.returnPressed.connect( lambda key=random_key: self.main_window. master_table_normalization_mass_density_line_edit_entered(key)) _mass_units = QLabel("g/cc") _top_widget = QWidget() _top_layout = QHBoxLayout() _top_layout.addWidget(_mass_text) _top_layout.addWidget(_mass_units) _top_widget.setLayout(_top_layout) _mass_button = QPushButton("...") _mass_button.setFixedWidth(CONFIG_BUTTON_WIDTH) _mass_button.setFixedHeight(CONFIG_BUTTON_HEIGHT) _mass_button.pressed.connect( lambda key=random_key: self.main_window. master_table_normalization_mass_density_button_pressed(key)) _verti_layout = QVBoxLayout() _verti_layout.addWidget(_top_widget) _verti_layout.addWidget(_mass_button) _mass_widget = QWidget() _mass_widget.setLayout(_verti_layout) self.table_ui.setCellWidget(row, column, _mass_widget) _master_table_row_ui['normalization']['mass_density'][ 'text'] = _mass_text _master_table_row_ui['normalization']['mass_density'][ 'button'] = _mass_button # column 18 - packing fraction column += 1 _item = QTableWidgetItem("") self.table_ui.setItem(row, column, _item) # column 19 - shape (cylinder or sphere) column += 1 _layout = QHBoxLayout() _layout.setContentsMargins(0, 0, 0, 0) _widget = QComboBox() _widget.currentIndexChanged.connect( lambda value=_shape_default_value, key=random_key: self.main_window .master_table_normalization_shape_changed(value, key)) _widget.blockSignals(True) _list_ui_to_unlock.append(_widget) _widget.addItem("Cylinder") _widget.addItem("Sphere") _widget.addItem("Hollow Cylinder") _master_table_row_ui['normalization']['shape'] = _widget _layout.addWidget(_widget) _w = QWidget() _w.setLayout(_layout) self.table_ui.setCellWidget(row, column, _w) # column 20 - dimensions column += 1 # layout 1 _grid_layout = QGridLayout() _label1 = QLabel("Radius:") _grid_layout.addWidget(_label1, 1, 0) _value1 = QLabel("N/A") _grid_layout.addWidget(_value1, 1, 1) _dim1 = QLabel("cm") _grid_layout.addWidget(_dim1, 1, 2) _label2 = QLabel("Radius:") _label2.setVisible(False) _grid_layout.addWidget(_label2, 2, 0) _value2 = QLabel("N/A") _value2.setVisible(False) _grid_layout.addWidget(_value2, 2, 1) _dim2 = QLabel("cm") _dim2.setVisible(False) _grid_layout.addWidget(_dim2, 2, 2) _label3 = QLabel("Height:") _grid_layout.addWidget(_label3, 3, 0) _value3 = QLabel("N/A") _grid_layout.addWidget(_value3, 3, 1) _dim3 = QLabel("cm") _grid_layout.addWidget(_dim3, 3, 2) _master_table_row_ui['normalization']['geometry']['radius'][ 'value'] = _value1 _master_table_row_ui['normalization']['geometry']['radius2'][ 'value'] = _value2 _master_table_row_ui['normalization']['geometry']['height'][ 'value'] = _value3 _master_table_row_ui['normalization']['geometry']['radius'][ 'label'] = _label1 _master_table_row_ui['normalization']['geometry']['radius2'][ 'label'] = _label2 _master_table_row_ui['normalization']['geometry']['height'][ 'label'] = _label3 _master_table_row_ui['normalization']['geometry']['radius'][ 'units'] = _dim1 _master_table_row_ui['normalization']['geometry']['radius2'][ 'units'] = _dim2 _master_table_row_ui['normalization']['geometry']['height'][ 'units'] = _dim3 _geometry_widget = QWidget() _geometry_widget.setLayout(_grid_layout) _set_dimensions_button = QPushButton("...") _set_dimensions_button.setFixedHeight(CONFIG_BUTTON_HEIGHT) _set_dimensions_button.setFixedWidth(CONFIG_BUTTON_WIDTH) _verti_layout = QVBoxLayout() _verti_layout.addWidget(_geometry_widget) _verti_layout.addWidget(_set_dimensions_button) _verti_widget = QWidget() _verti_widget.setLayout(_verti_layout) _set_dimensions_button.pressed.connect( lambda key=random_key: self.main_window. master_table_normalization_dimensions_setter_button_pressed( key)) # noqa self.table_ui.setCellWidget(row, column, _verti_widget) # column 21 - abs. correction column += 1 _layout = QHBoxLayout() _layout.setContentsMargins(0, 0, 0, 0) _widget = QComboBox() _widget.currentIndexChanged.connect( lambda value=list_abs_correction[0], key=random_key: self. main_window.master_table_normalization_abs_correction_changed( value, key)) # noqa _widget.blockSignals(True) _list_ui_to_unlock.append(_widget) for _item in list_abs_correction: _widget.addItem(_item) _widget.setCurrentIndex(0) _master_table_row_ui['normalization']['abs_correction'] = _widget _layout.addWidget(_widget) _w = QWidget() _w.setLayout(_layout) self.table_ui.setCellWidget(row, column, _w) # column 24 - multi. scattering correction column += 1 _layout = QHBoxLayout() _layout.setContentsMargins(0, 0, 0, 0) _widget = QComboBox() _widget.currentIndexChanged.connect( lambda value=list_multi_scat_correction[ 0], key=random_key: self.main_window. master_table_normalization_multi_scattering_correction_changed( value, key)) # noqa _widget.blockSignals(True) _list_ui_to_unlock.append(_widget) for _item in list_multi_scat_correction: _widget.addItem(_item) _widget.setCurrentIndex(0) _master_table_row_ui['normalization']['mult_scat_correction'] = _widget _layout.addWidget(_widget) _w = QWidget() _w.setLayout(_layout) self.table_ui.setCellWidget(row, column, _w) # column 22 - inelastic correction column += 1 _layout = QHBoxLayout() _layout.setContentsMargins(0, 0, 0, 0) _widget1 = QComboBox() _widget1.setMinimumHeight(20) list_inelastic_correction = self.get_inelastic_scattering_list( shape=_shape_default_value) for _item in list_inelastic_correction: _widget1.addItem(_item) _widget1.setCurrentIndex(0) _master_table_row_ui['normalization'][ 'inelastic_correction'] = _widget1 _button = QPushButton("...") _button.setFixedWidth(CONFIG_BUTTON_WIDTH) _button.setFixedHeight(CONFIG_BUTTON_HEIGHT) _button.pressed.connect( lambda key=random_key: self.main_window. master_table_normalization_placzek_button_pressed(key)) _master_table_row_ui['normalization']['placzek_button'] = _button _button.setVisible(False) _layout.addWidget(_widget1) _layout.addWidget(_button) _widget = QWidget() _widget.setLayout(_layout) _default_value = 'None' _widget1.currentIndexChanged.connect( lambda value=_default_value, key=random_key: self.main_window. master_table_normalization_inelastic_correction_changed( value, key)) # noqa _widget.blockSignals(True) _list_ui_to_unlock.append(_widget) self.table_ui.setCellWidget(row, column, _widget) # automatically populate placzek infos with default values _norm_formated_placzek_default = self.formated_placzek_default( normalization_placzek_arguments) _master_table_row_ui['normalization'][ 'placzek_infos'] = _norm_formated_placzek_default # column 23 - key/value pair column += 1 _layout = QHBoxLayout() _spacer_kv1 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) _layout.addItem(_spacer_kv1) _button = QPushButton("...") _layout.addWidget(_button) _button.setFixedWidth(CONFIG_BUTTON_WIDTH) _button.setFixedHeight(CONFIG_BUTTON_HEIGHT) _button.pressed.connect(lambda key=random_key: self.main_window. master_table_keyvalue_button_pressed(key)) _new_widget = QWidget() _new_widget.setLayout(_layout) self.table_ui.setCellWidget(row, column, _new_widget) _master_table_row_ui['align_and_focus_args_button'] = _button _spacer_kv2 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) _layout.addItem(_spacer_kv2) _layout.addStretch() align_and_focus_args = self.add_global_key_value_to_local_key_value( align_and_focus_args) _master_table_row_ui[ 'align_and_focus_args_infos'] = align_and_focus_args # Recap. self.main_window.master_table_list_ui[ random_key] = _master_table_row_ui self.unlock_signals_ui(list_ui=_list_ui_to_unlock) self.main_window.check_status_of_right_click_buttons()