def coord_line_edit(self): template = QRegExp(r"[-]?\d*\.?\d{0,3}") validator = QRegExpValidator(template) line = QLineEdit("0.0") line.setValidator(validator) line.setFixedWidth(60) # line.editingFinished.connect(self.update_dist_to_target) line.textChanged.connect(self.update_dist_to_target) return line
class ParameterEditBox(QWidget): def __init__(self, name: str, para: Parameter, *args, **kwargs) -> None: super().__init__(*args, **kwargs) if para.type not in ["LIST_OF_INT", "LIST_OF_FLOAT", int, float]: raise ValueError(f"{self.__class__.__name__} does not support parameter of type {para.type}") self._parameter = para self._name = name self.value_input = QLineEdit(self) if self._parameter.info is not None: self.value_input.setToolTip(self._parameter.info) self._set_text() self.value_input.editingFinished.connect(self._update_value) layout = QHBoxLayout(self) self.value_input.setMaximumWidth(70) self.value_input.setFixedWidth(70) layout.addWidget(QLabel(self._name)) layout.addWidget(self.value_input) layout.setContentsMargins(0,0,0,0) def _set_text(self): if isinstance(self._parameter.type, str) and "LIST" in self._parameter.type: self.value_input.setText(", ".join(list(map(str, self._parameter.value)))) else: self.value_input.setText(str(self._parameter.value)) def _update_value(self): text = self.value_input.text() try: if self._parameter.type == "LIST_OF_INT": self._parameter.value = list(map(int, text.split(","))) elif self._parameter.type == "LIST_OF_FLOAT": self._parameter.value = list(map(float, text.split(","))) elif self._parameter.type is float: self._parameter.value = float(text) elif self._parameter.type is int: self._parameter.value = int(text) except Exception as e: self._set_text() msg = QMessageBox(self) msg.setIcon(QMessageBox.Critical) msg.setWindowTitle('Setting Error') msg.setText('Illegal Parameter Setting') msg.setInformativeText(f"{text} is illegal for the parameter.<br>" + str(e)) msg.setStandardButtons(QMessageBox.Ok) msg.show()
class ConfigCobrapyDialog(QDialog): """A dialog to set values in cobrapy-config.txt""" def __init__(self, appdata: CnaData): QDialog.__init__(self) self.setWindowTitle("Configure COBRApy") self.appdata = appdata self.layout = QVBoxLayout() # allow MILP solvers only? avail_solvers = list(set(solvers.keys()) - {'scipy'}) # SCIPY currently not even usable for FBA h2 = QHBoxLayout() label = QLabel("Default solver:\n(set when loading a model)") h2.addWidget(label) self.default_solver = QComboBox() self.default_solver.addItems(avail_solvers) self.default_solver.setCurrentIndex(avail_solvers.index(interface_to_str(cobra.Configuration().solver))) h2.addWidget(self.default_solver) self.layout.addItem(h2) h9 = QHBoxLayout() label = QLabel("Solver for current model:") h9.addWidget(label) self.current_solver = QComboBox() self.current_solver.addItems(avail_solvers) self.current_solver.setCurrentIndex(avail_solvers.index(interface_to_str(appdata.project.cobra_py_model.problem))) h9.addWidget(self.current_solver) self.layout.addItem(h9) h7 = QHBoxLayout() label = QLabel( "Number of processes for multiprocessing (e.g. FVA):") h7.addWidget(label) self.num_processes = QLineEdit() self.num_processes.setFixedWidth(100) self.num_processes.setText(str(cobra.Configuration().processes)) validator = QIntValidator(1, cpu_count(), self) self.num_processes.setValidator(validator) h7.addWidget(self.num_processes) self.layout.addItem(h7) h8 = QHBoxLayout() label = QLabel( "Default tolerance:\n(set when loading a model)") h8.addWidget(label) self.default_tolerance = QLineEdit() self.default_tolerance.setFixedWidth(100) self.default_tolerance.setText(str(cobra.Configuration().tolerance)) validator = QDoubleValidator(self) validator.setBottom(1e-9) # probably a reasonable consensus value self.default_tolerance.setValidator(validator) h8.addWidget(self.default_tolerance) self.layout.addItem(h8) h10 = QHBoxLayout() label = QLabel( "Tolerance for current model:") h10.addWidget(label) self.current_tolerance = QLineEdit() self.current_tolerance.setFixedWidth(100) self.current_tolerance.setText(str(self.appdata.project.cobra_py_model.tolerance)) validator = QDoubleValidator(self) validator.setBottom(0) self.current_tolerance.setValidator(validator) h10.addWidget(self.current_tolerance) self.layout.addItem(h10) l2 = QHBoxLayout() self.button = QPushButton("Apply Changes") self.cancel = QPushButton("Close") l2.addWidget(self.button) l2.addWidget(self.cancel) self.layout.addItem(l2) self.setLayout(self.layout) self.cancel.clicked.connect(self.reject) self.button.clicked.connect(self.apply) def apply(self): cobra.Configuration().solver = self.default_solver.currentText() cobra.Configuration().processes = int(self.num_processes.text()) try: val = float(self.default_tolerance.text()) if 1e-9 <= val <= 0.1: cobra.Configuration().tolerance = val else: raise ValueError except: QMessageBox.critical(self, "Cannot set default tolerance", "Choose a value between 0.1 and 1e-9 as default tolerance.") return try: self.appdata.project.cobra_py_model.solver = self.current_solver.currentText() self.appdata.project.cobra_py_model.tolerance = float(self.current_tolerance.text()) except Exception as e: QMessageBox.critical(self, "Cannot set current solver/tolerance", str(e)) return parser = configparser.ConfigParser() parser.add_section('cobrapy-config') parser.set('cobrapy-config', 'solver', interface_to_str(cobra.Configuration().solver)) parser.set('cobrapy-config', 'processes', str(cobra.Configuration().processes)) parser.set('cobrapy-config', 'tolerance', str(cobra.Configuration().tolerance)) try: fp = open(self.appdata.cobrapy_conf_path, "w") except FileNotFoundError: os.makedirs(appdirs.user_config_dir( "cnapy", roaming=True, appauthor=False)) fp = open(self.appdata.cobrapy_conf_path, "w") parser.write(fp) fp.close() self.accept()
class LineListPane(QWidget): # this builds a single pane dedicated to a single list. def __init__(self, table_view, linelist, sort_proxy, caller, *args, **kwargs): super().__init__(None, *args, **kwargs) self.table_view = table_view self.linelist = linelist self._sort_proxy = sort_proxy self._caller = caller self._build_GUI(linelist, table_view) def _build_GUI(self, linelist, table_view): panel_layout = QVBoxLayout() panel_layout.setSizeConstraint(QLayout.SetMaximumSize) self.setLayout(panel_layout) # header with line list metadata. info = QTextBrowser() info.setMaximumHeight(100) info.setAutoFillBackground(True) info.setStyleSheet("background-color: rgb(230,230,230);") for comment in linelist.meta['comments']: info.append(comment) # buttons and selectors dedicated to the specific list # displayed in this pane. button_pane = QWidget() hlayout = QGridLayout() # 'add set' button self.create_set_button = QPushButton(self) self.create_set_button.setObjectName("add_set_button") _translate = QCoreApplication.translate self.create_set_button.setText(_translate("MainWindow", "Create set")) self.create_set_button.setToolTip( "Create new line set from selected lines.") self.create_set_button.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) hlayout.addWidget(self.create_set_button, 1, 0) # the create_set button is enabled/disabled by logic elsewhere self.create_set_button.setEnabled(False) self.create_set_button.clicked.connect(lambda: self._createSet()) # 'deselect all' button deselect_button = QPushButton(self) deselect_button.setObjectName("deselect_button") _translate = QCoreApplication.translate deselect_button.setText(_translate("MainWindow", "Deselect")) deselect_button.setToolTip("Un-select everything on this set.") deselect_button.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) hlayout.addWidget(deselect_button, 1, 1) deselect_button.clicked.connect(lambda: table_view.clearSelection()) # color picker self.combo_box_color = QComboBox(self) self.combo_box_color.setObjectName("color_selector") self.combo_box_color.setToolTip( "Color for selected lines in this set.") model = self.combo_box_color.model() for cname in ID_COLORS: item = QStandardItem(cname) item.setForeground(ID_COLORS[cname]) item.setData(QColor(ID_COLORS[cname]), role=Qt.UserRole) model.appendRow(item) hlayout.addWidget(self.combo_box_color, 1, 2) hlayout.addWidget(QLabel("Color"), 0, 2) # plotting height self.height_textbox = QLineEdit(str(DEFAULT_HEIGHT)) validator = QDoubleValidator() validator.setRange(0.05, 0.95, decimals=2) self.height_textbox.setValidator(validator) self.height_textbox.setFixedWidth(50) self.height_textbox.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.height_textbox.setToolTip("Relative height to plot.") hlayout.addWidget(self.height_textbox, 1, 3) hlayout.addWidget(QLabel("Height"), 0, 3) # redshift self.redshift_textbox = QLineEdit(str(0.0)) validator = QDoubleValidator() validator.setRange(-1.e5, 1.e10, decimals=4) self.redshift_textbox.setValidator(validator) self.redshift_textbox.setFixedWidth(70) self.redshift_textbox.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.redshift_textbox.setToolTip("Redshift lines by") hlayout.addWidget(self.redshift_textbox, 1, 4) hlayout.addWidget(QLabel("Redshift"), 0, 4) # redshift units self.combo_box_z_units = QComboBox(self) self.combo_box_z_units.setObjectName("redshift_units") self.combo_box_z_units.setToolTip("Redshift units.") model = self.combo_box_z_units.model() for uname in ['z', 'km/s']: item = QStandardItem(uname) model.appendRow(item) hlayout.addWidget(self.combo_box_z_units, 1, 5) # put it all together. spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) hlayout.addItem(spacerItem, 1, 6) button_pane.setLayout(hlayout) panel_layout.addWidget(info) panel_layout.addWidget(table_view) panel_layout.addWidget(button_pane) def __eq__(self, other): return self.__dict__ == other.__dict__ def setLineSetsTabbedPane(self, pane): self._sets_tabbed_pane = pane # this must be set only once per tabbed pane, otherwise multiple # signal handlers can result in more than one tab being closed # when just one closing request is posted. self._sets_tabbed_pane.tabCloseRequested.connect(self.tab_close) def _createSet(self): # build list with only the selected rows. These must be model # rows, not view rows! selected_view_rows = self.table_view.selectionModel().selectedRows() selected_model_rows = [ self._sort_proxy.mapToSource(x) for x in selected_view_rows ] if len(selected_model_rows) > 0: r = [x for x in selected_model_rows] local_list = self.linelist.extract_rows(r) # name is used to match lists with table views local_list.name = self.linelist.name table_model = LineListTableModel(local_list) pane, table_view = _createLineListPane(local_list, table_model, self._caller) pane._sets_tabbed_pane = self._sets_tabbed_pane table_view.selectionModel().selectionChanged.connect( self._caller._countSelections) table_view.selectionModel().selectionChanged.connect( pane.handle_button_activation) self._sets_tabbed_pane.addTab(pane, str(self._sets_tabbed_pane.count())) def tab_close(self, index): self._sets_tabbed_pane.removeTab(index) def handle_button_activation(self): nselected = len(self.table_view.selectionModel().selectedRows()) self.create_set_button.setEnabled(nselected > 0)
def _build_waverange_dialog(self, wave_range, line_list): dialog = QDialog(parent=self.centralWidget) dialog.setWindowTitle("Wavelength range") dialog.setWindowModality(Qt.ApplicationModal) dialog.resize(370, 250) button_ok = QPushButton("OK") button_ok.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) button_cancel = QPushButton("Cancel") button_cancel.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) button_ok.clicked.connect(dialog.accept) button_cancel.clicked.connect(dialog.reject) min_text = QLineEdit("%.2f" % wave_range[0].value) max_text = QLineEdit("%.2f" % wave_range[1].value) validator = QDoubleValidator() validator.setBottom(0.0) validator.setDecimals(2) min_text.setValidator(validator) max_text.setValidator(validator) min_text.setFixedWidth(150) max_text.setFixedWidth(150) min_text.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) max_text.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) min_text.setToolTip("Minimum wavelength to read from list.") max_text.setToolTip("Maximum wavelength to read from list.") nlines_label = self._compute_nlines_in_waverange( line_list, min_text, max_text) min_text.editingFinished.connect( lambda: self._compute_nlines_in_waverange( line_list, min_text, max_text, label=nlines_label)) max_text.editingFinished.connect( lambda: self._compute_nlines_in_waverange( line_list, min_text, max_text, label=nlines_label)) # set up layouts and widgets for the dialog. text_pane = QWidget() text_layout = QGridLayout() text_layout.addWidget(min_text, 1, 0) text_layout.addWidget(QLabel("Minimum wavelength"), 0, 0) text_layout.addWidget(max_text, 1, 1) text_layout.addWidget(QLabel("Maximum wavelength"), 0, 1) spacerItem = QSpacerItem(40, 10, QSizePolicy.Expanding, QSizePolicy.Minimum) text_layout.addItem(spacerItem, 1, 2) text_pane.setLayout(text_layout) label_pane = QWidget() label_layout = QHBoxLayout() label_layout.addWidget(nlines_label) label_layout.addWidget(QLabel(" lines included in range.")) label_layout.addStretch() label_pane.setLayout(label_layout) button_pane = QWidget() button_layout = QHBoxLayout() button_layout.addStretch() button_layout.addWidget(button_cancel) button_layout.addWidget(button_ok) button_pane.setLayout(button_layout) dialog_layout = QVBoxLayout() dialog_layout.setSizeConstraint(QLayout.SetMaximumSize) dialog_layout.addWidget(text_pane) dialog_layout.addWidget(label_pane) dialog_layout.addStretch() dialog_layout.addWidget(button_pane) dialog.setLayout(dialog_layout) button_ok.setDefault(True) button_cancel.setDefault(False) accepted = dialog.exec_() > 0 amin = amax = None if accepted: return self._get_range_from_textfields(min_text, max_text) return (amin, amax)
def create_wwwc_tab(apply_adjust): Conf = namedtuple("Conf", "min max step default") ww_conf = Conf(0, 2000, 1, 350) wc_conf = Conf(-2000, 2000, 1, 50) tab = QWidget() tab.layout = QFormLayout() # BUG: 只有一个负号的时候会变成0,应该保留负号 ww_edit = QLineEdit() ww_edit.setValidator(QtGui.QIntValidator(ww_conf.min, ww_conf.max)) ww_edit.setFixedWidth(50) wc_edit = QLineEdit() wc_edit.setValidator(QtGui.QIntValidator(wc_conf.min, wc_conf.max)) wc_edit.setFixedWidth(50) ww_slider = QSlider(Qt.Horizontal) # 窗宽滑动条 ww_slider.setMinimum(ww_conf.min) ww_slider.setMaximum(ww_conf.max) ww_slider.setSingleStep(ww_conf.step) ww_slider.setValue(ww_conf.default) wc_slider = QSlider(Qt.Horizontal) # 窗位滑动条 wc_slider.setMinimum(wc_conf.min) wc_slider.setMaximum(wc_conf.max) wc_slider.setSingleStep(wc_conf.step) wc_slider.setValue(wc_conf.default) ww_label = QLabel() ww_label.setText("窗宽: ") wc_label = QLabel() wc_label.setText("窗位: ") ww_combo = QHBoxLayout() ww_combo.addWidget(ww_edit) ww_combo.addWidget(ww_slider) wc_combo = QHBoxLayout() wc_combo.addWidget(wc_edit) wc_combo.addWidget(wc_slider) tab.layout.addRow(ww_label, ww_combo) tab.layout.addRow(wc_label, wc_combo) tab.setLayout(tab.layout) def slider_change(slider, editor): def func(): editor.setText(str(slider.value())) apply_adjust( functools.partial(wwwc, ww_slider.value(), wc_slider.value())) return func def edit_changed(editor, slider): def func(): value = editor.text() if value == "" or value == "-": value = 0 value = int(value) slider.setValue(value) return func ww_slider.valueChanged.connect(slider_change(ww_slider, ww_edit)) wc_slider.valueChanged.connect(slider_change(wc_slider, wc_edit)) ww_edit.textChanged.connect(edit_changed(ww_edit, ww_slider)) # wc_edit.textChanged.connect(wc_edit_change) return tab, "WW/WC"
class ContourOptionsDialog(QDialog): """ Dialog box for selecting contour options """ def __init__(self, contour_settings): super(ContourOptionsDialog, self).__init__(contour_settings.cubeviz_layout) self.setWindowFlags(self.windowFlags() | Qt.Tool) self.setWindowTitle("Contour Options") self.is_preview_active = False # preview mode? self.contour_settings = contour_settings # ref to caller ContourSettings self.image_viewer = self.contour_settings.image_viewer # ref to image viewer self.options = self.contour_settings.options # ref to ContourSettings options self._colormap_members = self.contour_settings.colormap_members # Colormap options self._colormap_index = DEFAULT_GLUE_COLORMAP_INDEX # Currently selected colormap if "cmap" in self.options: if self.options["cmap"] in self._colormap_members: self._colormap_index = self._colormap_members.index( self.options["cmap"]) # Is there a user spacing? if self.contour_settings.spacing is None: self.is_custom_spacing = False else: self.is_custom_spacing = True # Is there a user min? if self.contour_settings.vmin is None: self.is_vmin = False else: self.is_vmin = True # Is there a user max? if self.contour_settings.vmax is None: self.is_vmax = False else: self.is_vmax = True self.add_contour_label = self.contour_settings.add_contour_label # bool self._init_ui() def _init_ui(self): # Line 1: Color map self.colormap_label = QLabel("Color Scheme: ") self.colormap_combo = QColormapCombo() self.colormap_combo.addItem("", userData=cm.viridis) self.colormap_combo._update_icons() self.colormap_combo.setCurrentIndex(self._colormap_index) self.colormap_combo.setMaximumWidth(150) self.colormap_combo.currentIndexChanged.connect( self._on_colormap_change) # hbl is short for Horizontal Box Layout hbl1 = QHBoxLayout() hbl1.addWidget(self.colormap_label) hbl1.addWidget(self.colormap_combo) # Line 2: Display contour labels self.contour_label_checkBox = QCheckBox("Contour labels (font size):") if self.contour_settings.add_contour_label: self.contour_label_checkBox.setChecked(True) self.contour_label_checkBox.toggled.connect(self.toggle_labels) font_string = str(self.contour_settings.font_size) self.font_size_input = QLineEdit(font_string) self.font_size_input.setFixedWidth(150) self.font_size_input.setDisabled( not self.contour_settings.add_contour_label) hbl2 = QHBoxLayout() hbl2.addWidget(self.contour_label_checkBox) hbl2.addWidget(self.font_size_input) # Line 3: Contour Spacing self.custom_spacing_checkBox = QCheckBox("Contour spacing (interval):") if self.is_custom_spacing: self.custom_spacing_checkBox.setChecked(True) self.custom_spacing_checkBox.toggled.connect(self.custom_spacing) self.spacing_input = QLineEdit() self.spacing_input.setFixedWidth(150) self.spacing_input.setDisabled(not self.is_custom_spacing) spacing = "" if self.is_custom_spacing: spacing = str(self.contour_settings.spacing) elif self.contour_settings.data_spacing is not None: spacing = self.contour_settings.data_spacing spacing = "{0:1.4f}".format(spacing) self.spacing_default_text = spacing self.spacing_input.setText(spacing) hbl3 = QHBoxLayout() hbl3.addWidget(self.custom_spacing_checkBox) hbl3.addWidget(self.spacing_input) # Line 4: Vmax self.vmax_checkBox = QCheckBox("Set max:") self.vmax_input = QLineEdit() self.vmax_input.setFixedWidth(150) self.vmax_input.setDisabled(not self.is_vmax) vmax = "" if self.is_vmax: self.vmax_checkBox.setChecked(True) vmax = str(self.contour_settings.vmax) elif self.contour_settings.data_max is not None: vmax = self.contour_settings.data_max vmax = "{0:1.4f}".format(vmax) self.vmax_input.setText(vmax) self.vmax_default_text = vmax self.vmax_checkBox.toggled.connect(self.toggle_vmax) hbl4 = QHBoxLayout() hbl4.addWidget(self.vmax_checkBox) hbl4.addWidget(self.vmax_input) # Line 5: Vmin self.vmin_checkBox = QCheckBox("Set min:") self.vmin_input = QLineEdit() self.vmin_input.setFixedWidth(150) self.vmin_input.setDisabled(not self.is_vmin) vmin = "" if self.is_vmin: self.vmin_checkBox.setChecked(True) vmin = str(self.contour_settings.vmin) elif self.contour_settings.data_min is not None: vmin = self.contour_settings.data_min vmin = "{0:1.4f}".format(vmin) self.vmin_input.setText(vmin) self.vmin_default_text = vmin self.vmin_checkBox.toggled.connect(self.toggle_vmin) hbl5 = QHBoxLayout() hbl5.addWidget(self.vmin_checkBox) hbl5.addWidget(self.vmin_input) # Line f: self.previewButton = QPushButton("Preview") self.previewButton.clicked.connect(self.preview) self.defaultButton = QPushButton("Reset") self.defaultButton.clicked.connect(self.default) self.okButton = QPushButton("OK") self.okButton.clicked.connect(self.finish) self.okButton.setDefault(True) self.cancelButton = QPushButton("Cancel") self.cancelButton.clicked.connect(self.cancel) hblf = QHBoxLayout() hblf.addStretch(1) hblf.addWidget(self.previewButton) hblf.addWidget(self.defaultButton) hblf.addWidget(self.cancelButton) hblf.addWidget(self.okButton) vbl = QVBoxLayout() vbl.addLayout(hbl1) vbl.addLayout(hbl2) vbl.addLayout(hbl3) vbl.addLayout(hbl4) vbl.addLayout(hbl5) vbl.addLayout(hblf) self.setLayout(vbl) self.show() def update_data_vals(self, vmin="", vmax="", spacing="1"): self.vmin_default_text = vmin if not self.is_vmin: self.vmin_input.setText(vmin) self.vmax_default_text = vmax if not self.is_vmax: self.vmax_input.setText(vmax) self.spacing_default_text = spacing if not self.is_custom_spacing: self.spacing_input.setText(spacing) def _on_colormap_change(self, index): """Combo index changed handler""" self._colormap_index = index def custom_spacing(self): """Checkbox toggled handler""" if self.is_custom_spacing: self.is_custom_spacing = False self.spacing_input.setDisabled(True) self.spacing_input.setText(self.spacing_default_text) self.spacing_input.setStyleSheet("") else: self.is_custom_spacing = True self.spacing_input.setDisabled(False) def toggle_labels(self): """Checkbox toggled handler""" if self.add_contour_label: self.add_contour_label = False self.font_size_input.setDisabled(True) font_string = str(self.contour_settings.font_size) self.font_size_input.setText(font_string) self.font_size_input.setStyleSheet("") else: self.add_contour_label = True self.font_size_input.setDisabled(False) def toggle_vmax(self): """Checkbox toggled handler""" if self.is_vmax: self.is_vmax = False self.vmax_input.setDisabled(True) self.vmax_input.setText(self.vmax_default_text) self.vmax_input.setStyleSheet("") else: self.is_vmax = True self.vmax_input.setDisabled(False) def toggle_vmin(self): """Checkbox toggled handler""" if self.is_vmin: self.is_vmin = False self.vmin_input.setDisabled(True) self.vmin_input.setText(self.vmin_default_text) self.vmin_input.setStyleSheet("") else: self.is_vmin = True self.vmin_input.setDisabled(False) def input_validation(self): red = "background-color: rgba(255, 0, 0, 128);" def float_check(min_val=None): if user_input.text() == "": user_input.setStyleSheet(red) return False else: try: value = float(user_input.text()) if min_val is not None: if value <= min_val: user_input.setStyleSheet(red) return False else: user_input.setStyleSheet("") except ValueError: user_input.setStyleSheet(red) return False return True def int_check(min_val=None): if user_input.text() == "": user_input.setStyleSheet(red) return False else: try: value = int(user_input.text()) if min_val is not None: if value <= min_val: user_input.setStyleSheet(red) return False else: user_input.setStyleSheet("") except ValueError: user_input.setStyleSheet(red) return False return True success = True # Check 1: spacing_input if self.is_custom_spacing: user_input = self.spacing_input float_check(0) success = success and float_check() # Check 2: font_size_input if self.add_contour_label: user_input = self.font_size_input int_check(0) success = success and int_check() # Check 3: vmax if self.is_vmax: user_input = self.vmax_input float_check() success = success and float_check() # Check 4: vmax if self.is_vmin: user_input = self.vmin_input float_check() success = success and float_check() # Check 5: vmax and vmin if self.is_vmax and self.is_vmin and success: vmax = float(self.vmax_input.text()) vmin = float(self.vmin_input.text()) if vmax <= vmin: self.vmax_input.setStyleSheet(red) self.vmin_input.setStyleSheet(red) success = False return success def finish(self): """ Ok button pressed. Finalize options and send to image viewer """ success = self.input_validation() if not success: return # Change Color Map self._colormap_index = self.colormap_combo.currentIndex() colormap = self._colormap_members[self._colormap_index] self.contour_settings.options["cmap"] = colormap # labels self.contour_settings.add_contour_label = self.add_contour_label # font size if self.add_contour_label: font_size = int(self.font_size_input.text()) self.contour_settings.font_size = font_size else: self.contour_settings.font_size = DEFAULT_CONTOUR_FONT_SIZE # Spacing if self.is_custom_spacing: self.contour_settings.spacing = float(self.spacing_input.text()) else: self.contour_settings.spacing = None # vmax if self.is_vmax: vmax = float(self.vmax_input.text()) self.contour_settings.vmax = vmax self.contour_settings.options["vmax"] = vmax else: self.contour_settings.vmax = None self.contour_settings.options["vmax"] = None # vmin if self.is_vmin: vmin = float(self.vmin_input.text()) self.contour_settings.vmin = vmin self.contour_settings.options["vmin"] = vmin else: self.contour_settings.vmin = None self.contour_settings.options["vmin"] = None # Redraw contour if self.contour_settings.image_viewer.is_contour_active: self.contour_settings.draw_function() self.close() def preview(self): """ Prepare preview contour settings and send to image viewer """ success = self.input_validation() if not success: return image_viewer = self.contour_settings.image_viewer preview_settings = ContourSettings(image_viewer) preview_settings.dialog = self preview_settings.options = self.contour_settings.options.copy() preview_settings.spacing = self.contour_settings.spacing # Change Color Map self._colormap_index = self.colormap_combo.currentIndex() colormap = self._colormap_members[self._colormap_index] preview_settings.options["cmap"] = colormap # labels add_contour_label = self.contour_label_checkBox.isChecked() preview_settings.add_contour_label = add_contour_label # font size if add_contour_label: font_size = int(self.font_size_input.text()) preview_settings.font_size = font_size # Spacing if self.is_custom_spacing: preview_settings.spacing = float(self.spacing_input.text()) else: preview_settings.spacing = None # vmax if self.is_vmax: vmax = float(self.vmax_input.text()) preview_settings.vmax = vmax preview_settings.options["vmax"] = vmax else: preview_settings.vmax = None preview_settings.options["vmax"] = None # vmin if self.is_vmin: vmin = float(self.vmin_input.text()) preview_settings.vmin = vmin preview_settings.options["vmin"] = vmin else: preview_settings.vmin = None preview_settings.options["vmin"] = None # Redraw contour if image_viewer.is_contour_active: self.is_preview_active = True image_viewer.set_contour_preview(preview_settings) else: message = "Contour map is currently switched off. " \ "Please turn on the contour map by selecting " \ "a component from the contour map drop-down menu." info = QMessageBox.critical(self, "Error", message) def default(self): """ Set options back to default and send to image viewer """ self.contour_settings.options = self.contour_settings.default_options() self.contour_settings.spacing = None self.contour_settings.font_size = DEFAULT_CONTOUR_FONT_SIZE self.contour_settings.vmax = None self.contour_settings.vmin = None self.contour_settings.add_contour_label = False if self.contour_settings.image_viewer.is_contour_active: self.contour_settings.draw_function() self.contour_settings.options_dialog() def cancel(self): if self.contour_settings.image_viewer.is_contour_active: self.contour_settings.draw_function() self.close() def closeEvent(self, event): """closeEvent handler""" if self.is_preview_active: self.contour_settings.image_viewer.end_contour_preview() def keyPressEvent(self, e): if e.key() == Qt.Key_Escape: self.cancel()
def populate_unit_layout(self, unit_layout, gui=None): """ Populate horizontal layout (living on conversion gui) with appropriate widgets. Set wave attribute to current wavelength. Layouts: 10^[QLineEdit] X [QComboBox] / [QComboBox] or 10^[QLineEdit] X [QComboBox] :param unit_layout: (QHBoxLayout) Horizontal layout :param gui: conversion gui :return: updated unit_layout """ power = self._get_current_power() unit_layout.addWidget(QLabel("10^")) power_input = QLineEdit(str(power)) power_input.setFixedWidth(30) self.power_input = power_input power_input.textChanged.connect(self._update_message) unit_layout.addWidget(power_input) unit_layout.addWidget(QLabel(" X ")) flux_unit_str = self.spectral_flux_density.to_string() flux_options = FLUX_UNIT_REGISTRY.get_unit_list(current_unit=flux_unit_str) if flux_unit_str in flux_options: index = flux_options.index(flux_unit_str) else: index = find_unit_index(flux_options, flux_unit_str) if index is None: flux_options.append(flux_unit_str) index = flux_options.index(flux_unit_str) flux_combo = QComboBox() flux_combo.addItems(flux_options) flux_combo.setCurrentIndex(index) flux_combo.currentIndexChanged.connect(self._on_flux_combo_change) flux_combo.currentIndexChanged.connect(self._update_message) self.flux_combo = flux_combo unit_layout.addWidget(flux_combo) if self.area is not None: division = QLabel(" / ") unit_layout.addWidget(division) area_str = self.area.to_string() if self.controller is None: no_pixel_area = True else: no_pixel_area = self.controller.pixel_area is None if self.area.decompose() == u.pix.decompose() and no_pixel_area: area_options = AREA_UNIT_REGISTRY.get_unit_list(pixel_only=True) elif 'solid angle' in self.area.physical_type and no_pixel_area: area_options = AREA_UNIT_REGISTRY.get_unit_list(solid_angle_only=True) else: area_options = AREA_UNIT_REGISTRY.get_unit_list() if area_str in area_options: index = area_options.index(area_str) else: index = find_unit_index(area_options, area_str) if index is None: area_options.append(area_str) index = area_options.index(area_str) area_combo = QComboBox() area_combo.width() area_combo.addItems(area_options) area_combo.setCurrentIndex(index) area_combo.currentIndexChanged.connect(self._update_message) self.area_combo = area_combo unit_layout.addWidget(area_combo) unit_layout.addStretch(1) unit_layout.setSpacing(0) if self.message_box is not None: self._update_message() if gui is not None: cubeviz_layout = gui.cubeviz_layout if cubeviz_layout is not None: self.wave = cubeviz_layout.get_wavelength() return unit_layout
def populate_unit_layout(self, unit_layout, gui=None): """ Populate horizontal layout (living on conversion gui) with appropriate widgets. Set wave attribute to current wavelength. Layouts: 10^[QLineEdit] X [QComboBox] / [QComboBox] or 10^[QLineEdit] X [QComboBox] :param unit_layout: (QHBoxLayout) Horizontal layout :param gui: conversion gui :return: updated unit_layout """ power = self._get_current_power() unit_layout.addWidget(QLabel("10^")) power_input = QLineEdit(str(power)) power_input.setFixedWidth(30) self.power_input = power_input power_input.textChanged.connect(self._update_message) unit_layout.addWidget(power_input) unit_layout.addWidget(QLabel(" X ")) flux_unit_str = self.spectral_flux_density.to_string() flux_options = FLUX_UNIT_REGISTRY.compose_unit_list(current_unit=flux_unit_str) if flux_unit_str in flux_options: index = flux_options.index(flux_unit_str) else: index = find_unit_index(flux_options, flux_unit_str) if index is None: flux_options.append(flux_unit_str) index = flux_options.index(flux_unit_str) flux_combo = QComboBox() flux_combo.addItems(flux_options) flux_combo.setCurrentIndex(index) flux_combo.currentIndexChanged.connect(self._on_flux_combo_change) flux_combo.currentIndexChanged.connect(self._update_message) self.flux_combo = flux_combo unit_layout.addWidget(flux_combo) if self.area is not None: division = QLabel(" / ") unit_layout.addWidget(division) area_str = self.area.to_string() no_pixel_area = self.pixel_area is None if self.area.decompose() == u.pix.decompose() and no_pixel_area: area_options = AREA_UNIT_REGISTRY.compose_unit_list(pixel_only=True) elif 'solid angle' in self.area.physical_type and no_pixel_area: area_options = AREA_UNIT_REGISTRY.compose_unit_list(solid_angle_only=True) else: area_options = AREA_UNIT_REGISTRY.compose_unit_list() if area_str in area_options: index = area_options.index(area_str) else: index = find_unit_index(area_options, area_str) if index is None: area_options.append(area_str) index = area_options.index(area_str) area_combo = QComboBox() area_combo.width() area_combo.addItems(area_options) area_combo.setCurrentIndex(index) area_combo.currentIndexChanged.connect(self._update_message) self.area_combo = area_combo unit_layout.addWidget(area_combo) unit_layout.addStretch(1) unit_layout.setSpacing(0) if self.message_box is not None: self._update_message() return unit_layout
class MiniControl(QWidget): def __init__(self, parent, selectedTab=0): super().__init__() self.textButtonStyleEnabled = "QPushButton {background-color: #151B54; color: white;} QPushButton:hover {background-color: #333972;} QPushButton:pressed { background-color: #515790;}" self.textButtonStyleDisabled = "QPushButton {background-color: #323232; color: #323232;} QPushButton:hover {background-color: #323232;} QPushButton:pressed { background-color: #323232;}" self.setWindowTitle(config.thisTranslation["remote_control"]) self.parent = parent self.devotionals = sorted( glob.glob(config.marvelData + "/devotionals/*.devotional")) # specify window size if config.qtMaterial and config.qtMaterialTheme: self.resizeWindow(1 / 2, 1 / 3) else: self.resizeWindow(2 / 5, 1 / 3) self.resizeEvent = (lambda old_method: (lambda event: (self.onResized(event), old_method(event))[-1]))( self.resizeEvent) self.bibleButtons = {} self.commentaryButtons = {} self.bookIntroButtons = {} # setup interface self.bible_layout = None self.setupUI() self.tabs.setCurrentIndex(selectedTab) # window appearance def resizeWindow(self, widthFactor, heightFactor): availableGeometry = QGuiApplication.instance().desktop( ).availableGeometry() self.setMinimumWidth(500) self.resize(availableGeometry.width() * widthFactor, availableGeometry.height() * heightFactor) def onResized(self, event): pass def closeEvent(self, event): config.miniControl = False # manage key capture def event(self, event): if event.type() == QEvent.KeyRelease: if event.modifiers() == Qt.ControlModifier: if event.key() == Qt.Key_B: self.tabs.setCurrentIndex(0) elif event.key() == Qt.Key_T: self.tabs.setCurrentIndex(1) elif event.key() == Qt.Key_C: self.tabs.setCurrentIndex(2) elif event.key() == Qt.Key_L: self.tabs.setCurrentIndex(3) elif event.key() == Qt.Key_D: self.tabs.setCurrentIndex(4) elif event.key() == Qt.Key_O: self.tabs.setCurrentIndex(5) elif event.key() == Qt.Key_Escape: self.close() return QWidget.event(self, event) # setup ui def setupUI(self): textButtonStyle = "QPushButton {background-color: #151B54; color: white;} QPushButton:hover {background-color: #333972;} QPushButton:pressed { background-color: #515790;}" mainLayout = QGridLayout() commandBox = QVBoxLayout() commandBox.setSpacing(3) commandBar = QWidget() commandLayout1 = QBoxLayout(QBoxLayout.LeftToRight) commandLayout1.setSpacing(5) self.searchLineEdit = QLineEdit() self.searchLineEdit.setClearButtonEnabled(True) self.searchLineEdit.setToolTip( config.thisTranslation["enter_command_here"]) self.searchLineEdit.returnPressed.connect(self.searchLineEntered) self.searchLineEdit.setFixedWidth(450) commandLayout1.addWidget(self.searchLineEdit) enterButton = QPushButton(config.thisTranslation["enter"]) enterButton.setFixedWidth(100) enterButton.clicked.connect(self.searchLineEntered) commandLayout1.addWidget(enterButton) # commandLayout1.addStretch() commandBox.addLayout(commandLayout1) if config.showMiniKeyboardInMiniControl: commandLayout2 = QBoxLayout(QBoxLayout.LeftToRight) commandLayout2.setSpacing(5) keys = [ '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', ':', '-', ',', '.', ' ', '<', 'X' ] for key in keys: button = QPushButton(key) button.setMaximumWidth(30) button.clicked.connect(partial(self.keyEntryAction, key)) commandLayout2.addWidget(button) commandLayout2.addStretch() commandBox.addLayout(commandLayout2) if config.showMiniKeyboardInMiniControl and config.isTtsInstalled: ttsLayout = QBoxLayout(QBoxLayout.LeftToRight) ttsLayout.setSpacing(5) self.languageCombo = QComboBox() ttsLayout.addWidget(self.languageCombo) if config.espeak: languages = TtsLanguages().isoLang2epeakLang else: languages = TtsLanguages().isoLang2qlocaleLang self.languageCodes = list(languages.keys()) for code in self.languageCodes: self.languageCombo.addItem(languages[code][1]) # Check if selected tts engine has the language user specify. if not (config.ttsDefaultLangauge in self.languageCodes): config.ttsDefaultLangauge = "en" # Set initial item initialIndex = self.languageCodes.index(config.ttsDefaultLangauge) self.languageCombo.setCurrentIndex(initialIndex) # setting tts default language here is confusing; better place in menu #setDefaultButton = QPushButton(config.thisTranslation["setDefault"]) #setDefaultButton.setFixedWidth(130) #setDefaultButton.clicked.connect(self.setTtsDefaultLanguage) #ttsLayout.addWidget(setDefaultButton) speakButton = QPushButton(config.thisTranslation["speak"]) speakButton.setFixedWidth(100) speakButton.clicked.connect(self.speakCommandFieldText) ttsLayout.addWidget(speakButton) stopButton = QPushButton(config.thisTranslation["stop"]) stopButton.setFixedWidth(100) stopButton.clicked.connect( self.parent.textCommandParser.stopTtsAudio) ttsLayout.addWidget(stopButton) ttsLayout.addStretch() commandBox.addLayout(ttsLayout) commandBar.setLayout(commandBox) mainLayout.addWidget(commandBar, 0, 0, Qt.AlignCenter) self.tabs = QTabWidget() self.tabs.currentChanged.connect(self.tabChanged) mainLayout.addWidget(self.tabs, 1, 0, Qt.AlignCenter) parser = BibleVerseParser(config.parserStandarisation) self.bookMap = parser.standardAbbreviation bookNums = list(self.bookMap.keys()) self.bookNumGps = [ bookNums[0:10], bookNums[10:20], bookNums[20:30], bookNums[30:39], bookNums[39:49], bookNums[49:59], bookNums[59:69], bookNums[69:79], bookNums[79:86], bookNums[86:94], bookNums[94:99], bookNums[99:104], bookNums[104:110], bookNums[110:119], bookNums[119:124], bookNums[124:129], bookNums[129:139], bookNums[139:149], bookNums[149:159], bookNums[159:169], bookNums[169:174], bookNums[174:179], bookNums[179:189], bookNums[189:199], ] # Bible books tab self.bible = QWidget() self.populateBooksButtons(config.mainText) self.tabs.addTab(self.bible, config.thisTranslation["bible"]) # Bible translations tab self.biblesBox = QWidget() self.biblesBoxContainer = QVBoxLayout() collectionsLayout = self.newRowLayout() if len(config.bibleCollections) > 0: button = QPushButton("All") button.setStyleSheet(textButtonStyle) button.clicked.connect(partial(self.selectCollection, "All")) collectionsLayout.addWidget(button) count = 0 for collection in sorted(config.bibleCollections.keys()): button = QPushButton(collection) button.setStyleSheet(textButtonStyle) button.clicked.connect( partial(self.selectCollection, collection)) collectionsLayout.addWidget(button) count += 1 if count > 5: count = 0 self.biblesBoxContainer.addLayout(collectionsLayout) collectionsLayout = self.newRowLayout() self.biblesBoxContainer.addLayout(collectionsLayout) self.bibleBoxWidget = QWidget() self.bibleBoxLayout = QVBoxLayout() self.bibleBoxLayout.setContentsMargins(0, 0, 0, 0) self.bibleBoxLayout.setSpacing(1) row_layout = self.newRowLayout() row_layout.setContentsMargins(0, 0, 0, 0) row_layout.setSpacing(1) biblesSqlite = BiblesSqlite() bibles = biblesSqlite.getBibleList() count = 0 for bible in bibles: button = QPushButton(bible) if bible in config.bibleDescription: button.setToolTip("{0}".format(config.bibleDescription[bible])) button.clicked.connect(partial(self.bibleAction, bible)) row_layout.addWidget(button) count += 1 if count > 6: count = 0 self.bibleBoxLayout.addLayout(row_layout) row_layout = self.newRowLayout() self.bibleButtons[bible] = button self.bibleBoxLayout.addLayout(row_layout) self.bibleBoxLayout.addStretch() self.biblesBoxContainer.addLayout(self.bibleBoxLayout) self.biblesBoxContainer.addStretch() self.biblesBox.setLayout(self.biblesBoxContainer) self.tabs.addTab(self.biblesBox, config.thisTranslation["translations"]) # Commentaries tab commentaries_box = QWidget() box_layout = QVBoxLayout() box_layout.setContentsMargins(0, 0, 0, 0) box_layout.setSpacing(1) row_layout = self.newRowLayout() button = QPushButton(config.thisTranslation["activeOnly"]) button.setStyleSheet(textButtonStyle) button.clicked.connect(self.activeCommentaries) row_layout.addWidget(button) box_layout.addLayout(row_layout) row_layout = self.newRowLayout() commentaries = Commentary().getCommentaryList() count = 0 for commentary in commentaries: button = QPushButton(commentary) button.setToolTip(Commentary.fileLookup[commentary]) button.clicked.connect(partial(self.commentaryAction, commentary)) self.commentaryButtons[commentary] = button row_layout.addWidget(button) count += 1 if count > 6: count = 0 box_layout.addLayout(row_layout) row_layout = self.newRowLayout() box_layout.addLayout(row_layout) box_layout.addStretch() commentaries_box.setLayout(box_layout) self.tabs.addTab(commentaries_box, config.thisTranslation["commentaries"]) # Lexicons tab lexicons_box = QWidget() box_layout = QVBoxLayout() box_layout.setContentsMargins(0, 0, 0, 0) box_layout.setSpacing(1) row_layout = self.newRowLayout() lexicons = LexiconData().lexiconList count = 0 for lexicon in lexicons: button = QPushButton(lexicon) if lexicon in config.lexiconDescription: button.setToolTip("{0}".format( config.lexiconDescription[lexicon])) button.clicked.connect(partial(self.lexiconAction, lexicon)) row_layout.addWidget(button) count += 1 if count > 6: count = 0 box_layout.addLayout(row_layout) row_layout = self.newRowLayout() box_layout.addLayout(row_layout) box_layout.addStretch() lexicons_box.setLayout(box_layout) self.tabs.addTab(lexicons_box, config.thisTranslation["lexicons"]) # Dictionaries tab dictionaries_box = QWidget() box_layout = QVBoxLayout() box_layout.setContentsMargins(0, 0, 0, 0) box_layout.setSpacing(1) row_layout = self.newRowLayout() dictionaries = IndexesSqlite().dictionaryList count = 0 for dictionary in dictionaries: button = QPushButton(dictionary[0]) button.setToolTip(dictionary[1]) button.clicked.connect( partial(self.dictionaryAction, dictionary[0])) row_layout.addWidget(button) count += 1 if count > 6: count = 0 box_layout.addLayout(row_layout) row_layout = self.newRowLayout() box_layout.addLayout(row_layout) box_layout.addStretch() dictionaries_box.setLayout(box_layout) self.tabs.addTab(dictionaries_box, config.thisTranslation["dictionaries"]) # Book intros tab bookIntros_box = QWidget() box_layout = QVBoxLayout() box_layout.setContentsMargins(0, 0, 0, 0) box_layout.setSpacing(1) row_layout = self.newRowLayout() button = QPushButton(config.thisTranslation["activeOnly"]) button.setStyleSheet(textButtonStyle) button.clicked.connect(self.activeBookIntros) row_layout.addWidget(button) box_layout.addLayout(row_layout) row_layout = self.newRowLayout() commentaries = Commentary().getCommentaryList() count = 0 for commentary in commentaries: button = QPushButton(commentary) button.setToolTip(Commentary.fileLookup[commentary]) button.clicked.connect(partial(self.bookIntroAction, commentary)) self.bookIntroButtons[commentary] = button row_layout.addWidget(button) count += 1 if count > 6: count = 0 box_layout.addLayout(row_layout) row_layout = self.newRowLayout() box_layout.addLayout(row_layout) box_layout.addStretch() bookIntros_box.setLayout(box_layout) self.tabs.addTab(bookIntros_box, config.thisTranslation["bookIntro"]) # Devotionals tab if len(self.devotionals) > 0: devotionals_box = QWidget() box_layout = QVBoxLayout() box_layout.setContentsMargins(0, 0, 0, 0) box_layout.setSpacing(1) row_layout = self.newRowLayout() count = 0 for file in self.devotionals: name = Path(file).stem button = QPushButton(name) # button.setToolTip(dictionary[1]) button.clicked.connect(partial(self.devotionalAction, name)) row_layout.addWidget(button) count += 1 if count > 2: count = 0 box_layout.addLayout(row_layout) row_layout.addStretch() row_layout = self.newRowLayout() for i in range(count, 3): button = QPushButton("") row_layout.addWidget(button) box_layout.addLayout(row_layout) box_layout.addStretch() devotionals_box.setLayout(box_layout) self.tabs.addTab(devotionals_box, config.thisTranslation["devotionals"]) self.tabs.setCurrentIndex(config.miniControlInitialTab) self.setLayout(mainLayout) def populateBooksButtons(self, bibleName): books = Bible(bibleName).getBookList() if self.bible_layout is not None: while self.bible_layout.count(): child = self.bible_layout.takeAt(0) if child.widget(): child.widget().deleteLater() else: self.bible_layout = QVBoxLayout() self.bible_layout.setContentsMargins(0, 0, 0, 0) self.bible_layout.setSpacing(1) for bookNumGp in self.bookNumGps: gp = QWidget() layout = self.newRowLayout() for bookNum in bookNumGp: if int(bookNum) in books: text = self.bookMap[bookNum] button = QPushButton(text) if config.developer: button.setToolTip("{0} - {1}".format( BibleBooks.eng[bookNum][1], bookNum)) else: button.setToolTip("{0}".format( BibleBooks.eng[bookNum][1])) button.clicked.connect( partial(self.bibleBookAction, bookNum)) layout.addWidget(button) gp.setLayout(layout) self.bible_layout.addWidget(gp) # for bookNumGp in self.bookNumGps[5:]: # gp = QWidget() # layout = self.newRowLayout() # for bookNum in bookNumGp: # text = self.bookMap[bookNum] # button = QPushButton(text) # button.clicked.connect(partial(self.bibleBookAction, bookNum)) # layout.addWidget(button) # gp.setLayout(layout) # bible_layout.addWidget(gp) self.bible_layout.addStretch() self.bible.setLayout(self.bible_layout) def newRowLayout(self): row_layout = QHBoxLayout() row_layout.setContentsMargins(0, 0, 0, 0) row_layout.setSpacing(1) return row_layout def tabChanged(self, index): prefix = "" if index == 0: prefix = "BIBLE:::{0}:::".format(config.mainText) elif index == 1: prefix = "TEXT:::" elif index == 2: prefix = "COMMENTARY:::{0}:::".format(config.commentaryText) elif index == 3: prefix = "LEXICON:::" elif index == 4: prefix = "SEARCHTOOL:::" if not config.clearCommandEntry: self.searchLineEdit.setText(prefix) def searchLineEntered(self): saveOpenBibleWindowContentOnNextTab = config.openBibleWindowContentOnNextTab searchString = self.searchLineEdit.text() if ":::" not in searchString or ":::{0}:::".format( config.mainText) in searchString: config.openBibleWindowContentOnNextTab = False self.parent.textCommandLineEdit.setText(searchString) self.parent.runTextCommand(searchString) self.searchLineEdit.setFocus() self.populateBooksButtons(config.mainText) config.openBibleWindowContentOnNextTab = saveOpenBibleWindowContentOnNextTab #def setTtsDefaultLanguage(self): #config.ttsDefaultLangauge = self.languageCodes[self.languageCombo.currentIndex()] def speakCommandFieldText(self): text = self.searchLineEdit.text() if ":::" in text: text = text.split(":::")[-1] command = "SPEAK:::{0}:::{1}".format( self.languageCodes[self.languageCombo.currentIndex()], text) self.runCommmand(command) def bibleBookAction(self, book): command = "{0} ".format(self.bookMap[book]) self.runCommmand(command) self.searchLineEdit.setFocus() def keyEntryAction(self, key): text = self.searchLineEdit.text() if key == "X": text = "" elif key == "<": text = text[:-1] else: text += key self.searchLineEdit.setText(text) def bibleAction(self, bible): command = "BIBLE:::{0}:::{1}".format( bible, self.parent.verseReference("main")[1]) self.runCommmand(command) command = "_bibleinfo:::{0}".format(bible) self.parent.runTextCommand(command) self.populateBooksButtons(config.mainText) def commentaryAction(self, commentary): command = "COMMENTARY:::{0}:::{1}".format( commentary, self.parent.verseReference("main")[1]) self.runCommmand(command) command = "_commentaryinfo:::{0}".format(commentary) self.parent.runTextCommand(command) def bookIntroAction(self, commentary): command = "COMMENTARY:::{0}:::{1}".format( commentary, BibleBooks().eng[str(config.mainB)][-1]) self.runCommmand(command) command = "_commentaryinfo:::{0}".format(commentary) self.parent.runTextCommand(command) def devotionalAction(self, devotional): command = "DEVOTIONAL:::{0}".format(devotional) self.runCommmand(command) def lexiconAction(self, lexicon): searchString = self.searchLineEdit.text() if ":::" not in searchString: TextCommandParser.last_lexicon_entry = searchString command = "SEARCHLEXICON:::{0}:::{1}".format( lexicon, TextCommandParser.last_lexicon_entry) self.runCommmand(command) def dictionaryAction(self, dictionary): searchString = self.searchLineEdit.text() if ":::" not in searchString: TextCommandParser.last_text_search = searchString command = "SEARCHTOOL:::{0}:::{1}".format( dictionary, TextCommandParser.last_text_search) self.runCommmand(command) def runCommmand(self, command): self.searchLineEdit.setText(command) self.parent.runTextCommand(command) self.parent.textCommandLineEdit.setText(command) self.populateBooksButtons(config.mainText) def selectCollection(self, collection): if not collection == "All": biblesInCollection = config.bibleCollections[collection] for bible in self.bibleButtons.keys(): button = self.bibleButtons[bible] if collection == "All": button.setEnabled(True) button.setStyleSheet("") else: if bible in biblesInCollection: button.setEnabled(True) button.setStyleSheet("") else: button.setEnabled(False) button.setStyleSheet(self.textButtonStyleDisabled) def activeCommentaries(self): activeCommentaries = [ item[0] for item in Commentary().getCommentaryListThatHasBookAndChapter( config.mainB, config.mainC) ] for commentary in self.commentaryButtons.keys(): button = self.commentaryButtons[commentary] if commentary in activeCommentaries: button.setEnabled(True) button.setStyleSheet("") else: button.setEnabled(False) button.setStyleSheet(self.textButtonStyleDisabled) def activeBookIntros(self): activeCommentaries = [ item[0] for item in Commentary().getCommentaryListThatHasBookAndChapter( config.mainB, 0) ] for commentary in self.bookIntroButtons.keys(): button = self.bookIntroButtons[commentary] if commentary in activeCommentaries: button.setEnabled(True) button.setStyleSheet("") else: button.setEnabled(False) button.setStyleSheet(self.textButtonStyleDisabled)
def __init__(self, layer): super().__init__() self.layer = layer layer.events.select.connect(self._on_select) layer.events.deselect.connect(self._on_deselect) layer.events.name.connect(self._on_layer_name_change) layer.events.blending.connect(self._on_blending_change) layer.events.opacity.connect(self._on_opacity_change) layer.events.visible.connect(self._on_visible_change) self.setObjectName('layer') self.grid_layout = QGridLayout() cb = QCheckBox(self) cb.setObjectName('visibility') cb.setToolTip('Layer visibility') cb.setChecked(self.layer.visible) cb.setProperty('mode', 'visibility') cb.stateChanged.connect(lambda state=cb: self.changeVisible(state)) self.visibleCheckBox = cb self.grid_layout.addWidget(cb, 0, 0) textbox = QLineEdit(self) textbox.setText(layer.name) textbox.home(False) textbox.setToolTip('Layer name') textbox.setFixedWidth(122) textbox.setAcceptDrops(False) textbox.setEnabled(True) textbox.editingFinished.connect(self.changeText) self.nameTextBox = textbox self.grid_layout.addWidget(textbox, 0, 1) self.grid_layout.addWidget(QLabel('opacity:'), 1, 0) sld = QSlider(Qt.Horizontal, self) sld.setFocusPolicy(Qt.NoFocus) sld.setFixedWidth(110) sld.setMinimum(0) sld.setMaximum(100) sld.setSingleStep(1) sld.setValue(self.layer.opacity * 100) sld.valueChanged[int].connect( lambda value=sld: self.changeOpacity(value)) self.opacitySilder = sld self.grid_layout.addWidget(sld, 1, 1) blend_comboBox = QComboBox() for blend in self.layer._blending_modes: blend_comboBox.addItem(blend) index = blend_comboBox.findText(self.layer.blending, Qt.MatchFixedString) blend_comboBox.setCurrentIndex(index) blend_comboBox.activated[str].connect( lambda text=blend_comboBox: self.changeBlending(text)) self.blendComboBox = blend_comboBox self.grid_layout.addWidget(QLabel('blending:'), 2, 0) self.grid_layout.addWidget(blend_comboBox, 2, 1) self.setLayout(self.grid_layout) msg = 'Click to select\nDrag to rearrange\nDouble click to expand' self.setToolTip(msg) self.setExpanded(False) self.setFixedWidth(250) self.grid_layout.setColumnMinimumWidth(0, 100) self.grid_layout.setColumnMinimumWidth(1, 100) self.layer.selected = True
class ConfigDialog(QDialog): """A dialog to set values in cnapy-config.txt""" def __init__(self, appdata: CnaData): QDialog.__init__(self) self.setWindowTitle("Configure CNApy") cross_icon = QIcon(":/icons/cross.png") cross = cross_icon.pixmap(QSize(32, 32)) self.appdata = appdata self.oeng = appdata.octave_engine self.meng = appdata.matlab_engine self.layout = QVBoxLayout() self.cna_ok = False descr = QLabel("\ Some functionalities in CNApy need a working CNA installation.\n \ To use CNA you need either Matlab >= R2019 or Octave >= 5 .\n \ Below you can choose a Matlab directory or the Octave executable.\n \ Only if one of the engines is green your CNA directory can be validated." ) self.layout.addWidget(descr) ml = QHBoxLayout() label = QLabel("Matlab") label.setFixedWidth(100) ml.addWidget(label) self.ml_label = QLabel() self.ml_label.setPixmap(cross) self.ml_label.setFixedWidth(100) ml.addWidget(self.ml_label) self.choose_ml_path_btn = QPushButton("Choose Matlab folder") self.choose_ml_path_btn.setFixedWidth(300) ml.addWidget(self.choose_ml_path_btn) label2 = QLabel("") label2.setFixedWidth(30) ml.addWidget(label2) self.matlab_path = QLabel() self.matlab_path.setMinimumWidth(200) self.matlab_path.setText(self.appdata.matlab_path) ml.addWidget(self.matlab_path) self.layout.addItem(ml) oc = QHBoxLayout() label = QLabel("Octave") label.setFixedWidth(100) oc.addWidget(label) self.oc_label = QLabel() self.oc_label.setPixmap(cross) self.oc_label.setFixedWidth(100) oc.addWidget(self.oc_label) self.choose_oc_exe_btn = QPushButton("Choose Octave octave-cli(.exe)") self.choose_oc_exe_btn.setFixedWidth(300) oc.addWidget(self.choose_oc_exe_btn) label2 = QLabel("") label2.setFixedWidth(30) oc.addWidget(label2) self.oc_exe = QLabel() self.oc_exe.setText(self.appdata.octave_executable) self.oc_exe.setMinimumWidth(200) oc.addWidget(self.oc_exe) self.layout.addItem(oc) h9 = QHBoxLayout() label = QLabel("Selected engine:") h9.addWidget(label) label2 = QLabel("") label2.setFixedWidth(30) h9.addWidget(label2) self.selected_engine = QComboBox() self.selected_engine.addItem("None") h9.addWidget(self.selected_engine) label2 = QLabel("") label2.setMinimumWidth(200) h9.addWidget(label2) self.layout.addItem(h9) cna_l = QHBoxLayout() label = QLabel("CNA") label.setFixedWidth(100) cna_l.addWidget(label) self.cna_label = QLabel() self.cna_label.setPixmap(cross) self.cna_label.setFixedWidth(100) cna_l.addWidget(self.cna_label) self.choose_cna_path_btn = QPushButton("Choose CNA directory") self.choose_cna_path_btn.setFixedWidth(300) cna_l.addWidget(self.choose_cna_path_btn) label2 = QLabel("") label2.setFixedWidth(30) cna_l.addWidget(label2) self.cna_path = QLabel() self.cna_path.setMinimumWidth(200) self.cna_path.setText(self.appdata.cna_path) cna_l.addWidget(self.cna_path) self.layout.addItem(cna_l) h2 = QHBoxLayout() label = QLabel("Default color for values in a scenario:") h2.addWidget(label) self.scen_color_btn = QPushButton() self.scen_color_btn.setFixedWidth(100) palette = self.scen_color_btn.palette() palette.setColor(QPalette.Button, self.appdata.scen_color) self.scen_color_btn.setPalette(palette) h2.addWidget(self.scen_color_btn) self.layout.addItem(h2) h3 = QHBoxLayout() label = QLabel( "Default color for computed values not part of the scenario:") h3.addWidget(label) self.comp_color_btn = QPushButton() self.comp_color_btn.setFixedWidth(100) palette = self.comp_color_btn.palette() palette.setColor(QPalette.Button, self.appdata.comp_color) self.comp_color_btn.setPalette(palette) h3.addWidget(self.comp_color_btn) self.layout.addItem(h3) h4 = QHBoxLayout() label = QLabel("Special Color used for non equal flux bounds:") h4.addWidget(label) self.spec1_color_btn = QPushButton() self.spec1_color_btn.setFixedWidth(100) palette = self.spec1_color_btn.palette() palette.setColor(QPalette.Button, self.appdata.special_color_1) self.spec1_color_btn.setPalette(palette) h4.addWidget(self.spec1_color_btn) self.layout.addItem(h4) h5 = QHBoxLayout() label = QLabel( "Special Color 2 used for non equal flux bounds that exclude 0:") h5.addWidget(label) self.spec2_color_btn = QPushButton() self.spec2_color_btn.setFixedWidth(100) palette = self.spec2_color_btn.palette() palette.setColor(QPalette.Button, self.appdata.special_color_2) self.spec2_color_btn.setPalette(palette) h5.addWidget(self.spec2_color_btn) self.layout.addItem(h5) h6 = QHBoxLayout() label = QLabel("Color used for empty reaction boxes:") h6.addWidget(label) self.default_color_btn = QPushButton() self.default_color_btn.setFixedWidth(100) palette = self.default_color_btn.palette() palette.setColor(QPalette.Button, self.appdata.default_color) self.default_color_btn.setPalette(palette) h6.addWidget(self.default_color_btn) self.layout.addItem(h6) h = QHBoxLayout() label = QLabel("Work directory:") h.addWidget(label) self.work_directory = QPushButton() self.work_directory.setText(self.appdata.work_directory) h.addWidget(self.work_directory) self.layout.addItem(h) h7 = QHBoxLayout() label = QLabel("Shown number of digits after the decimal point:") h7.addWidget(label) self.rounding = QLineEdit() self.rounding.setFixedWidth(100) self.rounding.setText(str(self.appdata.rounding)) validator = QIntValidator(0, 20, self) self.rounding.setValidator(validator) h7.addWidget(self.rounding) self.layout.addItem(h7) h8 = QHBoxLayout() label = QLabel( "Absolute tolerance used to compare float values in the UI:") h8.addWidget(label) self.abs_tol = QLineEdit() self.abs_tol.setFixedWidth(100) self.abs_tol.setText(str(self.appdata.abs_tol)) validator = QDoubleValidator(self) validator.setTop(1) self.abs_tol.setValidator(validator) h8.addWidget(self.abs_tol) self.layout.addItem(h8) l2 = QHBoxLayout() self.button = QPushButton("Apply Changes") self.cancel = QPushButton("Close") l2.addWidget(self.button) l2.addWidget(self.cancel) self.layout.addItem(l2) self.setLayout(self.layout) # Connecting the signal self.choose_ml_path_btn.clicked.connect(self.choose_ml_path) self.choose_oc_exe_btn.clicked.connect(self.choose_oc_exe) self.choose_cna_path_btn.clicked.connect(self.choose_cna_path) self.work_directory.clicked.connect(self.choose_work_directory) self.scen_color_btn.clicked.connect(self.choose_scen_color) self.comp_color_btn.clicked.connect(self.choose_comp_color) self.spec1_color_btn.clicked.connect(self.choose_spec1_color) self.spec2_color_btn.clicked.connect(self.choose_spec2_color) self.default_color_btn.clicked.connect(self.choose_default_color) self.selected_engine.currentTextChanged.connect(self.update) self.cancel.clicked.connect(self.reject) self.button.clicked.connect(self.apply) self.check_all() if self.meng is not None: self.selected_engine.insertItem(1, "Matlab") if self.appdata.selected_engine == "matlab": self.selected_engine.setCurrentIndex(1) if self.oeng is not None: self.selected_engine.insertItem(1, "Octave") if self.appdata.selected_engine == "octave": self.selected_engine.setCurrentIndex(1) self.update() def update(self): cross_icon = QIcon(":/icons/cross.png") cross = cross_icon.pixmap(QSize(32, 32)) check_icon = QIcon(":/icons/check.png") check = check_icon.pixmap(QSize(32, 32)) selected_engine = self.selected_engine.currentText() if selected_engine == "None": qmark_icon = QIcon(":/icons/qmark.png") qmark = qmark_icon.pixmap(QSize(32, 32)) self.cna_label.setPixmap(qmark) else: if self.cna_ok: self.cna_label.setPixmap(check) else: self.cna_label.setPixmap(cross) if self.oeng is not None: # disable button if octave is already working self.oc_label.setPixmap(check) else: self.oc_label.setPixmap(cross) if self.meng is not None: self.ml_label.setPixmap(check) else: self.ml_label.setPixmap(cross) self.selected_engine.currentTextChanged.disconnect(self.update) self.selected_engine.clear() self.selected_engine.addItem("None") if self.meng is not None: self.selected_engine.addItem("Matlab") if self.oeng is not None: self.selected_engine.addItem("Octave") # if selected_engine is "None": self.selected_engine.setCurrentIndex(0) if selected_engine == "Matlab": self.selected_engine.setCurrentIndex(1) if selected_engine == "Octave": if self.selected_engine.count() == 2: self.selected_engine.setCurrentIndex(1) elif self.selected_engine.count() == 3: self.selected_engine.setCurrentIndex(2) self.selected_engine.currentTextChanged.connect(self.update) def choose_ml_path(self): dialog = QFileDialog(self, directory=self.matlab_path.text()) dialog.setFileMode(QFileDialog.DirectoryOnly) directory: str = dialog.getExistingDirectory() if not directory or len( directory) == 0 or not os.path.exists(directory): return self.choose_ml_path_btn.setEnabled(False) self.matlab_path.setText(directory) self.try_install_matlab_engine(directory) self.check_matlab() self.choose_ml_path_btn.setEnabled(True) self.update() def try_install_matlab_engine(self, directory: str): try: path = os.path.join(directory, 'extern/engines/python') cwd = os.getcwd() os.chdir(path) temp_dir = TemporaryDirectory() os.system("python setup.py build --build-base=" + temp_dir.name + ' install') os.chdir(cwd) except FileNotFoundError: # no Matlab engine found pass def choose_oc_exe(self): dialog = QFileDialog(self, directory=self.oc_exe.text()) filename: str = dialog.getOpenFileName(directory=os.getcwd())[0] if not filename or len(filename) == 0 or not os.path.exists(filename): return self.oc_exe.setText(filename) if os.path.isfile(filename): os.environ['OCTAVE_EXECUTABLE'] = filename self.choose_oc_exe_btn.setEnabled(False) self.check_octave() self.choose_oc_exe_btn.setEnabled(True) self.update() def check_all(self): self.check_octave() self.check_matlab() self.check_cna() def check_octave(self): if self.oeng is None: self.oeng = try_octave_engine(self.oc_exe.text()) def check_matlab(self): # only recheck matlab if necessary if self.meng is None: self.meng = try_matlab_engine() def choose_cna_path(self): dialog = QFileDialog(self, directory=self.cna_path.text()) dialog.setFileMode(QFileDialog.DirectoryOnly) directory: str = dialog.getExistingDirectory() if not directory or len( directory) == 0 or not os.path.exists(directory): return self.cna_path.setText(directory) self.update() self.reset_engine() self.check_cna() self.update() def choose_work_directory(self): dialog = QFileDialog(self, directory=self.work_directory.text()) directory: str = dialog.getExistingDirectory() if not directory or len( directory) == 0 or not os.path.exists(directory): return self.work_directory.setText(directory) def reset_engine(self): # This resets the engines if self.oeng is None: self.meng = try_matlab_engine() else: self.oeng = try_octave_engine(self.oc_exe.text()) def check_cna(self): if self.oeng is not None: self.cna_ok = try_cna(self.oeng, self.cna_path.text()) elif self.meng is not None: self.cna_ok = try_cna(self.meng, self.cna_path.text()) def choose_scen_color(self): palette = self.scen_color_btn.palette() initial = palette.color(QPalette.Button) dialog = QColorDialog(self) color: str = dialog.getColor(initial) if color.isValid(): palette.setColor(QPalette.Button, color) self.scen_color_btn.setPalette(palette) def choose_comp_color(self): palette = self.comp_color_btn.palette() initial = palette.color(QPalette.Button) dialog = QColorDialog(self) color: str = dialog.getColor(initial) if color.isValid(): palette.setColor(QPalette.Button, color) self.comp_color_btn.setPalette(palette) def choose_spec1_color(self): palette = self.spec1_color_btn.palette() initial = palette.color(QPalette.Button) dialog = QColorDialog(self) color: str = dialog.getColor(initial) if color.isValid(): palette.setColor(QPalette.Button, color) self.spec1_color_btn.setPalette(palette) def choose_spec2_color(self): palette = self.spec2_color_btn.palette() initial = palette.color(QPalette.Button) dialog = QColorDialog(self) color: str = dialog.getColor(initial) if color.isValid(): palette.setColor(QPalette.Button, color) self.spec2_color_btn.setPalette(palette) def choose_default_color(self): palette = self.default_color_btn.palette() initial = palette.color(QPalette.Button) dialog = QColorDialog(self) color: str = dialog.getColor(initial) if color.isValid(): palette.setColor(QPalette.Button, color) self.default_color_btn.setPalette(palette) def apply(self): self.appdata.matlab_path = self.matlab_path.text() self.appdata.octave_executable = self.oc_exe.text() self.appdata.cna_path = self.cna_path.text() self.appdata.matlab_engine = self.meng self.appdata.octave_engine = self.oeng if self.selected_engine.currentText() == "None": self.appdata.selected_engine = None elif self.selected_engine.currentText() == "Matlab": self.appdata.selected_engine = "matlab" elif self.selected_engine.currentText() == "Octave": self.appdata.selected_engine = "octave" self.appdata.select_engine() self.appdata.window.disable_enable_dependent_actions() self.appdata.work_directory = self.work_directory.text() palette = self.scen_color_btn.palette() self.appdata.scen_color = palette.color(QPalette.Button) palette = self.comp_color_btn.palette() self.appdata.comp_color = palette.color(QPalette.Button) palette = self.spec1_color_btn.palette() self.appdata.special_color_1 = palette.color(QPalette.Button) palette = self.spec2_color_btn.palette() self.appdata.special_color_2 = palette.color(QPalette.Button) palette = self.default_color_btn.palette() self.appdata.default_color = palette.color(QPalette.Button) self.appdata.rounding = int(self.rounding.text()) self.appdata.abs_tol = float(self.abs_tol.text()) parser = configparser.ConfigParser() parser.add_section('cnapy-config') parser.set('cnapy-config', 'version', self.appdata.version) parser.set('cnapy-config', 'matlab_path', self.appdata.matlab_path) parser.set('cnapy-config', 'OCTAVE_EXECUTABLE', self.appdata.octave_executable) parser.set('cnapy-config', 'work_directory', self.appdata.work_directory) parser.set('cnapy-config', 'cna_path', self.appdata.cna_path) parser.set('cnapy-config', 'scen_color', str(self.appdata.scen_color.rgb())) parser.set('cnapy-config', 'comp_color', str(self.appdata.comp_color.rgb())) parser.set('cnapy-config', 'spec1_color', str(self.appdata.special_color_1.rgb())) parser.set('cnapy-config', 'spec2_color', str(self.appdata.special_color_2.rgb())) parser.set('cnapy-config', 'default_color', str(self.appdata.default_color.rgb())) parser.set('cnapy-config', 'rounding', str(self.appdata.rounding)) parser.set('cnapy-config', 'abs_tol', str(self.appdata.abs_tol)) parser.set('cnapy-config', 'selected_engine', str(self.appdata.selected_engine)) try: fp = open(self.appdata.conf_path, "w") except FileNotFoundError: os.makedirs( appdirs.user_config_dir("cnapy", roaming=True, appauthor=False)) fp = open(self.appdata.conf_path, "w") parser.write(fp) fp.close() self.accept()
class ContourOptionsDialog(QDialog): """ Dialog box for selecting contour options """ def __init__(self, contour_settings): super(ContourOptionsDialog, self).__init__(contour_settings.cubeviz_layout) self.setWindowFlags(self.windowFlags() | Qt.Tool) self.setWindowTitle("Contour Options") self.is_preview_active = False # preview mode? self.contour_settings = contour_settings # ref to caller ContourSettings self.image_viewer = self.contour_settings.image_viewer # ref to image viewer self.options = self.contour_settings.options # ref to ContourSettings options self._colormap_members = self.contour_settings.colormap_members # Colormap options self._colormap_index = DEFAULT_GLUE_COLORMAP_INDEX # Currently selected colormap if "cmap" in self.options: if self.options["cmap"] in self._colormap_members: self._colormap_index = self._colormap_members.index(self.options["cmap"]) # Is there a user spacing? if self.contour_settings.spacing is None: self.is_custom_spacing = False else: self.is_custom_spacing = True # Is there a user min? if self.contour_settings.vmin is None: self.is_vmin = False else: self.is_vmin = True # Is there a user max? if self.contour_settings.vmax is None: self.is_vmax = False else: self.is_vmax = True self.add_contour_label = self.contour_settings.add_contour_label # bool self._init_ui() def _init_ui(self): # Line 1: Color map self.colormap_label = QLabel("Color Scheme: ") self.colormap_combo = QColormapCombo() self.colormap_combo.addItem("", userData=UserDataWrapper(cm.viridis)) self.colormap_combo._update_icons() self.colormap_combo.setCurrentIndex(self._colormap_index) self.colormap_combo.setMaximumWidth(150) self.colormap_combo.currentIndexChanged.connect( self._on_colormap_change) # hbl is short for Horizontal Box Layout hbl1 = QHBoxLayout() hbl1.addWidget(self.colormap_label) hbl1.addWidget(self.colormap_combo) # Line 2: Display contour labels self.contour_label_checkBox = QCheckBox("Contour labels (font size):") if self.contour_settings.add_contour_label: self.contour_label_checkBox.setChecked(True) self.contour_label_checkBox.toggled.connect(self.toggle_labels) font_string = str(self.contour_settings.font_size) self.font_size_input = QLineEdit(font_string) self.font_size_input.setFixedWidth(150) self.font_size_input.setDisabled( not self.contour_settings.add_contour_label) hbl2 = QHBoxLayout() hbl2.addWidget(self.contour_label_checkBox) hbl2.addWidget(self.font_size_input) # Line 3: Contour Spacing self.custom_spacing_checkBox = QCheckBox("Contour spacing (interval):") if self.is_custom_spacing: self.custom_spacing_checkBox.setChecked(True) self.custom_spacing_checkBox.toggled.connect(self.custom_spacing) self.spacing_input = QLineEdit() self.spacing_input.setFixedWidth(150) self.spacing_input.setDisabled(not self.is_custom_spacing) spacing = "" if self.is_custom_spacing: spacing = str(self.contour_settings.spacing) elif self.contour_settings.data_spacing is not None: spacing = self.contour_settings.data_spacing spacing = "{0:1.4f}".format(spacing) self.spacing_default_text = spacing self.spacing_input.setText(spacing) hbl3 = QHBoxLayout() hbl3.addWidget(self.custom_spacing_checkBox) hbl3.addWidget(self.spacing_input) # Line 4: Vmax self.vmax_checkBox = QCheckBox("Set max:") self.vmax_input = QLineEdit() self.vmax_input.setFixedWidth(150) self.vmax_input.setDisabled(not self.is_vmax) vmax = "" if self.is_vmax: self.vmax_checkBox.setChecked(True) vmax = str(self.contour_settings.vmax) elif self.contour_settings.data_max is not None: vmax = self.contour_settings.data_max vmax = "{0:1.4f}".format(vmax) self.vmax_input.setText(vmax) self.vmax_default_text = vmax self.vmax_checkBox.toggled.connect(self.toggle_vmax) hbl4 = QHBoxLayout() hbl4.addWidget(self.vmax_checkBox) hbl4.addWidget(self.vmax_input) # Line 5: Vmin self.vmin_checkBox = QCheckBox("Set min:") self.vmin_input = QLineEdit() self.vmin_input.setFixedWidth(150) self.vmin_input.setDisabled(not self.is_vmin) vmin = "" if self.is_vmin: self.vmin_checkBox.setChecked(True) vmin = str(self.contour_settings.vmin) elif self.contour_settings.data_min is not None: vmin = self.contour_settings.data_min vmin = "{0:1.4f}".format(vmin) self.vmin_input.setText(vmin) self.vmin_default_text = vmin self.vmin_checkBox.toggled.connect(self.toggle_vmin) hbl5 = QHBoxLayout() hbl5.addWidget(self.vmin_checkBox) hbl5.addWidget(self.vmin_input) # Line f: self.previewButton = QPushButton("Preview") self.previewButton.clicked.connect(self.preview) self.defaultButton = QPushButton("Reset") self.defaultButton.clicked.connect(self.default) self.okButton = QPushButton("OK") self.okButton.clicked.connect(self.finish) self.okButton.setDefault(True) self.cancelButton = QPushButton("Cancel") self.cancelButton.clicked.connect(self.cancel) hblf = QHBoxLayout() hblf.addStretch(1) hblf.addWidget(self.previewButton) hblf.addWidget(self.defaultButton) hblf.addWidget(self.cancelButton) hblf.addWidget(self.okButton) vbl = QVBoxLayout() vbl.addLayout(hbl1) vbl.addLayout(hbl2) vbl.addLayout(hbl3) vbl.addLayout(hbl4) vbl.addLayout(hbl5) vbl.addLayout(hblf) self.setLayout(vbl) self.show() def update_data_vals(self, vmin="", vmax="", spacing="1"): self.vmin_default_text = vmin if not self.is_vmin: self.vmin_input.setText(vmin) self.vmax_default_text = vmax if not self.is_vmax: self.vmax_input.setText(vmax) self.spacing_default_text = spacing if not self.is_custom_spacing: self.spacing_input.setText(spacing) def _on_colormap_change(self, index): """Combo index changed handler""" self._colormap_index = index def custom_spacing(self): """Checkbox toggled handler""" if self.is_custom_spacing: self.is_custom_spacing = False self.spacing_input.setDisabled(True) spacing = "" if self.contour_settings.data_spacing: spacing = self.contour_settings.data_spacing spacing = "{0:1.4f}".format(spacing) self.spacing_input.setText(spacing) self.spacing_input.setStyleSheet("") else: self.is_custom_spacing = True self.spacing_input.setDisabled(False) def toggle_labels(self): """Checkbox toggled handler""" if self.add_contour_label: self.add_contour_label = False self.font_size_input.setDisabled(True) font_string = str(self.contour_settings.font_size) self.font_size_input.setText(font_string) self.font_size_input.setStyleSheet("") else: self.add_contour_label = True self.font_size_input.setDisabled(False) def toggle_vmax(self): """Checkbox toggled handler""" if self.is_vmax: self.is_vmax = False self.vmax_input.setDisabled(True) vmax = "" if self.contour_settings.data_max: vmax = self.contour_settings.data_max vmax = "{0:1.4f}".format(vmax) self.vmax_input.setText(vmax) self.vmax_input.setStyleSheet("") else: self.is_vmax = True self.vmax_input.setDisabled(False) def toggle_vmin(self): """Checkbox toggled handler""" if self.is_vmin: self.is_vmin = False self.vmin_input.setDisabled(True) vmin = "" if self.contour_settings.data_min: vmin = self.contour_settings.data_min vmin = "{0:1.4f}".format(vmin) self.vmin_input.setText(vmin) self.vmin_input.setStyleSheet("") else: self.is_vmin = True self.vmin_input.setDisabled(False) def input_validation(self): red = "background-color: rgba(255, 0, 0, 128);" def float_check(min_val=None): if user_input.text() == "": user_input.setStyleSheet(red) return False else: try: value = float(user_input.text()) if min_val is not None: if value <= min_val: user_input.setStyleSheet(red) return False else: user_input.setStyleSheet("") except ValueError: user_input.setStyleSheet(red) return False return True def int_check(min_val=None): if user_input.text() == "": user_input.setStyleSheet(red) return False else: try: value = int(user_input.text()) if min_val is not None: if value <= min_val: user_input.setStyleSheet(red) return False else: user_input.setStyleSheet("") except ValueError: user_input.setStyleSheet(red) return False return True success = True # Check 1: spacing_input if self.is_custom_spacing: user_input = self.spacing_input float_check(0) success = success and float_check() # Check 2: font_size_input if self.add_contour_label: user_input = self.font_size_input int_check(0) success = success and int_check() # Check 3: vmax if self.is_vmax: user_input = self.vmax_input float_check() success = success and float_check() # Check 4: vmax if self.is_vmin: user_input = self.vmin_input float_check() success = success and float_check() # Check 5: vmax and vmin if self.is_vmax and self.is_vmin and success: vmax = float(self.vmax_input.text()) vmin = float(self.vmin_input.text()) if vmax <= vmin: self.vmax_input.setStyleSheet(red) self.vmin_input.setStyleSheet(red) success = False return success def finish(self): """ Ok button pressed. Finalize options and send to image viewer """ success = self.input_validation() if not success: return # Change Color Map self._colormap_index = self.colormap_combo.currentIndex() colormap = self._colormap_members[self._colormap_index] self.contour_settings.options["cmap"] = colormap # labels self.contour_settings.add_contour_label = self.add_contour_label # font size if self.add_contour_label: font_size = int(self.font_size_input.text()) self.contour_settings.font_size = font_size else: self.contour_settings.font_size = DEFAULT_CONTOUR_FONT_SIZE # Spacing if self.is_custom_spacing: self.contour_settings.spacing = float(self.spacing_input.text()) else: self.contour_settings.spacing = None # vmax if self.is_vmax: vmax = float(self.vmax_input.text()) self.contour_settings.vmax = vmax self.contour_settings.options["vmax"] = vmax else: self.contour_settings.vmax = None self.contour_settings.options["vmax"] = None # vmin if self.is_vmin: vmin = float(self.vmin_input.text()) self.contour_settings.vmin = vmin self.contour_settings.options["vmin"] = vmin else: self.contour_settings.vmin = None self.contour_settings.options["vmin"] = None # Redraw contour if self.contour_settings.image_viewer.is_contour_active: self.contour_settings.draw_function() self.close() def preview(self): """ Prepare preview contour settings and send to image viewer """ success = self.input_validation() if not success: return image_viewer = self.contour_settings.image_viewer preview_settings = ContourSettings(image_viewer) preview_settings.dialog = self preview_settings.options = self.contour_settings.options.copy() preview_settings.spacing = self.contour_settings.spacing # Change Color Map self._colormap_index = self.colormap_combo.currentIndex() colormap = self._colormap_members[self._colormap_index] preview_settings.options["cmap"] = colormap # labels add_contour_label = self.contour_label_checkBox.isChecked() preview_settings.add_contour_label = add_contour_label # font size if add_contour_label: font_size = int(self.font_size_input.text()) preview_settings.font_size = font_size # Spacing if self.is_custom_spacing: preview_settings.spacing = float(self.spacing_input.text()) else: preview_settings.spacing = None # vmax if self.is_vmax: vmax = float(self.vmax_input.text()) preview_settings.vmax = vmax preview_settings.options["vmax"] = vmax else: preview_settings.vmax = None preview_settings.options["vmax"] = None # vmin if self.is_vmin: vmin = float(self.vmin_input.text()) preview_settings.vmin = vmin preview_settings.options["vmin"] = vmin else: preview_settings.vmin = None preview_settings.options["vmin"] = None # Redraw contour if image_viewer.is_contour_active: self.is_preview_active = True image_viewer.set_contour_preview(preview_settings) else: message = "Contour map is currently switched off. " \ "Please turn on the contour map by selecting " \ "a component from the contour map drop-down menu." info = QMessageBox.critical(self, "Error", message) def default(self): """ Set options back to default and send to image viewer """ self.contour_settings.options = self.contour_settings.default_options() self.contour_settings.spacing = None self.contour_settings.font_size = DEFAULT_CONTOUR_FONT_SIZE self.contour_settings.vmax = None self.contour_settings.vmin = None self.contour_settings.add_contour_label = False if self.contour_settings.image_viewer.is_contour_active: self.contour_settings.draw_function() self.contour_settings.options_dialog() def cancel(self): if self.contour_settings.image_viewer.is_contour_active: self.contour_settings.draw_function() self.close() def closeEvent(self, event): """closeEvent handler""" if self.is_preview_active: self.contour_settings.image_viewer.end_contour_preview() def keyPressEvent(self, e): if e.key() == Qt.Key_Escape: self.cancel()
class BufferWidget(QWidget): def __init__(self, buffer_settings): super(BufferWidget, self).__init__() # Settings self.buffer_settings = buffer_settings if not self.buffer_settings: self.buffer_settings['buffer_length'] = '{:.3f}'.format( BUFFERLENGTH) self.buffer_settings['sample_length'] = '{:.3f}'.format( SAMPLELENGTH) self.buffer_settings['delay_buffer'] = '{:.3f}'.format(DELAYBUFFER) self.buffer_settings['overwrite_depth'] = OVERWRITEDEPTH self.buffer_settings['electrode_settings'] = {} self.buffer_widgets = {} buffer_layout = QGridLayout(self) row = -1 if 'electrode_settings' in self.buffer_settings.keys(): for label, sett in self.buffer_settings[ 'electrode_settings'].items(): row += 1 buffer_layout.addWidget(QLabel(label), row, 0, 1, 1) self.buffer_widgets[label] = {} self.buffer_widgets[label]['chk_threshold'] = QCheckBox( "Threshold") self.buffer_widgets[label]['chk_threshold'].setChecked( bool(sett['threshold'])) self.buffer_widgets[label]['edit_validity'] = QLineEdit() self.buffer_widgets[label]['edit_validity'].setText( str(sett['validity'])) buffer_layout.addWidget( self.buffer_widgets[label]['chk_threshold'], row, 1, 1, 1) buffer_layout.addWidget(QLabel('Validity Threshold (%)'), row, 2, 1, 1) buffer_layout.addWidget( self.buffer_widgets[label]['edit_validity'], row, 3, 1, 1) row += 1 buffer_layout.addWidget(QLabel("Depth buffer size (s): "), row, 0, 1, 1) self.edit_buffer_length = QLineEdit( self.buffer_settings['buffer_length']) self.edit_buffer_length.setInputMask("0.000") self.edit_buffer_length.setFixedWidth(40) buffer_layout.addWidget(self.edit_buffer_length, row, 1, 1, 1) row += 1 buffer_layout.addWidget(QLabel("Depth samples size (s): "), row, 0, 1, 1) self.edit_sample_length = QLineEdit( self.buffer_settings['sample_length']) self.edit_sample_length.setInputMask("0.000") self.edit_sample_length.setFixedWidth(40) buffer_layout.addWidget(self.edit_sample_length, row, 1, 1, 1) row += 1 buffer_layout.addWidget(QLabel("Delay depth recording (s): "), row, 0, 1, 1) self.delay_buffer = QLineEdit(self.buffer_settings['delay_buffer']) self.delay_buffer.setInputMask("0.000") self.delay_buffer.setFixedWidth(40) buffer_layout.addWidget(self.delay_buffer, row, 1, 1, 1) row += 1 self.overwrite_depth = QCheckBox("Overwrite depth values") self.overwrite_depth.setChecked( self.buffer_settings['overwrite_depth']) buffer_layout.addWidget(self.overwrite_depth, row, 0, 1, 1) def to_dict(self): # convert all fields to dictionary and return it self.buffer_settings['buffer_length'] = self.edit_buffer_length.text() self.buffer_settings['sample_length'] = self.edit_sample_length.text() self.buffer_settings['delay_buffer'] = self.delay_buffer.text() self.buffer_settings[ 'overwrite_depth'] = self.overwrite_depth.isChecked() for key, value in self.buffer_widgets.items(): self.buffer_settings['electrode_settings'][key] = {} self.buffer_settings['electrode_settings'][key][ 'threshold'] = value['chk_threshold'].isChecked() self.buffer_settings['electrode_settings'][key][ 'validity'] = float(value['edit_validity'].text())
class MiniControl(QWidget): def __init__(self, parent): super().__init__() self.setWindowTitle(config.thisTranslation["remote_control"]) self.parent = parent # specify window size if config.qtMaterial and config.qtMaterialTheme: self.resizeWindow(1 / 2, 1 / 3) else: self.resizeWindow(2 / 5, 1 / 3) self.resizeEvent = (lambda old_method: (lambda event: (self.onResized(event), old_method(event))[-1]))( self.resizeEvent) # setup interface self.setupUI() # window appearance def resizeWindow(self, widthFactor, heightFactor): availableGeometry = QGuiApplication.instance().desktop( ).availableGeometry() self.setMinimumWidth(500) self.resize(availableGeometry.width() * widthFactor, availableGeometry.height() * heightFactor) def onResized(self, event): pass def closeEvent(self, event): config.miniControl = False # manage key capture def event(self, event): if event.type() == QEvent.KeyRelease: if event.modifiers() == Qt.ControlModifier: if event.key() == Qt.Key_B: self.tabs.setCurrentIndex(0) elif event.key() == Qt.Key_T: self.tabs.setCurrentIndex(1) elif event.key() == Qt.Key_C: self.tabs.setCurrentIndex(2) elif event.key() == Qt.Key_L: self.tabs.setCurrentIndex(3) elif event.key() == Qt.Key_D: self.tabs.setCurrentIndex(4) elif event.key() == Qt.Key_Escape: self.close() return QWidget.event(self, event) # setup ui def setupUI(self): mainLayout = QGridLayout() commandBox = QVBoxLayout() commandBox.setSpacing(3) commandBar = QWidget() commandLayout1 = QBoxLayout(QBoxLayout.LeftToRight) commandLayout1.setSpacing(5) self.searchLineEdit = QLineEdit() self.searchLineEdit.setClearButtonEnabled(True) self.searchLineEdit.setToolTip( config.thisTranslation["enter_command_here"]) self.searchLineEdit.returnPressed.connect(self.searchLineEntered) self.searchLineEdit.setFixedWidth(300) commandLayout1.addWidget(self.searchLineEdit) enterButton = QPushButton(config.thisTranslation["enter"]) enterButton.setFixedWidth(100) enterButton.clicked.connect(self.searchLineEntered) commandLayout1.addWidget(enterButton) commandLayout1.addStretch() commandBox.addLayout(commandLayout1) commandLayout2 = QBoxLayout(QBoxLayout.LeftToRight) commandLayout2.setSpacing(5) keys = [ '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', ':', '-', ',', '.', ' ', '<', 'X' ] for key in keys: button = QPushButton(key) button.setMaximumWidth(30) button.clicked.connect(partial(self.keyEntryAction, key)) commandLayout2.addWidget(button) commandLayout2.addStretch() commandBox.addLayout(commandLayout2) if config.isTtsInstalled: ttsLayout = QBoxLayout(QBoxLayout.LeftToRight) ttsLayout.setSpacing(5) self.languageCombo = QComboBox() ttsLayout.addWidget(self.languageCombo) if config.espeak: languages = TtsLanguages().isoLang2epeakLang else: languages = TtsLanguages().isoLang2qlocaleLang self.languageCodes = list(languages.keys()) for code in self.languageCodes: self.languageCombo.addItem(languages[code][1]) # Check if selected tts engine has the language user specify. if not (config.ttsDefaultLangauge in self.languageCodes): config.ttsDefaultLangauge = "en" # Set initial item initialIndex = self.languageCodes.index(config.ttsDefaultLangauge) self.languageCombo.setCurrentIndex(initialIndex) # setting tts default language here is confusing; better place in menu #setDefaultButton = QPushButton(config.thisTranslation["setDefault"]) #setDefaultButton.setFixedWidth(130) #setDefaultButton.clicked.connect(self.setTtsDefaultLanguage) #ttsLayout.addWidget(setDefaultButton) speakButton = QPushButton(config.thisTranslation["speak"]) speakButton.setFixedWidth(100) speakButton.clicked.connect(self.speakCommandFieldText) ttsLayout.addWidget(speakButton) stopButton = QPushButton(config.thisTranslation["stop"]) stopButton.setFixedWidth(100) stopButton.clicked.connect( self.parent.textCommandParser.stopTtsAudio) ttsLayout.addWidget(stopButton) ttsLayout.addStretch() commandBox.addLayout(ttsLayout) commandBar.setLayout(commandBox) mainLayout.addWidget(commandBar, 0, 0, Qt.AlignCenter) self.tabs = QTabWidget() self.tabs.currentChanged.connect(self.tabChanged) mainLayout.addWidget(self.tabs, 1, 0, Qt.AlignCenter) parser = BibleVerseParser(config.parserStandarisation) self.bookMap = parser.standardAbbreviation bookNums = list(self.bookMap.keys()) bookNumGps = [ bookNums[0:10], bookNums[10:20], bookNums[20:30], bookNums[30:39], bookNums[39:49], bookNums[49:59], bookNums[59:66], ] bible = QWidget() bible_layout = QVBoxLayout() bible_layout.setMargin(0) bible_layout.setSpacing(0) for bookNumGp in bookNumGps[0:5]: gp = QWidget() layout = self.newRowLayout() for bookNum in bookNumGp: text = self.bookMap[bookNum] button = QPushButton(text) button.clicked.connect(partial(self.bibleBookAction, bookNum)) layout.addWidget(button) gp.setLayout(layout) bible_layout.addWidget(gp) for bookNumGp in bookNumGps[5:]: gp = QWidget() layout = self.newRowLayout() for bookNum in bookNumGp: text = self.bookMap[bookNum] button = QPushButton(text) button.clicked.connect(partial(self.bibleBookAction, bookNum)) layout.addWidget(button) gp.setLayout(layout) bible_layout.addWidget(gp) bible_layout.addStretch() bible.setLayout(bible_layout) self.tabs.addTab(bible, config.thisTranslation["bible"]) bibles_box = QWidget() box_layout = QVBoxLayout() box_layout.setMargin(0) box_layout.setSpacing(0) row_layout = self.newRowLayout() biblesSqlite = BiblesSqlite() bibles = biblesSqlite.getBibleList() count = 0 for bible in bibles: button = QPushButton(bible) button.clicked.connect(partial(self.bibleAction, bible)) row_layout.addWidget(button) count += 1 if count > 6: count = 0 box_layout.addLayout(row_layout) row_layout = self.newRowLayout() box_layout.addLayout(row_layout) box_layout.addStretch() bibles_box.setLayout(box_layout) self.tabs.addTab(bibles_box, config.thisTranslation["translations"]) commentaries_box = QWidget() box_layout = QVBoxLayout() box_layout.setMargin(0) box_layout.setSpacing(0) row_layout = self.newRowLayout() commentaries = Commentary().getCommentaryList() count = 0 for commentary in commentaries: button = QPushButton(commentary) button.clicked.connect(partial(self.commentaryAction, commentary)) row_layout.addWidget(button) count += 1 if count > 6: count = 0 box_layout.addLayout(row_layout) row_layout = self.newRowLayout() box_layout.addLayout(row_layout) box_layout.addStretch() commentaries_box.setLayout(box_layout) self.tabs.addTab(commentaries_box, config.thisTranslation["commentaries"]) lexicons_box = QWidget() box_layout = QVBoxLayout() box_layout.setMargin(0) box_layout.setSpacing(0) row_layout = self.newRowLayout() lexicons = LexiconData().lexiconList count = 0 for lexicon in lexicons: button = QPushButton(lexicon) button.clicked.connect(partial(self.lexiconAction, lexicon)) row_layout.addWidget(button) count += 1 if count > 6: count = 0 box_layout.addLayout(row_layout) row_layout = self.newRowLayout() box_layout.addLayout(row_layout) box_layout.addStretch() lexicons_box.setLayout(box_layout) self.tabs.addTab(lexicons_box, config.thisTranslation["lexicons"]) dictionaries_box = QWidget() box_layout = QVBoxLayout() box_layout.setMargin(0) box_layout.setSpacing(0) row_layout = self.newRowLayout() dictionaries = IndexesSqlite().dictionaryList count = 0 for dictionary in dictionaries: button = QPushButton(dictionary[0]) button.setToolTip(dictionary[1]) button.clicked.connect( partial(self.dictionaryAction, dictionary[0])) row_layout.addWidget(button) count += 1 if count > 6: count = 0 box_layout.addLayout(row_layout) row_layout = self.newRowLayout() box_layout.addLayout(row_layout) box_layout.addStretch() dictionaries_box.setLayout(box_layout) self.tabs.addTab(dictionaries_box, config.thisTranslation["dictionaries"]) self.tabs.setCurrentIndex(config.miniControlInitialTab) self.setLayout(mainLayout) def newRowLayout(self): row_layout = QHBoxLayout() row_layout.setSpacing(0) row_layout.setMargin(0) return row_layout def tabChanged(self, index): prefix = "" if index == 0: prefix = "BIBLE:::{0}:::".format(config.mainText) elif index == 1: prefix = "TEXT:::" elif index == 2: prefix = "COMMENTARY:::{0}:::".format(config.commentaryText) elif index == 3: prefix = "LEXICON:::" elif index == 4: prefix = "SEARCHTOOL:::" if not config.clearCommandEntry: self.searchLineEdit.setText(prefix) def searchLineEntered(self): searchString = self.searchLineEdit.text() self.parent.textCommandLineEdit.setText(searchString) self.parent.runTextCommand(searchString) self.searchLineEdit.setFocus() #def setTtsDefaultLanguage(self): #config.ttsDefaultLangauge = self.languageCodes[self.languageCombo.currentIndex()] def speakCommandFieldText(self): text = self.searchLineEdit.text() if ":::" in text: text = text.split(":::")[-1] command = "SPEAK:::{0}:::{1}".format( self.languageCodes[self.languageCombo.currentIndex()], text) self.runCommmand(command) def bibleBookAction(self, book): command = "{0} ".format(self.bookMap[book]) self.runCommmand(command) self.searchLineEdit.setFocus() def keyEntryAction(self, key): text = self.searchLineEdit.text() if key == "X": text = "" elif key == "<": text = text[:-1] else: text += key self.searchLineEdit.setText(text) def bibleAction(self, bible): command = "BIBLE:::{0}:::{1}".format( bible, self.parent.verseReference("main")[1]) self.runCommmand(command) command = "_bibleinfo:::{0}".format(bible) self.parent.runTextCommand(command) def commentaryAction(self, commentary): command = "COMMENTARY:::{0}:::{1}".format( commentary, self.parent.verseReference("main")[1]) self.runCommmand(command) command = "_commentaryinfo:::{0}".format(commentary) self.parent.runTextCommand(command) def lexiconAction(self, lexicon): command = "LEXICON:::{0}:::{1}".format( lexicon, TextCommandParser.last_lexicon_entry) self.runCommmand(command) def dictionaryAction(self, dictionary): command = "SEARCHTOOL:::{0}:::{1}".format( dictionary, TextCommandParser.last_text_search) self.runCommmand(command) def runCommmand(self, command): self.searchLineEdit.setText(command) self.parent.runTextCommand(command) self.parent.textCommandLineEdit.setText(command)