def _create_switch(self, box, layout, col, labels): if labels is None: return None l = QLabel(labels[0], box) l.setMinimumHeight(20) l.setAlignment(Qt.AlignCenter | Qt.AlignBottom) font = l.font() font.setPointSize(7) font.setBold(True) l.setFont(font) layout.addWidget(l, 3, col, Qt.AlignBottom | Qt.AlignCenter) r1 = QRadioButton(box) r1.setStyleSheet( 'QRadioButton::indicator{subcontrol-position:center;}') layout.addWidget(r1, 4, col, Qt.AlignCenter) r2 = QRadioButton(box) r2.setStyleSheet( 'QRadioButton::indicator{subcontrol-position:center;}') layout.addWidget(r2, 5, col, Qt.AlignCenter) l = QLabel(labels[1], box) l.setAlignment(Qt.AlignCenter) l.setFont(font) layout.addWidget(l, 6, col, Qt.AlignTop | Qt.AlignCenter) g = QButtonGroup(box) g.addButton(r1) g.addButton(r2) r1.setChecked(True) return r2
class ApolloLabeledRSwitch(ApolloControl): def __init__(self, parent, text, lines=1, labelwidth=16, *args, **kwargs): super().__init__(parent, *args, **kwargs) # Make sure the text is bottom aligned in the specified number of lines text = "\n" * (lines - text.count("\n") - 1) + text self.label = QLabel(text, self) self.label.setFixedWidth(labelwidth) self.addWidget(self.label) self.layout.addSpacing(3) self.switch = QRadioButton(self) self.switch.setFixedSize(20, 20) self.switch.setStyleSheet( 'QRadioButton::indicator{ subcontrol-position:center; } QRadioButton { color: #666; }' ) self.addWidget(self.switch) self.addStretch()
def test_text(pixmap_differ: PixmapDiffer): actual: QPainter expected: QPainter with pixmap_differ.create_painters( 300, 240, 'scaled_radio_button_text') as (actual, expected): ex_widget = QWidget() ex_layout = QVBoxLayout(ex_widget) ex_radio1 = QRadioButton('Lorem ipsum') ex_radio2 = QRadioButton('Lorem ipsum') ex_font = ex_radio1.font() if ex_font.family() == 'Sans Serif': # Fonts are different on Travis CI. big_font_size = 26 small_font_size = 25 ex_radio1.setStyleSheet('QRadioButton::indicator {width: 26} ' 'QRadioButton {spacing: 13}') ex_radio2.setStyleSheet('QRadioButton::indicator {width: 25} ' 'QRadioButton {spacing: 12}') else: big_font_size = 29 small_font_size = 28 ex_radio1.setStyleSheet('QRadioButton::indicator {width: 29} ' 'QRadioButton {spacing: 14}') ex_radio2.setStyleSheet('QRadioButton::indicator {width: 28} ' 'QRadioButton {spacing: 14}') ex_font.setPointSize(big_font_size) ex_radio1.setFont(ex_font) ex_font.setPointSize(small_font_size) ex_radio2.setFont(ex_font) ex_size_policy = QSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) ex_radio1.setSizePolicy(ex_size_policy) ex_radio2.setSizePolicy(ex_size_policy) ex_layout.addWidget(ex_radio1) ex_layout.addWidget(ex_radio2) ex_layout.setStretch(0, 4) ex_layout.setStretch(1, 1) ex_widget.resize(300, 240) expected.drawPixmap(0, 0, ex_widget.grab()) widget = QWidget() layout = QVBoxLayout(widget) radio1 = ScaledRadioButton('Lorem ipsum') radio2 = ScaledRadioButton('Lorem ipsum') size_policy = QSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) radio1.setSizePolicy(size_policy) radio2.setSizePolicy(size_policy) layout.addWidget(radio1) layout.addWidget(radio2) layout.setStretch(0, 4) layout.setStretch(1, 1) widget.resize(300, 240) actual.drawPixmap(0, 0, widget.grab())
def _setup_ui(self): layout = QVBoxLayout(self) self.setLayout(layout) layout.setMargin(1) layout.setSpacing(1) layout.addSpacing(50) l = QLabel('BANK S', self) l.setMinimumHeight(20) l.setAlignment(Qt.AlignCenter | Qt.AlignBottom) font = l.font() font.setPointSize(7) font.setBold(True) l.setFont(font) layout.addWidget(l, Qt.AlignCenter) bank_s = QRadioButton(self) bank_s.setStyleSheet( 'QRadioButton::indicator{subcontrol-position:center;}') layout.addWidget(bank_s, Qt.AlignTop | Qt.AlignCenter) s_only = QRadioButton(self) s_only.setStyleSheet( 'QRadioButton::indicator{subcontrol-position:center;}') s_only.toggled.connect( lambda s: self._usbif.send(um.WriteControlBankS(s))) layout.addWidget(s_only, Qt.AlignTop | Qt.AlignCenter) l = QLabel('S ONLY', self) l.setAlignment(Qt.AlignCenter | Qt.AlignTop) l.setFont(font) layout.addWidget(l, Qt.AlignTop | Qt.AlignCenter) bank_s.setChecked(True)
class SCOUTS(QMainWindow): """Main Window Widget for SCOUTS.""" style = { 'title': 'QLabel {font-size: 18pt; font-weight: 600}', 'header': 'QLabel {font-size: 12pt; font-weight: 520}', 'label': 'QLabel {font-size: 10pt}', 'button': 'QPushButton {font-size: 10pt}', 'md button': 'QPushButton {font-size: 12pt}', 'run button': 'QPushButton {font-size: 18pt; font-weight: 600}', 'line edit': 'QLineEdit {font-size: 10pt}', 'checkbox': 'QCheckBox {font-size: 10pt}', 'radio button': 'QRadioButton {font-size: 10pt}' } def __init__(self) -> None: """SCOUTS Constructor. Defines all aspects of the GUI.""" # ### # ### Main Window setup # ### # Inherits from QMainWindow super().__init__() self.rootdir = get_project_root() self.threadpool = QThreadPool() # Sets values for QMainWindow self.setWindowTitle("SCOUTS") self.setWindowIcon( QIcon( os.path.abspath(os.path.join(self.rootdir, 'src', 'scouts.ico')))) # Creates StackedWidget as QMainWindow's central widget self.stacked_pages = QStackedWidget(self) self.setCentralWidget(self.stacked_pages) # Creates Widgets for individual "pages" and adds them to the StackedWidget self.main_page = QWidget() self.samples_page = QWidget() self.gating_page = QWidget() self.pages = (self.main_page, self.samples_page, self.gating_page) for page in self.pages: self.stacked_pages.addWidget(page) # ## Sets widget at program startup self.stacked_pages.setCurrentWidget(self.main_page) # ### # ### MAIN PAGE # ### # Main page layout self.main_layout = QVBoxLayout(self.main_page) # Title section # Title self.title = QLabel(self.main_page) self.title.setText('SCOUTS - Single Cell Outlier Selector') self.title.setStyleSheet(self.style['title']) self.title.adjustSize() self.main_layout.addWidget(self.title) # ## Input section # Input header self.input_header = QLabel(self.main_page) self.input_header.setText('Input settings') self.input_header.setStyleSheet(self.style['header']) self.main_layout.addChildWidget(self.input_header) self.input_header.adjustSize() self.main_layout.addWidget(self.input_header) # Input frame self.input_frame = QFrame(self.main_page) self.input_frame.setFrameShape(QFrame.StyledPanel) self.input_frame.setLayout(QFormLayout()) self.main_layout.addWidget(self.input_frame) # Input button self.input_button = QPushButton(self.main_page) self.input_button.setStyleSheet(self.style['button']) self.set_icon(self.input_button, 'x-office-spreadsheet') self.input_button.setObjectName('input') self.input_button.setText(' Select input file (.xlsx or .csv)') self.input_button.clicked.connect(self.get_path) # Input path box self.input_path = QLineEdit(self.main_page) self.input_path.setObjectName('input_path') self.input_path.setStyleSheet(self.style['line edit']) # Go to sample naming page self.samples_button = QPushButton(self.main_page) self.samples_button.setStyleSheet(self.style['button']) self.set_icon(self.samples_button, 'preferences-other') self.samples_button.setText(' Name samples...') self.samples_button.clicked.connect(self.goto_samples_page) # Go to gating page self.gates_button = QPushButton(self.main_page) self.gates_button.setStyleSheet(self.style['button']) self.set_icon(self.gates_button, 'preferences-other') self.gates_button.setText(' Gating && outlier options...') self.gates_button.clicked.connect(self.goto_gates_page) # Add widgets above to input frame Layout self.input_frame.layout().addRow(self.input_button, self.input_path) self.input_frame.layout().addRow(self.samples_button) self.input_frame.layout().addRow(self.gates_button) # ## Analysis section # Analysis header self.analysis_header = QLabel(self.main_page) self.analysis_header.setText('Analysis settings') self.analysis_header.setStyleSheet(self.style['header']) self.analysis_header.adjustSize() self.main_layout.addWidget(self.analysis_header) # Analysis frame self.analysis_frame = QFrame(self.main_page) self.analysis_frame.setFrameShape(QFrame.StyledPanel) self.analysis_frame.setLayout(QVBoxLayout()) self.main_layout.addWidget(self.analysis_frame) # Cutoff text self.cutoff_text = QLabel(self.main_page) self.cutoff_text.setText('Type of outlier to select:') self.cutoff_text.setToolTip( 'Choose whether to select outliers using the cutoff value from a reference\n' 'sample (OutR) or by using the cutoff value calculated for each sample\n' 'individually (OutS)') self.cutoff_text.setStyleSheet(self.style['label']) # Cutoff button group self.cutoff_group = QButtonGroup(self) # Cutoff by sample self.cutoff_sample = QRadioButton(self.main_page) self.cutoff_sample.setText('OutS') self.cutoff_sample.setObjectName('sample') self.cutoff_sample.setStyleSheet(self.style['radio button']) self.cutoff_sample.setChecked(True) self.cutoff_group.addButton(self.cutoff_sample) # Cutoff by reference self.cutoff_reference = QRadioButton(self.main_page) self.cutoff_reference.setText('OutR') self.cutoff_reference.setObjectName('ref') self.cutoff_reference.setStyleSheet(self.style['radio button']) self.cutoff_group.addButton(self.cutoff_reference) # Both cutoffs self.cutoff_both = QRadioButton(self.main_page) self.cutoff_both.setText('both') self.cutoff_both.setObjectName('sample ref') self.cutoff_both.setStyleSheet(self.style['radio button']) self.cutoff_group.addButton(self.cutoff_both) # Markers text self.markers_text = QLabel(self.main_page) self.markers_text.setStyleSheet(self.style['label']) self.markers_text.setText('Show results for:') self.markers_text.setToolTip( 'Individual markers: for each marker, select outliers\n' 'Any marker: select cells that are outliers for AT LEAST one marker' ) # Markers button group self.markers_group = QButtonGroup(self) # Single marker self.single_marker = QRadioButton(self.main_page) self.single_marker.setText('individual markers') self.single_marker.setObjectName('single') self.single_marker.setStyleSheet(self.style['radio button']) self.single_marker.setChecked(True) self.markers_group.addButton(self.single_marker) # Any marker self.any_marker = QRadioButton(self.main_page) self.any_marker.setText('any marker') self.any_marker.setObjectName('any') self.any_marker.setStyleSheet(self.style['radio button']) self.markers_group.addButton(self.any_marker) # Both methods self.both_methods = QRadioButton(self.main_page) self.both_methods.setText('both') self.both_methods.setObjectName('single any') self.both_methods.setStyleSheet(self.style['radio button']) self.markers_group.addButton(self.both_methods) # Tukey text self.tukey_text = QLabel(self.main_page) self.tukey_text.setStyleSheet(self.style['label']) # Tukey button group self.tukey_text.setText('Tukey factor:') self.tukey_group = QButtonGroup(self) # Low Tukey value self.tukey_low = QRadioButton(self.main_page) self.tukey_low.setText('1.5') self.tukey_low.setStyleSheet(self.style['radio button']) self.tukey_low.setChecked(True) self.tukey_group.addButton(self.tukey_low) # High Tukey value self.tukey_high = QRadioButton(self.main_page) self.tukey_high.setText('3.0') self.tukey_high.setStyleSheet(self.style['radio button']) self.tukey_group.addButton(self.tukey_high) # Add widgets above to analysis frame layout self.analysis_frame.layout().addWidget(self.cutoff_text) self.cutoff_buttons = QHBoxLayout() for button in self.cutoff_group.buttons(): self.cutoff_buttons.addWidget(button) self.analysis_frame.layout().addLayout(self.cutoff_buttons) self.analysis_frame.layout().addWidget(self.markers_text) self.markers_buttons = QHBoxLayout() for button in self.markers_group.buttons(): self.markers_buttons.addWidget(button) self.analysis_frame.layout().addLayout(self.markers_buttons) self.analysis_frame.layout().addWidget(self.tukey_text) self.tukey_buttons = QHBoxLayout() for button in self.tukey_group.buttons(): self.tukey_buttons.addWidget(button) self.tukey_buttons.addWidget(QLabel()) # aligns row with 2 buttons self.analysis_frame.layout().addLayout(self.tukey_buttons) # ## Output section # Output header self.output_header = QLabel(self.main_page) self.output_header.setText('Output settings') self.output_header.setStyleSheet(self.style['header']) self.output_header.adjustSize() self.main_layout.addWidget(self.output_header) # Output frame self.output_frame = QFrame(self.main_page) self.output_frame.setFrameShape(QFrame.StyledPanel) self.output_frame.setLayout(QFormLayout()) self.main_layout.addWidget(self.output_frame) # Output button self.output_button = QPushButton(self.main_page) self.output_button.setStyleSheet(self.style['button']) self.set_icon(self.output_button, 'folder') self.output_button.setObjectName('output') self.output_button.setText(' Select output folder') self.output_button.clicked.connect(self.get_path) # Output path box self.output_path = QLineEdit(self.main_page) self.output_path.setStyleSheet(self.style['line edit']) # Generate CSV checkbox self.output_csv = QCheckBox(self.main_page) self.output_csv.setText('Export multiple text files (.csv)') self.output_csv.setStyleSheet(self.style['checkbox']) self.output_csv.setChecked(True) # Generate XLSX checkbox self.output_excel = QCheckBox(self.main_page) self.output_excel.setText('Export multiple Excel spreadsheets (.xlsx)') self.output_excel.setStyleSheet(self.style['checkbox']) self.output_excel.clicked.connect(self.enable_single_excel) # Generate single, large XLSX checkbox self.single_excel = QCheckBox(self.main_page) self.single_excel.setText( 'Also save one multi-sheet Excel spreadsheet') self.single_excel.setToolTip( 'After generating all Excel spreadsheets, SCOUTS combines them into ' 'a single\nExcel spreadsheet where each sheet corresponds to an output' 'file from SCOUTS') self.single_excel.setStyleSheet(self.style['checkbox']) self.single_excel.setEnabled(False) self.single_excel.clicked.connect(self.memory_warning) # Add widgets above to output frame layout self.output_frame.layout().addRow(self.output_button, self.output_path) self.output_frame.layout().addRow(self.output_csv) self.output_frame.layout().addRow(self.output_excel) self.output_frame.layout().addRow(self.single_excel) # ## Run & help-quit section # Run button (stand-alone) self.run_button = QPushButton(self.main_page) self.set_icon(self.run_button, 'system-run') self.run_button.setText(' Run!') self.run_button.setStyleSheet(self.style['run button']) self.main_layout.addWidget(self.run_button) self.run_button.clicked.connect(self.run) # Help-quit frame (invisible) self.helpquit_frame = QFrame(self.main_page) self.helpquit_frame.setLayout(QHBoxLayout()) self.helpquit_frame.layout().setMargin(0) self.main_layout.addWidget(self.helpquit_frame) # Help button self.help_button = QPushButton(self.main_page) self.set_icon(self.help_button, 'help-about') self.help_button.setText(' Help') self.help_button.setStyleSheet(self.style['md button']) self.help_button.clicked.connect(self.get_help) # Quit button self.quit_button = QPushButton(self.main_page) self.set_icon(self.quit_button, 'process-stop') self.quit_button.setText(' Quit') self.quit_button.setStyleSheet(self.style['md button']) self.quit_button.clicked.connect(self.close) # Add widgets above to help-quit layout self.helpquit_frame.layout().addWidget(self.help_button) self.helpquit_frame.layout().addWidget(self.quit_button) # ### # ### SAMPLES PAGE # ### # Samples page layout self.samples_layout = QVBoxLayout(self.samples_page) # ## Title section # Title self.samples_title = QLabel(self.samples_page) self.samples_title.setText('Name your samples') self.samples_title.setStyleSheet(self.style['title']) self.samples_title.adjustSize() self.samples_layout.addWidget(self.samples_title) # Subtitle self.samples_subtitle = QLabel(self.samples_page) string = ( 'Please name the samples to be analysed by SCOUTS.\n\nSCOUTS searches the first ' 'column of your data\nand locates the exact string as part of the sample name.' ) self.samples_subtitle.setText(string) self.samples_subtitle.setStyleSheet(self.style['label']) self.samples_subtitle.adjustSize() self.samples_layout.addWidget(self.samples_subtitle) # ## Sample addition section # Sample addition frame self.samples_frame = QFrame(self.samples_page) self.samples_frame.setFrameShape(QFrame.StyledPanel) self.samples_frame.setLayout(QGridLayout()) self.samples_layout.addWidget(self.samples_frame) # Sample name box self.sample_name = QLineEdit(self.samples_page) self.sample_name.setStyleSheet(self.style['line edit']) self.sample_name.setPlaceholderText('Sample name ...') # Reference check self.is_reference = QCheckBox(self.samples_page) self.is_reference.setText('Reference?') self.is_reference.setStyleSheet(self.style['checkbox']) # Add sample to table self.add_sample_button = QPushButton(self.samples_page) QShortcut(QKeySequence("Return"), self.add_sample_button, self.write_to_sample_table) self.set_icon(self.add_sample_button, 'list-add') self.add_sample_button.setText(' Add sample (Enter)') self.add_sample_button.setStyleSheet(self.style['button']) self.add_sample_button.clicked.connect(self.write_to_sample_table) # Remove sample from table self.remove_sample_button = QPushButton(self.samples_page) QShortcut(QKeySequence("Delete"), self.remove_sample_button, self.remove_from_sample_table) self.set_icon(self.remove_sample_button, 'list-remove') self.remove_sample_button.setText(' Remove sample (Del)') self.remove_sample_button.setStyleSheet(self.style['button']) self.remove_sample_button.clicked.connect( self.remove_from_sample_table) # Add widgets above to sample addition layout self.samples_frame.layout().addWidget(self.sample_name, 0, 0) self.samples_frame.layout().addWidget(self.is_reference, 1, 0) self.samples_frame.layout().addWidget(self.add_sample_button, 0, 1) self.samples_frame.layout().addWidget(self.remove_sample_button, 1, 1) # ## Sample table self.sample_table = QTableWidget(self.samples_page) self.sample_table.setColumnCount(2) self.sample_table.setHorizontalHeaderItem(0, QTableWidgetItem('Sample')) self.sample_table.setHorizontalHeaderItem( 1, QTableWidgetItem('Reference?')) self.sample_table.horizontalHeader().setSectionResizeMode( 0, QHeaderView.Stretch) self.sample_table.horizontalHeader().setSectionResizeMode( 1, QHeaderView.ResizeToContents) self.samples_layout.addWidget(self.sample_table) # ## Save & clear buttons # Save & clear frame (invisible) self.saveclear_frame = QFrame(self.samples_page) self.saveclear_frame.setLayout(QHBoxLayout()) self.saveclear_frame.layout().setMargin(0) self.samples_layout.addWidget(self.saveclear_frame) # Clear samples button self.clear_samples = QPushButton(self.samples_page) self.set_icon(self.clear_samples, 'edit-delete') self.clear_samples.setText(' Clear table') self.clear_samples.setStyleSheet(self.style['md button']) self.clear_samples.clicked.connect(self.prompt_clear_data) # Save samples button self.save_samples = QPushButton(self.samples_page) self.set_icon(self.save_samples, 'document-save') self.save_samples.setText(' Save samples') self.save_samples.setStyleSheet(self.style['md button']) self.save_samples.clicked.connect(self.goto_main_page) # Add widgets above to save & clear layout self.saveclear_frame.layout().addWidget(self.clear_samples) self.saveclear_frame.layout().addWidget(self.save_samples) # ### # ### GATING PAGE # ### # Gating page layout self.gating_layout = QVBoxLayout(self.gating_page) # ## Title section # Title self.gates_title = QLabel(self.gating_page) self.gates_title.setText('Gating & outlier options') self.gates_title.setStyleSheet(self.style['title']) self.gates_title.adjustSize() self.gating_layout.addWidget(self.gates_title) # ## Gating options section # Gating header self.gate_header = QLabel(self.gating_page) self.gate_header.setText('Gating') self.gate_header.setStyleSheet(self.style['header']) self.gate_header.adjustSize() self.gating_layout.addWidget(self.gate_header) # Gating frame self.gate_frame = QFrame(self.gating_page) self.gate_frame.setFrameShape(QFrame.StyledPanel) self.gate_frame.setLayout(QFormLayout()) self.gating_layout.addWidget(self.gate_frame) # Gating button group self.gating_group = QButtonGroup(self) # Do not gate samples self.no_gates = QRadioButton(self.gating_page) self.no_gates.setObjectName('no_gate') self.no_gates.setText("Don't gate samples") self.no_gates.setStyleSheet(self.style['radio button']) self.no_gates.setChecked(True) self.gating_group.addButton(self.no_gates) self.no_gates.clicked.connect(self.activate_gate) # CyToF gating self.cytof_gates = QRadioButton(self.gating_page) self.cytof_gates.setObjectName('cytof') self.cytof_gates.setText('Mass Cytometry gating') self.cytof_gates.setStyleSheet(self.style['radio button']) self.cytof_gates.setToolTip( 'Exclude cells for which the average expression of all\n' 'markers is below the selected value') self.gating_group.addButton(self.cytof_gates) self.cytof_gates.clicked.connect(self.activate_gate) # CyToF gating spinbox self.cytof_gates_value = QDoubleSpinBox(self.gating_page) self.cytof_gates_value.setMinimum(0) self.cytof_gates_value.setMaximum(1) self.cytof_gates_value.setValue(0.1) self.cytof_gates_value.setSingleStep(0.05) self.cytof_gates_value.setEnabled(False) # scRNA-Seq gating self.rnaseq_gates = QRadioButton(self.gating_page) self.rnaseq_gates.setText('scRNA-Seq gating') self.rnaseq_gates.setStyleSheet(self.style['radio button']) self.rnaseq_gates.setToolTip( 'When calculating cutoff, ignore reads below the selected value') self.rnaseq_gates.setObjectName('rnaseq') self.gating_group.addButton(self.rnaseq_gates) self.rnaseq_gates.clicked.connect(self.activate_gate) # scRNA-Seq gating spinbox self.rnaseq_gates_value = QDoubleSpinBox(self.gating_page) self.rnaseq_gates_value.setMinimum(0) self.rnaseq_gates_value.setMaximum(10) self.rnaseq_gates_value.setValue(0) self.rnaseq_gates_value.setSingleStep(1) self.rnaseq_gates_value.setEnabled(False) # export gated population checkbox self.export_gated = QCheckBox(self.gating_page) self.export_gated.setText('Export gated cells as an output file') self.export_gated.setStyleSheet(self.style['checkbox']) self.export_gated.setEnabled(False) # Add widgets above to Gate frame layout self.gate_frame.layout().addRow(self.no_gates, QLabel()) self.gate_frame.layout().addRow(self.cytof_gates, self.cytof_gates_value) self.gate_frame.layout().addRow(self.rnaseq_gates, self.rnaseq_gates_value) self.gate_frame.layout().addRow(self.export_gated, QLabel()) # ## Outlier options section # Outlier header self.outlier_header = QLabel(self.gating_page) self.outlier_header.setText('Outliers') self.outlier_header.setStyleSheet(self.style['header']) self.outlier_header.adjustSize() self.gating_layout.addWidget(self.outlier_header) # Outlier frame self.outlier_frame = QFrame(self.gating_page) self.outlier_frame.setFrameShape(QFrame.StyledPanel) self.outlier_frame.setLayout(QVBoxLayout()) self.gating_layout.addWidget(self.outlier_frame) # Top outliers information self.top_outliers = QLabel(self.gating_page) self.top_outliers.setStyleSheet(self.style['label']) self.top_outliers.setText( 'By default, SCOUTS selects the top outliers from the population') self.top_outliers.setStyleSheet(self.style['label']) # Bottom outliers data self.bottom_outliers = QCheckBox(self.gating_page) self.bottom_outliers.setText('Include results for low outliers') self.bottom_outliers.setStyleSheet(self.style['checkbox']) # Non-outliers data self.not_outliers = QCheckBox(self.gating_page) self.not_outliers.setText('Include results for non-outliers') self.not_outliers.setStyleSheet(self.style['checkbox']) # Add widgets above to Gate frame layout self.outlier_frame.layout().addWidget(self.top_outliers) self.outlier_frame.layout().addWidget(self.bottom_outliers) self.outlier_frame.layout().addWidget(self.not_outliers) # ## Save/back button self.save_gates = QPushButton(self.gating_page) self.set_icon(self.save_gates, 'go-next') self.save_gates.setText(' Back to main menu') self.save_gates.setStyleSheet(self.style['md button']) self.gating_layout.addWidget(self.save_gates) self.save_gates.clicked.connect(self.goto_main_page) # ## Add empty label to take vertical space self.empty_label = QLabel(self.gating_page) self.empty_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.gating_layout.addWidget(self.empty_label) # ### # ### ICON SETTING # ### def set_icon(self, widget: QWidget, icon: str) -> None: """Associates an icon to a widget.""" i = QIcon() i.addPixmap( QPixmap( os.path.abspath( os.path.join(self.rootdir, 'src', 'default_icons', f'{icon}.svg')))) widget.setIcon(QIcon.fromTheme(icon, i)) # ### # ### STACKED WIDGET PAGE SWITCHING # ### def goto_main_page(self) -> None: """Switches stacked widget pages to the main page.""" self.stacked_pages.setCurrentWidget(self.main_page) def goto_samples_page(self) -> None: """Switches stacked widget pages to the samples table page.""" self.stacked_pages.setCurrentWidget(self.samples_page) def goto_gates_page(self) -> None: """Switches stacked widget pages to the gating & other options page.""" self.stacked_pages.setCurrentWidget(self.gating_page) # ### # ### MAIN PAGE GUI LOGIC # ### def get_path(self) -> None: """Opens a dialog box and sets the chosen file/folder path, depending on the caller widget.""" options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog sender_name = self.sender().objectName() if sender_name == 'input': query, _ = QFileDialog.getOpenFileName(self, "Select file", "", "All Files (*)", options=options) elif sender_name == 'output': query = QFileDialog.getExistingDirectory(self, "Select Directory", options=options) else: return if query: getattr(self, f'{sender_name}_path').setText(query) def enable_single_excel(self) -> None: """Enables checkbox for generating a single Excel output.""" if self.output_excel.isChecked(): self.single_excel.setEnabled(True) else: self.single_excel.setEnabled(False) self.single_excel.setChecked(False) # ### # ### SAMPLE NAME/SAMPLE TABLE GUI LOGIC # ### def write_to_sample_table(self) -> None: """Writes data to sample table.""" table = self.sample_table ref = 'no' sample = self.sample_name.text() if sample: for cell in range(table.rowCount()): item = table.item(cell, 0) if item.text() == sample: self.same_sample() return if self.is_reference.isChecked(): for cell in range(table.rowCount()): item = table.item(cell, 1) if item.text() == 'yes': self.more_than_one_reference() return ref = 'yes' sample = QTableWidgetItem(sample) is_reference = QTableWidgetItem(ref) is_reference.setFlags(Qt.ItemIsEnabled) row_position = table.rowCount() table.insertRow(row_position) table.setItem(row_position, 0, sample) table.setItem(row_position, 1, is_reference) self.is_reference.setChecked(False) self.sample_name.setText('') def remove_from_sample_table(self) -> None: """Removes data from sample table.""" table = self.sample_table rows = set(index.row() for index in table.selectedIndexes()) for index in sorted(rows, reverse=True): self.sample_table.removeRow(index) def prompt_clear_data(self) -> None: """Prompts option to clear all data in the sample table.""" if self.confirm_clear_data(): table = self.sample_table while table.rowCount(): self.sample_table.removeRow(0) # ### # ### GATING GUI LOGIC # ### def activate_gate(self) -> None: """Activates/deactivates buttons related to gating.""" if self.sender().objectName() == 'no_gate': self.cytof_gates_value.setEnabled(False) self.rnaseq_gates_value.setEnabled(False) self.export_gated.setEnabled(False) self.export_gated.setChecked(False) elif self.sender().objectName() == 'cytof': self.cytof_gates_value.setEnabled(True) self.rnaseq_gates_value.setEnabled(False) self.export_gated.setEnabled(True) elif self.sender().objectName() == 'rnaseq': self.cytof_gates_value.setEnabled(False) self.rnaseq_gates_value.setEnabled(True) self.export_gated.setEnabled(True) # ### # ### CONNECT SCOUTS TO ANALYTICAL MODULES # ### def run(self) -> None: """Runs SCOUTS as a Worker, based on user input in the GUI.""" try: data = self.parse_input() except Exception as error: trace = traceback.format_exc() self.propagate_error((error, trace)) else: data['widget'] = self worker = Worker(func=start_scouts, **data) worker.signals.started.connect(self.analysis_has_started) worker.signals.finished.connect(self.analysis_has_finished) worker.signals.success.connect(self.success_message) worker.signals.error.connect(self.propagate_error) self.threadpool.start(worker) def parse_input(self) -> Dict: """Returns user input on the GUI as a dictionary.""" # Input and output input_dict = { 'input_file': str(self.input_path.text()), 'output_folder': str(self.output_path.text()) } if not input_dict['input_file'] or not input_dict['output_folder']: raise NoIOPathError # Set cutoff by reference or by sample rule input_dict['cutoff_rule'] = self.cutoff_group.checkedButton( ).objectName() # 'sample', 'ref', 'sample ref' # Outliers for each individual marker or any marker in row input_dict['marker_rule'] = self.markers_group.checkedButton( ).objectName() # 'single', 'any', 'single any' # Tukey factor used for calculating cutoff input_dict['tukey_factor'] = float( self.tukey_group.checkedButton().text()) # '1.5', '3.0' # Output settings input_dict['export_csv'] = True if self.output_csv.isChecked( ) else False input_dict['export_excel'] = True if self.output_excel.isChecked( ) else False input_dict['single_excel'] = True if self.single_excel.isChecked( ) else False # Retrieve samples from sample table input_dict['sample_list'] = [] for tuples in self.yield_samples_from_table(): input_dict['sample_list'].append(tuples) if not input_dict['sample_list']: raise NoSampleError # Set gate cutoff (if any) input_dict['gating'] = self.gating_group.checkedButton().objectName( ) # 'no_gate', 'cytof', 'rnaseq' input_dict['gate_cutoff_value'] = None if input_dict['gating'] != 'no_gate': input_dict['gate_cutoff_value'] = getattr( self, f'{input_dict["gating"]}_gates_value').value() input_dict['export_gated'] = True if self.export_gated.isChecked( ) else False # Generate results for non-outliers input_dict['non_outliers'] = False if self.not_outliers.isChecked(): input_dict['non_outliers'] = True # Generate results for bottom outliers input_dict['bottom_outliers'] = False if self.bottom_outliers.isChecked(): input_dict['bottom_outliers'] = True # return dictionary with all gathered inputs return input_dict def yield_samples_from_table( self) -> Generator[Tuple[str, str], None, None]: """Yields sample names from the sample table.""" table = self.sample_table for cell in range(table.rowCount()): sample_name = table.item(cell, 0).text() sample_type = table.item(cell, 1).text() yield sample_name, sample_type # ### # ### MESSAGE BOXES # ### def analysis_has_started(self) -> None: """Disables run button while SCOUTS analysis is underway.""" self.run_button.setText(' Working...') self.run_button.setEnabled(False) def analysis_has_finished(self) -> None: """Enables run button after SCOUTS analysis has finished.""" self.run_button.setEnabled(True) self.run_button.setText(' Run!') def success_message(self) -> None: """Info message box used when SCOUTS finished without errors.""" title = "Analysis finished!" mes = "Your analysis has finished. No errors were reported." if self.stacked_pages.isEnabled() is True: QMessageBox.information(self, title, mes) def memory_warning(self) -> None: """Warning message box used when user wants to generate a single excel file.""" if self.sender().isChecked(): title = 'Memory warning!' mes = ( "Depending on your dataset, this option can consume a LOT of memory and take" " a long time to process. Please make sure that your computer can handle it!" ) QMessageBox.information(self, title, mes) def same_sample(self) -> None: """Error message box used when the user tries to input the same sample twice in the sample table.""" title = 'Error: sample name already in table' mes = ( "Sorry, you can't do this because this sample name is already in the table. " "Please select a different name.") QMessageBox.critical(self, title, mes) def more_than_one_reference(self) -> None: """Error message box used when the user tries to input two reference samples in the sample table.""" title = "Error: more than one reference selected" mes = ( "Sorry, you can't do this because there is already a reference column in the table. " "Please remove it before adding a reference.") QMessageBox.critical(self, title, mes) def confirm_clear_data(self) -> bool: """Question message box used to confirm user action of clearing sample table.""" title = 'Confirm Action' mes = "Table will be cleared. Are you sure?" reply = QMessageBox.question(self, title, mes, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: return True return False # ### # ### EXCEPTIONS & ERRORS # ### def propagate_error(self, error: Tuple[Exception, str]) -> None: """Calls the appropriate error message box based on type of Exception raised.""" if isinstance(error[0], NoIOPathError): self.no_io_path_error_message() elif isinstance(error[0], NoReferenceError): self.no_reference_error_message() elif isinstance(error[0], NoSampleError): self.no_sample_error_message() elif isinstance(error[0], PandasInputError): self.pandas_input_error_message() elif isinstance(error[0], SampleNamingError): self.sample_naming_error_message() else: self.generic_error_message(error) def no_io_path_error_message(self) -> None: """Message displayed when the user did not include an input file path, or an output folder path.""" title = 'Error: no file/folder' message = ("Sorry, no input file and/or output folder was provided. " "Please add the path to the necessary file/folder.") QMessageBox.critical(self, title, message) def no_reference_error_message(self) -> None: """Message displayed when the user wants to analyse cutoff based on a reference, but did not specify what sample corresponds to the reference.""" title = "Error: No reference selected" message = ( "Sorry, no reference sample was found on the sample list, but analysis was set to " "reference. Please add a reference sample, or change the rule for cutoff calculation." ) QMessageBox.critical(self, title, message) def no_sample_error_message(self) -> None: """Message displayed when the user did not add any samples to the sample table.""" title = "Error: No samples selected" message = ( "Sorry, the analysis cannot be performed because no sample names were input. " "Please add your sample names.") QMessageBox.critical(self, title, message) def pandas_input_error_message(self) -> None: """Message displayed when the input file cannot be read (likely because it is not a Excel or csv file).""" title = 'Error: unexpected input file' message = ( "Sorry, the input file could not be read. Please make sure that " "the data is save in a valid format (supported formats are: " ".csv, .xlsx).") QMessageBox.critical(self, title, message) def sample_naming_error_message(self) -> None: """Message displayed when none of the sample names passed by the user are found in the input DataFrame.""" title = 'Error: sample names not in input file' message = ( "Sorry, your sample names were not found in the input file. Please " "make sure that the names were typed correctly (case-sensitive).") QMessageBox.critical(self, title, message) def generic_error_message(self, error: Tuple[Exception, str]) -> None: """Error message box used to display any error message (including traceback) for any uncaught errors.""" title = 'An error occurred!' name, trace = error QMessageBox.critical(self, title, f"{str(name)}\n\nfull traceback:\n{trace}") def not_implemented_error_message(self) -> None: """Error message box used when the user accesses a functionality that hasn't been implemented yet.""" title = "Not yet implemented" mes = "Sorry, this functionality has not been implemented yet." QMessageBox.critical(self, title, mes) # ### # ### HELP & QUIT # ### @staticmethod def get_help() -> None: """Opens SCOUTS documentation on the browser. Called when the user clicks the "help" button""" webbrowser.open('https://scouts.readthedocs.io/en/master/') def closeEvent(self, event: QEvent) -> None: """Defines the message box for when the user wants to quit SCOUTS.""" title = 'Quit SCOUTS' mes = "Are you sure you want to quit?" reply = QMessageBox.question(self, title, mes, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: self.stacked_pages.setEnabled(False) message = self.quit_message() waiter = Waiter(waiter_func=self.threadpool.activeThreadCount) waiter.signals.started.connect(message.show) waiter.signals.finished.connect(message.destroy) waiter.signals.finished.connect(sys.exit) self.threadpool.start(waiter) event.ignore() def quit_message(self) -> QDialog: """Displays a window while SCOUTS is exiting""" message = QDialog(self) message.setWindowTitle('Exiting SCOUTS') message.resize(300, 50) label = QLabel('SCOUTS is exiting, please wait...', message) label.setStyleSheet(self.style['label']) label.adjustSize() label.setAlignment(Qt.AlignCenter) label.move(int((message.width() - label.width()) / 2), int((message.height() - label.height()) / 2)) return message
class MainWindow(QMainWindow): def __init__(self, ui_file, devMode, parent=None): super(MainWindow, self).__init__() self.uiFileName = ui_file # use this if there are multiple UI files if devMode == "development": # use ui file directly made by QDesigner uiFile = QFile(ui_file) uiFile.open(QFile.ReadOnly) # read in UI for the form loader = QUiLoader() self.window = loader.load(uiFile) uiFile.close() else: #deployment - use .py version of ui file, with slightly different setup self.ui = Ui_MainWindow() self.ui.setupUi(self) self.getParts() # identify form objects self.connectParts() # connect buttons to operations self.convs = Converters( ) # load converters for main conversion categories self.yc = YearConverters( ) # load converters for japanese years, zodiac years self.mess = Mess() # instructions and messages in local language self.validFloat = QDoubleValidator() self.validYear = QIntValidator() self.validYear.setRange(1, 9999) # used for years self.btnConvert.hide() self.widgetSetup("start") # initial conditions for form if devMode == "development": self.window.show() else: self.show() def widgetSetup(self, themode): # based on which main button is pressed self.themode = themode # this is set when a main button is pressed, or on initial load self.emptyConvLayout( ) # get rid of old radio buttons if they exist, hide input/output, etc. thetext, thestyle = makeHeader1( themode, self.uiFileName) # make heading for convType = themode self.header1.setStyleSheet( thestyle) # can have different background colors self.header1.setText(thetext) self.header1.show() self.hideBigInstructions() if themode in self.convs.getValidConvTypes( ): # set up radio buttons for conversions oneConvTypeInfo = self.convs.convTypeToConvInfo( themode) # get convCodes, displays for this convType for ix, (convCode, convDisplay) in enumerate( oneConvTypeInfo ): # iterate through enumerated list of tuples self.oneRadio = QRadioButton( "{}".format(convDisplay)) # text for button self.oneRadio.setObjectName("object_{}".format( convCode)) # to be used later by sender() self.oneRadio.setStyleSheet( makeStyleSheet("radiobutton", self.uiFileName)) self.layoutConv.addWidget(self.oneRadio) self.oneRadio.clicked.connect( self.convSetup ) # convSetup will call sender() to find convCode if ix == 0: self.oneRadio.setFocus( ) # set focus on first button in list if themode == "fromjpyear": # set up radio buttons for modern eras self.fromjpyearmode = "modern" # start with modern eras only self.showJpEras() if themode == "fromjpyearhistoric": # set up radio buttons for all eras self.fromjpyearmode = "all" # start with modern eras only self.showJpEras() if themode == "tojpyear": # no choices, go straight to input box self.showInstructions(self.mess.getToJpYear(self.yc.getMinYear()), "") self.input1.setText(str( self.yc.getNowYear())) # start with current year self.setUpValidator() self.convertUnits() if themode == "zodiac": # no choices, go straight to input box self.showInstructions(self.mess.getEnterYearZodiac(), "") self.input1.setText(str( self.yc.getNowYear())) # start with current year self.setUpValidator() self.convertUnits() if themode == "start": self.btnFromMetric.setFocus() self.showBigInstructions(self.mess.getStartMsg2()) def showBigInstructions(self, themsg): self.instructions2.setText(themsg) self.scrollArea.hide() self.instructions2.show() def hideBigInstructions(self): self.scrollArea.show() self.instructions2.hide() def showJpEras(self): # display radio buttons for Japanese eras jpEraList = self.yc.getEraNamesPlusCodes( self.fromjpyearmode) # modern or all for ix, (eraText, eraCode) in enumerate(jpEraList): self.oneRadio = QRadioButton( "{}".format(eraText)) # text for button self.oneRadio.setObjectName( "object_{}".format(eraCode)) # to be used later by sender() self.oneRadio.setStyleSheet( makeStyleSheet("radiobutton", self.uiFileName)) self.layoutConv.addWidget(self.oneRadio) self.oneRadio.clicked.connect( self.eraSetup) # eraSetup will call sender() to find eraCode if ix == 0: self.oneRadio.setFocus() # set focus on first button if self.fromjpyearmode == "modern": self.oneRadio = QRadioButton( "{}".format("Show more eras")) # now add option for more eras self.oneRadio.setObjectName( "object_{}".format("all")) # to be used later by sender() else: self.oneRadio = QRadioButton("{}".format( "Show fewer eras")) # now add option to return to modern eras self.oneRadio.setObjectName( "object_{}".format("modern")) # to be used later by sender() self.oneRadio.setStyleSheet( makeStyleSheet("radiobutton", self.uiFileName)) self.layoutConv.addWidget(self.oneRadio) self.oneRadio.clicked.connect( self.eraSetup) # eraSetup will call sender() to find eraCode def eraSetup(self): # this is called when radio button is chosen theEra = self.getCodeFromSenderName( ) # era or mode is determined by object name of sending radio button if theEra in ["all", "modern"]: # switch between modern and all self.fromjpyearmode = theEra # set the mode here self.emptyConvLayout() # clear former list if theEra == "all": self.widgetSetup("fromjpyearhistoric") else: self.widgetSetup("fromjpyear") else: # theEra will be eraCode for chosen era self.chosenEra = theEra # set this property if self.yc.getNowEra() == theEra: theHint = "(1- )" # no final year if it's the current era else: theHint = "(1-{})".format( self.yc.getNumYears(theEra)) # final year in that era self.showInstructions( self.mess.getFromJpYear(self.yc.getENameUnparsed(theEra)), theHint) self.output2.hide() self.setUpValidator() def setUpValidator(self): if self.themode in self.convs.getValidConvTypes(): # measures if self.convs.isTempConv(self.theConvCode): self.validFloat.setBottom( -999999) # temperatures can be negative else: self.validFloat.setBottom( 0.0) # other measures can't be negative self.input1.setValidator(self.validFloat) if self.themode in [ "fromjpyear", "fromjpyearhistoric", "tojpyear", "zodiac" ]: self.input1.setValidator( self.validYear) # range already set to 1-9999 def convSetup(self): # set up based on which radio button was set self.theConvCode = self.getCodeFromSenderName( ) # get the code based on the sending button, and set it self.showInstructions(self.mess.getEnterAmt()) self.setUpValidator() self.input1.setText("1") # show units=1 to start self.convertUnits() def getCodeFromSenderName(self): # based on objectName of sender button sending_button = self.sender() return str(sending_button.objectName()).replace("object_", "") def convertUnits(self): # main conversion routine pstart = self.mess.getPstart( ) # get paragraph HTML from Message object pstopstart = self.mess.getPstopstart() pstop = self.mess.getPstop() jcol = self.mess.getJColor() # special color for Japanese text if len(self.input1.text()) < 1: # test for blank input self.output2.setText( self.mess.getBlankConvertMsg()) # show error message self.output2.show() return if self.themode in self.convs.getValidConvTypes( ): # standard conversions: fromjpmeasure, tometric, etc amt1Text = self.input1.text() amt1 = strToNum(amt1Text) if self.convs.isTooCold(self.theConvCode, amt1): eqString = self.mess.getTooCold( ) #check for temp below abs zero else: eqString = self.convs.getEquation(self.theConvCode, amt1, " =" + pstopstart, jcol) self.output2.setText( pstart + eqString + pstop) # use paragraphs for better control of appearance elif self.themode == "tojpyear": # int'l year to Japanese year try: iYear = int(self.input1.text()) yearDisplay = self.mess.makeJYearDisplay( self.yc.iYearToJYear(iYear, jcol), iYear) except ValueError as errorMsg: yearDisplay = pstart + str( errorMsg) + pstop # display the error message self.output2.setText(yearDisplay) #print (yearDisplay) elif self.themode in ["fromjpyear", "fromjpyearhistoric" ]: # Japanese year to int'l year jYear = int(self.input1.text() ) # validator at work, so this should be an integer try: # raise exception if not in range iYear = self.yc.jYearToIYear(self.chosenEra, jYear) yearDisplay = pstart + "{} ({}) {}".format(self.yc.getENameUnparsed(self.chosenEra), \ self.yc.getJName(self.chosenEra, jcol), jYear) + \ pstopstart + self.mess.getIs() + " " + str(iYear) + pstop except ValueError as errorMsg: yearDisplay = pstart + str( errorMsg) + pstop # display the error message self.output2.setText(yearDisplay) elif self.themode == "zodiac": # international year to zodiac sign iYear = int(self.input1.text()) # display is HTML with paragraph, line height, and Japanese characters in color (specified in Mess class) yearDisplay = pstart + str(iYear) + " " + self.mess.getIs() + ":" + pstopstart + \ self.mess.getYearOfThe().capitalize() + " " + self.yc.getZodEName(iYear) + pstop self.output2.setText(yearDisplay) zBig = self.mess.makeZodiacBigDisplay( self.yc.getZodEName(iYear), self.yc.getZodJName(iYear, jcol), self.yc.getZodJZName(iYear, jcol)) self.showBigInstructions(zBig) self.output2.show() # common to all conversion types def emptyConvLayout( self): # clear the radio buttons in the converter/jpYear layout for i in reversed(range( self.layoutConv.count())): # delete them in reverse order self.layoutConv.itemAt(i).widget().deleteLater() self.instructions1.hide() self.input1.setPlaceholderText("") # clear previous hints self.input1.hide() # conversion not chosen yet, so hide this self.btnConvert.hide() # conversion not chosen yet, so hide this self.output2.hide() # conversion not chosen yet, so hide this def showInstructions( self, instructionsText, inputHint=""): # position UI elements, set label, show input box self.instructions1.setText(instructionsText) self.instructions1.show() self.input1.setText("") self.input1.setPlaceholderText(inputHint) self.input1.show() self.btnConvert.show() self.input1.setFocus() def convertQuickly(self): # testing if not self.input1.text(): amt = 0 else: amt = float(self.input1.text()) * 2.0 amtString = '{} kilograms'.format(amt) self.output2.setText(amtString) def getParts(self): # map form elements to object properties self.centralw = self.findWidget(QWidget, 'central_widget') self.input1 = self.findWidget(QLineEdit, 'input1') self.output2 = self.findWidget(QTextEdit, 'label_output2') self.header1 = self.findWidget(QLabel, 'label_header1') self.btnConvert = self.findWidget(QPushButton, 'button_convert') self.btnExit = self.findWidget(QPushButton, 'button_exit') self.btnFromMetric = self.findWidget(QPushButton, 'button_from_metric') self.btnToMetric = self.findWidget(QPushButton, 'button_to_metric') self.btnFromJpMeasure = self.findWidget(QPushButton, 'button_from_jpmeasure') self.btnToJpMeasure = self.findWidget(QPushButton, 'button_to_jpmeasure') self.btnFromJpYear = self.findWidget(QPushButton, 'button_from_jpyear') self.btnToJpYear = self.findWidget(QPushButton, 'button_to_jpyear') self.btnZodiac = self.findWidget(QPushButton, 'button_zodiac') self.scrollArea = self.findWidget(QScrollArea, 'conv_layout') content_widget = QWidget( ) # now add the QVBoxLayout widget programmatically, for scrolling self.scrollArea.setWidget(content_widget) self.scrollArea.setWidgetResizable(True) self.layoutConv = QVBoxLayout(content_widget) self.layoutConv.setAlignment( Qt.AlignTop ) # don't evenly space the radio buttons, but start at the top self.instructions1 = self.findWidget(QLabel, 'label_instructions1') self.instructions2 = self.findWidget(QLabel, 'label_instructions2') self.menuExit = self.findWidget(QAction, 'action_exit') self.menuFromMetric = self.findWidget(QAction, 'action_from_metric') self.menuToMetric = self.findWidget(QAction, 'action_to_metric') self.menuFromJpMeasure = self.findWidget(QAction, 'action_from_jpmeasure') self.menuToJpMeasure = self.findWidget(QAction, 'action_to_jpmeasure') self.menuFromJpYear = self.findWidget(QAction, 'action_from_jpyear') self.menuFromJpYearHistoric = self.findWidget( QAction, 'action_from_jpyear_historic') self.menuToJpYear = self.findWidget(QAction, 'action_to_jpyear') self.menuZodiac = self.findWidget(QAction, 'action_zodiac') self.menubar = self.findWidget(QMenuBar, 'menubar') if self.uiFileName == "main3.ui": self.menubar.setStyleSheet( getMenuStyle("main3.ui")) # in jpconvhelper.py def findWidget(self, widgetType, widgetName): if devMode == "development": return self.window.findChild(widgetType, widgetName) else: return self.findChild(widgetType, widgetName) def connectParts(self): # connect buttons and menu actions to operations self.input1.returnPressed.connect(self.convertUnits) self.btnConvert.clicked.connect(self.convertUnits) self.btnExit.clicked.connect(self.exitHandler) self.menuExit.triggered.connect(self.exitHandler) self.btnFromMetric.clicked.connect( lambda: self.widgetSetup("frommetric")) self.menuFromMetric.triggered.connect( lambda: self.widgetSetup("frommetric")) self.btnToMetric.clicked.connect(lambda: self.widgetSetup("tometric")) self.menuToMetric.triggered.connect( lambda: self.widgetSetup("tometric")) self.btnFromJpMeasure.clicked.connect( lambda: self.widgetSetup("fromjpmeasure")) self.menuFromJpMeasure.triggered.connect( lambda: self.widgetSetup("fromjpmeasure")) self.btnToJpMeasure.clicked.connect( lambda: self.widgetSetup("tojpmeasure")) self.menuToJpMeasure.triggered.connect( lambda: self.widgetSetup("tojpmeasure")) self.btnFromJpYear.clicked.connect( lambda: self.widgetSetup("fromjpyear")) self.menuFromJpYear.triggered.connect( lambda: self.widgetSetup("fromjpyear")) self.menuFromJpYearHistoric.triggered.connect( lambda: self.widgetSetup("fromjpyearhistoric")) self.btnToJpYear.clicked.connect(lambda: self.widgetSetup("tojpyear")) self.menuToJpYear.triggered.connect( lambda: self.widgetSetup("tojpyear")) self.btnZodiac.clicked.connect(lambda: self.widgetSetup("zodiac")) self.menuZodiac.triggered.connect(lambda: self.widgetSetup("zodiac")) def exitHandler(self): app.exit()
class NavFrame(QFrame): def __init__(self, parent=None): QFrame.__init__(self, parent) self.setStyleSheet("""QFrame{ background-color:#43454f;}""") self.setFrameShape(QFrame.StyledPanel) self.setFrameShadow(QFrame.Raised) self.frame_nav = QFrame(self) self.frame_nav.setMinimumSize(QSize(220, 300)) self.frame_nav.setStyleSheet("""QFrame{ background-color:#43454f;}""") self.frame_nav.setFrameShape(QFrame.StyledPanel) self.frame_nav.setFrameShadow(QFrame.Raised) self.gridLayout = QGridLayout(self) self.gridLayout.setContentsMargins(11, -1, 11, -1) self.gridLayout.addWidget(self.frame_nav, 3, 0, 1, 4) # set program img and name self.label_img = QLabel(self) self.label_img.setFixedSize(QSize(60, 60)) self.label_img.setPixmap(QPixmap(os.path.join(path, 'img/icon.png'))) # self.label_img.setPixmap(QPixmap("../img/icon.png")) self.label_img.setScaledContents(True) self.gridLayout.addWidget(self.label_img, 2, 1, 1, 1) self.label_name = QLabel("WebCheck ", self) self.label_name.setStyleSheet(styles.label_icon_name) self.gridLayout.addWidget(self.label_name, 2, 2, 1, 1) self.spacer_name_l = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.spacer_name_r = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.spacer_name_t = QSpacerItem(20, 70, QSizePolicy.Minimum, QSizePolicy.Maximum) self.gridLayout.addItem(self.spacer_name_l, 2, 0, 1, 1) self.gridLayout.addItem(self.spacer_name_r, 2, 3, 1, 1) self.gridLayout.addItem(self.spacer_name_t, 1, 1, 1, 2) # set bottom layout for keeping gb in it self.gridLayout_b = QGridLayout(self.frame_nav) self.spacer_gb_l = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.spacer_gb_r = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.spacer_gb_t = QSpacerItem(0, 20, QSizePolicy.Minimum, QSizePolicy.Maximum) self.spacer_gb_b = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) self.gridLayout_b.addItem(self.spacer_gb_l, 1, 2, 1, 1) self.gridLayout_b.addItem(self.spacer_gb_r, 1, 0, 1, 1) self.gridLayout_b.addItem(self.spacer_gb_t, 0, 1, 1, 1) self.gridLayout_b.addItem(self.spacer_gb_b, 2, 1, 1, 1) # set gb and radio buttons self.groupBox = QGroupBox("", self.frame_nav) self.gridLayout_b.addWidget(self.groupBox, 1, 1, 1, 1) self.groupBox.setMinimumSize(QSize(220, 350)) self.groupBox.setStyleSheet("""QGroupBox{background-image: url(ui/img/radioline.png); border: none;}""") self.verticalLayout_gb = QVBoxLayout(self.groupBox) self.radioButton_add = QRadioButton(" Add", self.groupBox) self.radioButton_add.setStyleSheet(styles.btn_radio) self.verticalLayout_gb.addWidget(self.radioButton_add) self.radioButton_monitored = QRadioButton(" Monitored", self.groupBox) self.radioButton_monitored.setStyleSheet(styles.btn_radio) self.verticalLayout_gb.addWidget(self.radioButton_monitored) self.radioButton_options = QRadioButton(" Options", self.groupBox) self.radioButton_options.setStyleSheet(styles.btn_radio) self.verticalLayout_gb.addWidget(self.radioButton_options) self.radioButton_about = QRadioButton(" About", self.groupBox) self.radioButton_about.setStyleSheet(styles.btn_radio) self.verticalLayout_gb.addWidget(self.radioButton_about)
def test_icon(pixmap_differ: PixmapDiffer): actual: QPainter expected: QPainter with pixmap_differ.create_painters( 300, 240, 'scaled_radio_button_icon') as (actual, expected): display = TicTacToeDisplay() icon = display.player1_icon display.close() ex_widget = QWidget() ex_layout = QVBoxLayout(ex_widget) ex_radio1 = QRadioButton() ex_radio2 = QRadioButton('Lorem ipsum') ex_radio1.setIcon(icon) ex_radio2.setIcon(icon) ex_font = ex_radio1.font() if ex_font.family() == 'Sans Serif': # Fonts are different on Travis CI. big_font_size = 93 small_font_size = 22 ex_radio1.setStyleSheet('QRadioButton::indicator {width: 93} ' 'QRadioButton {spacing: 46}') ex_radio2.setStyleSheet('QRadioButton::indicator {width: 22} ' 'QRadioButton {spacing: 11}') else: big_font_size = 93 small_font_size = 25 ex_radio1.setStyleSheet('QRadioButton::indicator {width: 93} ' 'QRadioButton {spacing: 46}') ex_radio2.setStyleSheet('QRadioButton::indicator {width: 25} ' 'QRadioButton {spacing: 12}') ex_radio1.setIconSize( QSize(big_font_size * 3 // 2, big_font_size * 3 // 2)) ex_radio2.setIconSize( QSize(small_font_size * 3 // 2, small_font_size * 3 // 2)) ex_font.setPointSize(big_font_size) ex_radio1.setFont(ex_font) ex_font.setPointSize(small_font_size) ex_radio2.setFont(ex_font) ex_size_policy = QSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) ex_radio1.setSizePolicy(ex_size_policy) ex_radio2.setSizePolicy(ex_size_policy) ex_layout.addWidget(ex_radio1) ex_layout.addWidget(ex_radio2) ex_layout.setStretch(0, 4) ex_layout.setStretch(1, 1) ex_widget.resize(300, 240) expected.drawPixmap(0, 0, ex_widget.grab()) widget = QWidget() layout = QVBoxLayout(widget) radio1 = ScaledRadioButton() radio2 = ScaledRadioButton('Lorem ipsum') radio1.setIcon(icon) radio2.setIcon(icon) size_policy = QSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) radio1.setSizePolicy(size_policy) radio2.setSizePolicy(size_policy) layout.addWidget(radio1) layout.addWidget(radio2) layout.setStretch(0, 4) layout.setStretch(1, 1) widget.resize(300, 240) actual.drawPixmap(0, 0, widget.grab())
class Window(QWidget): def __init__(self): super().__init__() # ----------style------------- self.font_type = "Arial" self.font_size = 10 self.font_color = "#676767" self.font_size2 = 12 self.font_color_black = "#f0f0f0" #--------------------------------- self.text8 = QTextEdit() self.text8.setReadOnly(True) self.check_text = False self.gbox6 = QGroupBox() try: f = open("plotter.txt", "x+") except: f = open("plotter.txt", "r") self.s = f.readline() f.close if self.s == "": f = open("plotter.txt", "w") f.write("dark") f.close() self.s = "dark" self.information_dialog() else: self.gbox6.setStyleSheet( "border:None;background-color:rgba(255,255,255,0)") self.text8.setStyleSheet( "border:None;background-color:rgba(255,255,255,0)") self.gbox6.setTitle("") self.text8.setText("") np.seterr(invalid='raise') self.setWindowTitle("XGrapher") self.setGeometry(500, 400, 900, 600) self.setMinimumSize(900, 600) pg.setConfigOption('background', (255, 255, 255, 0)) self.pw = pg.PlotWidget() self.pw.setXRange(0, 1) self.pw.setYRange(0, 1) self.pw.hideButtons() #--------------------------- self.list_errors = [] # -------------------------- self.a = False self.b = False self.c = False # ------------------------- self.d = False self.e = False self.f = False self.g = False self.after = False # ------------------------- self.check1 = False self.check2 = False self.check3 = False self.check_dot = False self.check_neg = False self.check_xrange = False self.check_yrange = False # ------------Labels----------------------------------------- self.label1 = QLabel() self.label1.setText("F(x):") self.label2 = QLabel() self.label2.setText("Min(x):") self.label3 = QLabel() self.label3.setText("Max(x):") self.label4 = QLabel() self.label5 = QLabel() self.label5.setText("< x <") self.label6 = QLabel() self.label6.setText("< y <") # --------------------------texteditors------------------ self.text1 = QLineEdit(self) self.text1.textChanged.connect(self.text1_response) self.text1.returnPressed.connect(self.focus_text1) self.text2 = QLineEdit(self) self.text2.textChanged.connect(self.text2_response) self.text2.returnPressed.connect(self.focus_text2) self.text3 = QLineEdit(self) self.text3.textChanged.connect(self.text3_response) self.text3.returnPressed.connect(self.focus_text3) self.text4 = QLineEdit() self.text4.textChanged.connect(self.text4_response) self.text4.returnPressed.connect(self.focus_text4) self.text5 = QLineEdit() self.text5.textChanged.connect(self.text5_response) self.text5.returnPressed.connect(self.focus_text5) self.text6 = QLineEdit() self.text6.textChanged.connect(self.text6_response) self.text6.returnPressed.connect(self.focus_text6) self.text7 = QLineEdit() self.text7.textChanged.connect(self.text7_response) self.text7.returnPressed.connect(self.focus_text7) # -------------------------------------------------------- self.button_2 = QPushButton() self.button_2.clicked.connect(self.auto_mode) self.button_save = QPushButton("Export Graph") self.button_help = QPushButton() self.button_help.clicked.connect(self.information_dialog) # ----------------------RadioButtons---------------------- self.rbutton1 = QRadioButton("Light") self.rbutton1.toggled.connect(self.light_mode) self.rbutton2 = QRadioButton("Dark") self.rbutton2.toggled.connect(self.dark_mode) # -------------------------------------------------------- self.setIcon() self.center() self.input_box() self.plot_box() self.vbox = QHBoxLayout() self.vbox.addWidget(self.gbox5) self.vbox.addSpacing(5) self.vbox.addWidget(self.plot) # self.setStyleSheet("background-color:rgb(32,32,32);") # self.setStyleSheet("background-color:rgb(240,240,240);") self.setLayout(self.vbox) if self.s == "dark": self.rbutton2.setChecked(True) else: self.rbutton1.setChecked(True) if self.s == "dark": self.dark_mode() else: self.light_mode() self.show() # --------------------------------------evalute------------------------------------------------------------------- self.replacements = { 'sin': 'np.sin', 'cos': 'np.cos', 'tan': 'np.tan', 'arccos': 'np.arccos', 'arcsin': 'np.arcsin', 'arctan': 'np.arctan', 'exp': 'np.exp', 'sqrt': 'np.sqrt', 'cbrt': 'np.cbrt', 'ln': 'np.log', "cosh": "np.cosh", "sinh": "np.cosh", "tanh": "np.cosh" } self.allowed_words = [ "x", "sin", "cos", "tan", "arccos", "arcsin", "arctan", "cosh", "sinh", "tanh", "exp", "sqrt", "cbrt", "log10", "ln" ] # ---------------------------------------------------------------------------------------------------------------- self.after = True def setIcon(self): appIcon = QIcon("close.ico") self.setWindowIcon(appIcon) def center(self): qRect = self.frameGeometry() centerPoint = QDesktopWidget().availableGeometry().center() qRect.moveCenter(centerPoint) self.move(qRect.topLeft()) def input_box(self): self.input = QGroupBox("Function") self.gbox = QGroupBox("Range") vbox_parent = QVBoxLayout() self.hbox_parent = QVBoxLayout() hbox1 = QHBoxLayout() hbox2 = QHBoxLayout() hbox3 = QHBoxLayout() hbox1.addWidget(self.label1) hbox1.addSpacing(17) hbox1.addWidget(self.text1) hbox2.addWidget(self.label2) hbox2.addSpacing(4) hbox2.addWidget(self.text2) hbox3.addWidget(self.label3) hbox3.addSpacing(0) hbox3.addWidget(self.text3) hbox_button = QHBoxLayout() hbox_button.addStretch(1) self.button = QPushButton("Reset") self.button.setFixedSize(70, 25) self.button.clicked.connect(self.reset) hbox_button.addWidget(self.button) vbox_parent.addLayout(hbox1) vbox_parent.addLayout(hbox2) vbox_parent.addLayout(hbox3) vbox_parent.addLayout(hbox_button) self.input.setLayout(vbox_parent) hbox4 = QHBoxLayout() hbox4.addWidget(self.text4) hbox4.addWidget(self.label5) hbox4.addWidget(self.text5) hbox5 = QHBoxLayout() hbox5.addWidget(self.text6) hbox5.addWidget(self.label6) hbox5.addWidget(self.text7) vbox3 = QVBoxLayout() vbox3.addWidget(self.button_2) vbox2 = QVBoxLayout() vbox2.addLayout(hbox4) vbox2.addLayout(hbox5) hbox6 = QHBoxLayout() hbox6.addLayout(vbox2) hbox6.addLayout(vbox3) self.gbox.setLayout(hbox6) #self.button_save.setFixedSize(200, 25) self.button_save.setFixedHeight(25) self.button_save.setFixedWidth(220) self.button_save.clicked.connect(self.export) hbox7 = QHBoxLayout() hbox7.addWidget(self.button_save) hbox7.addWidget(self.button_help) self.gbox3 = QGroupBox() self.gbox3.setFlat(True) self.gbox3.setStyleSheet("border: None") #self.gbox3.setLayout(hbox7) vbox3 = QVBoxLayout() vbox3.addWidget(self.gbox) self.gbox4 = QGroupBox("Status") hbox8 = QHBoxLayout() hbox8.addWidget(self.label4) self.gbox4.setLayout(hbox8) self.gbox_mode = QGroupBox("Style") vbox4 = QHBoxLayout() vbox4.addWidget(self.rbutton1) vbox4.addWidget(self.rbutton2) self.gbox_mode.setLayout(vbox4) hbox9 = QHBoxLayout() hbox9.addWidget(self.text8) self.gbox6.setLayout(hbox9) self.hbox_parent.addWidget(self.input) self.hbox_parent.addLayout(vbox3) self.hbox_parent.addLayout(hbox7) self.hbox_parent.addWidget(self.gbox6) self.hbox_parent.addWidget(self.gbox_mode) self.hbox_parent.addWidget(self.gbox4) self.gbox5 = QGroupBox() self.gbox5.setLayout(self.hbox_parent) def plot_box(self): self.plot = QGroupBox() layout = QVBoxLayout() self.pw.showGrid(True, True, 0.5) layout.addWidget(self.pw) self.plot.setLayout(layout) def text_restricted(self, str): if str != "": word = str[len(str) - 1] if re.match('[0-9-.]', word) is None: k = str.translate({ord(word): None}) str = k if word == "-" and len(str) > 1: k = str[1:].translate({ord(word): None}) str = str.replace(str[1:], k) if word == ".": i = 0 for v in str: if v == ".": i += 1 if i > 1: str = str[0:len(str) - 1] + "" if word == ".": self.check_dot = True else: str = "" return str def text1_response(self): if self.check1 == False: self.a = True self.plotx() else: self.check1 = False def text2_response(self): self.text2.setText(self.text_restricted(self.text2.text())) if self.check2 == False: self.b = True self.plotx() else: self.check2 = False def text3_response(self): self.text3.setText(self.text_restricted(self.text3.text())) if self.check3 == False: self.c = True self.plotx() else: self.check3 = False def text4_response(self): self.text4.setText(self.text_restricted(self.text4.text())) self.xrange() def text5_response(self): self.text5.setText(self.text_restricted(self.text5.text())) self.xrange() def text6_response(self): self.text6.setText(self.text_restricted(self.text6.text())) self.yrange() def text7_response(self): self.text7.setText(self.text_restricted(self.text7.text())) self.yrange() def xrange(self): if self.text4.text() == "" and self.text5.text() == "": self.error("No X Min Range") self.error("No X Max Range") self.error("Invalid X Range") self.f = False self.check_xrange = False if self.text1.text() == "" or self.text2.text( ) == "" or self.text3.text() == "": self.pw.setXRange(0, 1) else: self.pw.enableAutoRange(axis='x') elif self.text4.text() != "" and self.text5.text() != "": self.check_xrange = True if float(self.text4.text()) >= float(self.text5.text()): self.error_add("Invalid X Range") self.f = True else: self.pw.setXRange(float(self.text4.text()), float(self.text5.text())) self.error("No X Min Range") self.error("No X Max Range") self.error("Invalid X Range") self.f = False self.plotx() if self.text6.text() == "" or self.text7.text() == "": self.pw.enableAutoRange(axis='y') self.pw.setAutoVisible(y=True) else: if self.text4.text() == "" and self.check_xrange == True: self.error_add("No X Min Range") self.f = True self.pw.setXRange(0, 1) if self.text5.text() == "" and self.check_xrange == True: self.error_add("No X Max Range") self.f = True self.pw.setXRange(0, 1) if self.text6.text() != "" and self.text7.text() != "": self.pw.enableAutoRange(axis='x') self.pw.setAutoVisible(x=True) else: if self.d == True or self.e == True: self.pw.setYRange(0, 1) self.pw.setXRange(0, 1) else: self.pw.enableAutoRange() def yrange(self): if self.text6.text() == "" and self.text7.text() == "": self.error("No Y Min Range") self.error("No Y Max Range") self.error("Invalid Y Range") self.g = False self.check_yrange = False if self.text1.text() == "" or self.text2.text( ) == "" or self.text3.text() == "": self.pw.setYRange(0, 1) else: self.pw.enableAutoRange(axis='y') elif self.text6.text() != "" and self.text7.text() != "": self.check_yrange = True if float(self.text6.text()) >= float(self.text7.text()): self.error_add("Invalid Y Range") self.g = True else: self.pw.setYRange(float(self.text6.text()), float(self.text7.text())) self.error("No Y Min Range") self.error("No Y Max Range") self.error("Invalid Y Range") self.g = False self.plotx() if self.text4.text() == "" or self.text5.text() == "": self.pw.enableAutoRange(axis='x') self.pw.setAutoVisible(x=True) else: if self.text6.text() == "" and self.check_yrange == True: self.error_add("No Y Min Range") self.g = True self.pw.setYRange(0, 1) if self.text7.text() == "" and self.check_yrange == True: self.error_add("No Y Max Range") self.g = True self.pw.setYRange(0, 1) if self.text4.text() != "" and self.text5.text() != "": self.pw.enableAutoRange(axis='y') self.pw.setAutoVisible(y=True) else: if self.d == True or self.e == True: self.pw.setYRange(0, 1) self.pw.setXRange(0, 1) else: self.pw.enableAutoRange() def string2func(self, str): if str != "" and self.a == True and self.b == True and self.c == True: self.error("No Function to draw") self.d = False for word in re.findall('[a-zA-Z_]+', str): if word not in self.allowed_words: self.error_add("F(x) is not a Function of x") self.d = True else: self.d = False self.error('F(x) is not a Function of x') if word in self.replacements: str = str.replace(word, self.replacements[word]) if "^" in str: str = str.replace("^", "**") elif str == "" and self.b == True and self.c == True: self.error_add("No Function to draw") self.d = True self.pw.clear() def func(x): if str != "" and self.text2.text() != "" and self.text3.text( ) != "" and self.d == False: if self.d == False: try: if np.inf in eval(str): raise ZeroDivisionError if -np.inf in eval(str): raise ValueError except ZeroDivisionError: self.error_add("Cannot divide by Zero") self.d = True except FloatingPointError: self.error_addd("Undefined") self.d = True except ValueError: self.error_add("Math Error") self.d = True except: self.error_add("Syntax Error") self.d = True else: self.error("Cannot divide by Zero") self.error("Undefined") self.error("Math Error") self.error("Syntax Error") self.d = False return eval(str) return func def plotx(self): if self.text2.text() == "" and self.text3.text( ) == "" and self.text1.text( ) == "" and self.a == True and self.b == True and self.c == True: self.reset() func = self.string2func(self.text1.text()) if self.a == True and self.b == True and self.c == True and self.text2.text( ) != "" and self.text3.text() != "" and self.text1.text( ) != "" and self.d == False: if (self.text4.text() == "" and self.text5.text() == "") and ( self.text6.text() == "" and self.text7.text() == ""): self.pw.enableAutoRange() self.pw.clear() if (self.text2.text() == "-" or self.text3.text() == "-" or self.text3.text() == "." or self.text2.text() == "."): self.list_errors.append("Invalid Range") self.e = True else: min_num = float(self.text2.text()) max_num = float(self.text3.text()) if min_num >= max_num: self.error_add("Invalid Range") self.e = True else: range = np.linspace(min_num, max_num, 2000) if "x" not in self.text1.text( ) and self.text1.text() != "": try: if self.s == "light": self.pw.plot(range, np.ones(len(range)) * eval(self.text1.text()), pen=pg.mkPen(color=(140, 140, 140), width=2)) else: self.pw.plot(range, np.ones(len(range)) * eval(self.text1.text()), pen=pg.mkPen(color="w", width=2)) except ZeroDivisionError: self.error_add("Cannot divide by Zero") self.d = True except FloatingPointError: self.error_add("Undefined") self.d = True except ValueError: self.error_add("Math Error") self.d = True except: self.error_add("Syntax Error") self.d = True else: self.error("Cannot divide by Zero") self.error("Undefined") self.error("Math Error") self.error("Syntax Error") self.d = False else: y = func(range) if self.s == "light": self.pw.plot(range, y, pen=pg.mkPen(color=(140, 140, 140), width=2)) self.error("Invalid Range") self.error("No Min Value") self.error("No Max Value") else: self.pw.plot(range, y, pen=pg.mkPen(color="w", width=2)) self.error("Invalid Range") self.error("No Min Value") self.error("No Max Value") self.e = False else: if (self.text3.text() == "" and self.c == True): self.pw.clear() self.e = True self.error_add("No Max Value") elif (self.text3.text() != "" and self.c == True): self.error("No Max Value") if (self.text2.text() == "" and self.b == True): self.pw.clear() self.e = True self.error_add("No Min Value") elif (self.text2.text() != "" and self.b == True): self.error("No Min Value") def error(self, type): if type in self.list_errors: self.list_errors.remove(type) if len(self.list_errors) == 0: self.label4.setText("") else: self.label4.setText(self.list_errors[len(self.list_errors) - 1]) def error_add(self, error): if error in self.list_errors: pass else: self.list_errors.append(error) self.label4.setText(self.list_errors[len(self.list_errors) - 1]) def reset(self): self.pw.clear() if self.text4.text() == "" and self.text5.text( ) == "" and self.text6.text() == "" and self.text7.text() == "": self.pw.setXRange(0, 1) self.pw.setYRange(0, 1) self.check1 = True self.check2 = True self.check3 = True self.text1.setText("") self.text2.setText("") self.text3.setText("") self.a = False self.b = False self.c = False self.text1.setFocus() self.d = False self.e = False self.error("Invalid Range") self.error("No Min Value") self.error("No Max Value") self.error("Cannot divide by Zero") self.error("Undefined") self.error("Math Error") self.error("Syntax Error") self.error('F(x) is not a Function of x') self.error("No Function to draw") def focus_text1(self): self.text2.setFocus() def focus_text2(self): self.text3.setFocus() def focus_text3(self): self.text1.setFocus() def focus_text4(self): self.text5.setFocus() def focus_text5(self): self.text6.setFocus() def focus_text6(self): self.text7.setFocus() def focus_text7(self): self.text4.setFocus() def save(self): pass def information_dialog(self): if self.check_text == False: if self.s == "dark": self.gbox6.setTitle("Help") self.gbox6.setStyleSheet( "QGroupBox {border: 2px solid #3d3d3d;background-color:#383838;color: " + self.font_color_black + ";margin-top: 6px;}" + "QGroupBox::title {subcontrol-origin:margin;left:8px;padding: 0px 0px 0px 0px;}" ) self.text8.setStyleSheet( "border:None;background-color:#383838;border:None;color: " + self.font_color_black) self.text8.setFont( QFont(self.font_type, self.font_size, QFont.Normal)) self.text8.setText("--> The following operators must be used when writting the function:\n( - + / ^ ( ) ).\n\n--> The program supports the following functions and must be written as:" "\nsin(x),cos(x),tan(x),arccos(x),\narcsin(x),arctan(x),cosh(x),sinh(x),\ntanh(x),exp(x),sqrt(X),cbrt(x),\n" "log10(x),ln(x) and polynomial and rational functions." "\n\n--> The 'A' button in the Range box sets the x-axis and y-axis ranges to the appropriate values according to the values of the function.\n\n" \ "--> To close the Help box just click the help button beside the Export Graph.") else: self.gbox6.setTitle("Help") self.gbox6.setStyleSheet( "QGroupBox {border: 2px solid #e6e6e6;background-color:#f5f6f7;color: " + self.font_color + ";margin-top: 6px;}" + "QGroupBox::title {subcontrol-origin:margin;left:8px;padding: 0px 0px 0px 0px;}" ) self.text8.setStyleSheet( "border:None;background-color:#f5f6f7;color: " + self.font_color) self.text8.setFont( QFont(self.font_type, self.font_size, QFont.Normal)) self.text8.setText("--> The following operators must be used when writting the function:\n( - + / ^ ( ) ).\n\n--> The program supports the following functions and must be written as:" "\nsin(x),cos(x),tan(x),arccos(x),\narcsin(x),arctan(x),cosh(x),sinh(x),\ntanh(x),exp(x),sqrt(X),cbrt(x),\n" "log10(x),ln(x) and polynomial and rational functions." "\n\n--> The 'A' button in the Range box sets the x-axis and y-axis ranges to the appropriate values according to the values of the function.\n\n" \ "--> To close the Help box just click the help button beside the Export Graph.") self.check_text = True else: self.gbox6.setStyleSheet( "border:None;background-color:rgba(255,255,255,0)") self.text8.setStyleSheet( "border:None;background-color:rgba(255,255,255,0)") self.text8.setText("") self.gbox6.setTitle("") self.check_text = False def auto_mode(self): self.text4.setText("") self.text5.setText("") self.text6.setText("") self.text7.setText("") self.f = False self.g = False self.check_yrange == False self.check_xrange == False self.xrange() self.yrange() def dark_mode(self): self.input.setMaximumWidth(250) self.input.setFixedSize(250, 150) self.gbox.setMaximumWidth(250) self.gbox.setFixedSize(250, 90) self.gbox3.setMaximumWidth(250) self.gbox3.setFixedSize(250, 90) self.gbox4.setMaximumWidth(250) self.gbox4.setFixedSize(250, 45) self.gbox_mode.setMaximumWidth(250) self.gbox_mode.setFixedSize(250, 50) self.gbox5.setMaximumWidth(270) self.input.setObjectName("input") self.input.setStyleSheet( "QGroupBox#input{border: 2px solid #3d3d3d;background-color:#383838;color: " + self.font_color_black + ";margin-top: 6px;}" + "QGroupBox#input::title {subcontrol-origin:margin;left:8px;padding: 0px 0px 0px 0px;}" ) self.gbox.setStyleSheet( "QGroupBox {border: 2px solid #3d3d3d;background-color:#383838;color: " + self.font_color_black + ";margin-top: 6px;}" + "QGroupBox::title {subcontrol-origin:margin;left:8px;padding: 0px 0px 0px 0px;}" ) self.gbox4.setStyleSheet( "QGroupBox {border: 2px solid #3d3d3d;background-color:#383838;color: " + self.font_color_black + ";margin-top: 6px;}" + "QGroupBox::title {subcontrol-origin:margin;left:8px;padding: 0px 0px 0px 0px;}" ) self.gbox_mode.setStyleSheet( "QGroupBox {border: 2px solid #3d3d3d;background-color:#383838;color: " + self.font_color_black + ";margin-top: 6px;}" + "QGroupBox::title {subcontrol-origin:margin;left:8px;padding: 0px 0px 0px 0px;}" ) self.plot.setStyleSheet("color: " + self.font_color) self.setStyleSheet("background-color:#202020") self.label1.setStyleSheet( "background-color:#383838;border:None;color: " + self.font_color_black) self.label2.setStyleSheet( "background-color:#383838;border:None;color:" + self.font_color_black) self.label3.setStyleSheet( "background-color:#383838;border:None;color:" + self.font_color_black) self.label4.setStyleSheet( "background-color:#383838;border:None;color:" + self.font_color_black) self.label5.setStyleSheet( "background-color:#383838;border:None;color:" + self.font_color_black) self.label6.setStyleSheet( "background-color:#383838;border:None;color:" + self.font_color_black) self.rbutton1.setStyleSheet("background-color:#383838;color:" + self.font_color_black) self.rbutton2.setStyleSheet("background-color:#383838;color:" + self.font_color_black) self.rbutton1.setFont( QFont(self.font_type, self.font_size, QFont.Normal)) self.rbutton2.setFont( QFont(self.font_type, self.font_size, QFont.Normal)) self.label1.setFont(QFont(self.font_type, self.font_size, QFont.Normal)) self.label2.setFont(QFont(self.font_type, self.font_size, QFont.Normal)) self.label3.setFont(QFont(self.font_type, self.font_size, QFont.Normal)) self.label4.setFont(QFont(self.font_type, self.font_size, QFont.Normal)) self.label5.setFont(QFont(self.font_type, self.font_size, QFont.Normal)) self.label6.setFont(QFont(self.font_type, self.font_size, QFont.Normal)) self.text1.setStyleSheet( "border:1px solid #5b5b5b;background-color:#383838;color:" + self.font_color_black) self.text2.setStyleSheet( "border:1px solid #5b5b5b;background-color:#383838;color:" + self.font_color_black) self.text3.setStyleSheet( "border:1px solid #5b5b5b;background-color:#383838;color:" + self.font_color_black) self.text4.setStyleSheet( "border:1px solid #5b5b5b;background-color:#383838;color:" + self.font_color_black) self.text5.setStyleSheet( "border:1px solid #5b5b5b;background-color:#383838;color:" + self.font_color_black) self.text6.setStyleSheet( "border:1px solid #5b5b5b;background-color:#383838;color:" + self.font_color_black) self.text7.setStyleSheet( "border:1px solid #5b5b5b;background-color:#383838;color:" + self.font_color_black) self.button_save.setStyleSheet( " QPushButton{border: 1px solid #f0f0f0;Text-align:center;background:#333333; color:#f0f0f0}" "QPushButton::hover{border: 1px solid #f0f0f0;Text-align:center;background:#2c2c2c}" "QPushButton::Pressed{border: 1px solid #f0f0f0;Text-align:center;background:#3d3c3c}" ) self.button.setStyleSheet( " QPushButton{border: 1px solid #f0f0f0;Text-align:center;background:#333333; color:#f0f0f0}" "QPushButton::hover{border: 1px solid #f0f0f0;Text-align:center;background:#2c2c2c}" "QPushButton::Pressed{border: 1px solid #f0f0f0;Text-align:center;background:#3d3c3c}" ) self.text1.setFont(QFont(self.font_type, self.font_size, QFont.Normal)) self.text2.setFont(QFont(self.font_type, self.font_size, QFont.Normal)) self.text3.setFont(QFont(self.font_type, self.font_size, QFont.Normal)) self.text4.setFont(QFont(self.font_type, self.font_size, QFont.Normal)) self.text5.setFont(QFont(self.font_type, self.font_size, QFont.Normal)) self.text6.setFont(QFont(self.font_type, self.font_size, QFont.Normal)) self.text7.setFont(QFont(self.font_type, self.font_size, QFont.Normal)) self.gbox5.setObjectName("GroupBox") self.gbox5.setStyleSheet( "QGroupBox#GroupBox{border: None;background-color:#383838}") f = open("plotter.txt", "w") f.write("dark") f.close() self.s = "dark" self.pw.setBackground(background=None) if self.after == True: self.plotx() pixmap1 = QPixmap("auto-button_dark.png") button_icon1 = QIcon(pixmap1) self.button_2.setStyleSheet("border:none;background-color:#383838") self.button_2.setIcon(button_icon1) pixmap2 = QPixmap("help_dark.png") button_icon2 = QIcon(pixmap2) self.button_help.setIcon(button_icon2) self.button_help.setStyleSheet("border:none;background-color:#383838") if self.check_text == True: self.gbox6.setStyleSheet( "QGroupBox {border: 2px solid #3d3d3d;background-color:#383838;color: " + self.font_color_black + ";margin-top: 6px;}" + "QGroupBox::title {subcontrol-origin:margin;left:8px;padding: 0px 0px 0px 0px;}" ) self.text8.setStyleSheet( "border:None;background-color:#383838;border:None;color: " + self.font_color_black) self.text8.setFont( QFont(self.font_type, self.font_size, QFont.Normal)) def light_mode(self): self.input.setMaximumWidth(250) self.input.setFixedSize(250, 150) self.gbox.setMaximumWidth(250) self.gbox.setFixedSize(250, 90) self.gbox3.setMaximumWidth(250) self.gbox3.setFixedSize(250, 90) self.gbox4.setMaximumWidth(250) self.gbox4.setFixedSize(250, 45) self.gbox_mode.setMaximumWidth(250) self.gbox_mode.setFixedSize(250, 50) self.gbox5.setMaximumWidth(270) self.input.setObjectName("input") self.input.setStyleSheet( "QGroupBox#input{border: 2px solid #e6e6e6;background-color:#f5f6f7;color: " + self.font_color + ";margin-top: 6px;}" + "QGroupBox#input::title {subcontrol-origin:margin;left:8px;padding: 0px 0px 0px 0px;}" ) self.gbox.setStyleSheet( "QGroupBox {border: 2px solid #e6e6e6;background-color:#f5f6f7;color: " + self.font_color + ";margin-top: 6px;}" + "QGroupBox::title {subcontrol-origin:margin;left:8px;padding: 0px 0px 0px 0px;}" ) self.gbox4.setStyleSheet( "QGroupBox {border: 2px solid #e6e6e6;background-color:#f5f6f7;color: " + self.font_color + ";margin-top: 6px;}" + "QGroupBox::title {subcontrol-origin:margin;left:8px;padding: 0px 0px 0px 0px;}" ) self.gbox_mode.setStyleSheet( "QGroupBox {border: 2px solid #e6e6e6;background-color:#f5f6f7;color: " + self.font_color + ";margin-top: 6px;}" + "QGroupBox::title {subcontrol-origin:margin;left:8px;padding: 0px 0px 0px 0px;}" ) self.plot.setStyleSheet("color: " + self.font_color) self.setStyleSheet("background-color:white;") self.label1.setStyleSheet("background-color:#f5f6f7;color: " + self.font_color) self.label2.setStyleSheet("background-color:#f5f6f7;color:" + self.font_color) self.label3.setStyleSheet("background-color:#f5f6f7;color:" + self.font_color) self.label4.setStyleSheet("background-color:#f5f6f7;color:" + self.font_color) self.label5.setStyleSheet("background-color:#f5f6f7;color:" + self.font_color) self.label6.setStyleSheet("background-color:#f5f6f7;color:" + self.font_color) self.rbutton1.setStyleSheet("background-color:#f5f6f7;color:" + self.font_color) self.rbutton2.setStyleSheet("background-color:#f5f6f7;color:" + self.font_color) self.rbutton1.setFont( QFont(self.font_type, self.font_size, QFont.Normal)) self.rbutton2.setFont( QFont(self.font_type, self.font_size, QFont.Normal)) self.label1.setFont(QFont(self.font_type, self.font_size, QFont.Normal)) self.label2.setFont(QFont(self.font_type, self.font_size, QFont.Normal)) self.label3.setFont(QFont(self.font_type, self.font_size, QFont.Normal)) self.label4.setFont(QFont(self.font_type, self.font_size, QFont.Normal)) self.label5.setFont(QFont(self.font_type, self.font_size, QFont.Normal)) self.label6.setFont(QFont(self.font_type, self.font_size, QFont.Normal)) self.text1.setStyleSheet("background-color:white") self.text2.setStyleSheet("background-color:white") self.text3.setStyleSheet("background-color:white") self.text4.setStyleSheet("background-color:white") self.text5.setStyleSheet("background-color:white") self.text6.setStyleSheet("background-color:white") self.text7.setStyleSheet("background-color:white") self.button_save.setStyleSheet( " QPushButton{border: 1px solid #adadad;Text-align:center;background:#e1e1e1; color:black}" "QPushButton::hover{border: 1px solid #adadad;Text-align:center;background:#d8d7d7}" "QPushButton::Pressed{border: 1px solid #adadad;Text-align:center;background:#f5f6f7}" ) self.button.setStyleSheet( " QPushButton{border: 1px solid #adadad;Text-align:center;background:#e1e1e1; color:black}" "QPushButton::hover{border: 1px solid #adadad;Text-align:center;background:#d8d7d7}" "QPushButton::Pressed{border: 1px solid #adadad;Text-align:center;background:#f5f6f7}" ) self.text1.setFont(QFont(self.font_type, self.font_size, QFont.Normal)) self.text2.setFont(QFont(self.font_type, self.font_size, QFont.Normal)) self.text3.setFont(QFont(self.font_type, self.font_size, QFont.Normal)) self.text4.setFont(QFont(self.font_type, self.font_size, QFont.Normal)) self.text5.setFont(QFont(self.font_type, self.font_size, QFont.Normal)) self.text6.setFont(QFont(self.font_type, self.font_size, QFont.Normal)) self.text7.setFont(QFont(self.font_type, self.font_size, QFont.Normal)) self.gbox5.setObjectName("GroupBox") self.gbox5.setStyleSheet( "QGroupBox#GroupBox{border: None;background-color:#f5f6f7}") f = open("plotter.txt", "w") f.write("light") f.close() self.s = "light" self.pw.setBackground(background=None) if self.after == True: self.plotx() pixmap2 = QPixmap("auto-button.png") button_icon2 = QIcon(pixmap2) self.button_2.setStyleSheet("border:none;background-color:#f5f6f7") self.button_2.setIcon(button_icon2) pixmap2 = QPixmap("help_light.png") button_icon2 = QIcon(pixmap2) self.button_help.setIcon(button_icon2) self.button_help.setStyleSheet("border:none;background-color:#f5f6f7") if self.check_text == True: self.gbox6.setStyleSheet( "QGroupBox {border: 2px solid #e6e6e6;background-color:#f5f6f7;color: " + self.font_color + ";margin-top: 6px;}" + "QGroupBox::title {subcontrol-origin:margin;left:8px;padding: 0px 0px 0px 0px;}" ) self.text8.setStyleSheet( "border:None;background-color:#f5f6f7;color: " + self.font_color) self.text8.setFont( QFont(self.font_type, self.font_size, QFont.Normal)) def export(self): self.exportdialog = exportDialog.ExportDialog(self.pw.plotItem.scene()) name = QFileDialog.getSaveFileName( self, 'Save File', "", "PNG (*.PNG;*.PNG);;CSV (*.CSV);;SVG(*.SVG)", "", QFileDialog.Options()) if name[0] != "": if "PNG" in name[1]: if self.s == "dark": self.pw.setBackground(background=(0, 0, 0)) else: self.pw.setBackground(background=(255, 255, 255)) exporter = pg.exporters.ImageExporter(self.pw.plotItem) exporter.export(name[0]) self.pw.setBackground(background=None) elif "CSV" in name[1]: exporter = pg.exporters.CSVExporter(self.pw.plotItem) exporter.export(name[0]) elif "SVG" in name[1]: if self.s == "dark": self.pw.setBackground(background=(0, 0, 0)) else: self.pw.setBackground(background=(255, 255, 255)) exporter = pg.exporters.SVGExporter(self.pw.plotItem) exporter.export(name[0]) self.pw.setBackground(background=None)
0, count + 1, alignment=Qt.AlignCenter | Qt.AlignBottom) questions = [ "How likely is it that this person committed a premeditated crime?", "How likely is it that this person committed an impulsive crime?" ] for i, ques in enumerate(questions): q = QLabel(ques) q.setWordWrap(True) grid.addWidget(q, i + 1, 0) qbg = QButtonGroup() for count in range(len(header)): rad = QRadioButton('') rad.setStyleSheet( 'QRadioButton::indicator{width:60px; height:60px;}') qbg.addButton(rad) grid.addWidget(rad, i + 1, count + 1, alignment=Qt.AlignCenter) # for i in range(grid.rowCount()): # grid.setRowStretch(i, 0.5) lab = QLabel() lab.setPixmap(dv5_1) grid.addWidget(lab, 0, 0) surv.setLayout(grid) window.setLayout(wg) window.show() app.exec_()
class MainWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle('Queues\' Type') self.setGeometry(150, 150, 800, 500) self.setFixedSize(800, 500) self.center() self.setIcon() self.initRadioButtons() def initRadioButtons(self): width = self.width() height = self.height() self.deterministicRadio = QRadioButton('Deterministic Queue', self) self.deterministicRadio.setFont(QFont('Sanserif', 18)) self.deterministicRadio.setStyleSheet('QRadioButton{color:maroon}') self.deterministicRadio.adjustSize() self.deterministicRadio.move(100, 100) self.deterministicRadio.clicked.connect(self.deterministicRadioClicked) self.stochasticRadio = QRadioButton('Stochastic Queue', self) self.stochasticRadio.setFont(QFont('Sanserif', 18)) self.stochasticRadio.setStyleSheet('QRadioButton{color:darkslategray}') self.stochasticRadio.adjustSize() self.stochasticRadio.move((width / 2) + 50, 100) self.stochasticRadio.clicked.connect(self.stochasticRadioClicked) self.deterministicRadio = QRadioButton('WhatEver Queue', self) self.deterministicRadio.setFont(QFont('Sanserif', 18)) self.deterministicRadio.setStyleSheet('QRadioButton{color:steelblue}') self.deterministicRadio.adjustSize() self.deterministicRadio.move(300, 200) icon1 = QIcon('line.png') label1 = QLabel('Sample', self) pixmap1 = icon1.pixmap(100, 100, QIcon.Active, QIcon.On) label1.setPixmap(pixmap1) label1.move((width / 2) - 50, 300) label1.adjustSize() def deterministicRadioClicked(self): print('clickeddddd') self.dete = determenistic.DeterministicScreen() self.dete.show() self.destroy() def stochasticRadioClicked(self): self.soch = sochastic.SochasticScreen() self.soch.show() self.destroy() def center(self): qRect = self.frameGeometry() centerpoint = QDesktopWidget().availableGeometry().center() qRect.moveCenter(centerpoint) self.move(qRect.topLeft()) def setIcon(self): appIcon = QIcon('line.png') self.setWindowIcon(appIcon) def closeEvent(self, event): userInfo = QMessageBox.question(self, 'Closing ?', 'Do u want to quit ?', QMessageBox.Yes | QMessageBox.No) if userInfo == QMessageBox.Yes: event.accept() self.close() #sys.exit(QApplication(sys.argv).exec_()) elif userInfo == QMessageBox.No: event.ignore()
class PetrophysicsOptions(QWidget): polymorphic_states = { 'DParsons': {'param1': 'Coeficiente de Dykstra-Parsons', 'param2': 'Grau de heterogenêidade', 'param3': '', 'param4': '', 'prop1': ['Permeabilidade (mD)'], 'prop2': ['Permeabilidade (mD)'], 'prop3': '', 'prop4': ''}, 'Winland': {'param1': 'Garganta de Poro (Winland R35)', 'param2': '', 'param3': '', 'param4': '', 'prop1': ['Permeabilidade (mD)', 'Porosidade (%)'], 'prop2': 'Porosidade (%)', 'prop3': '', 'prop4': ''}, 'Lucia': {'param1': 'Classificação de Lucia (Gráfico de classes carbonáticas)', 'param2': '', 'param3': '', 'param4': '', 'prop1': ['Permeabilidade (mD)', 'Porosidade Interpartícula (%)'], 'prop2': '', 'prop3': '', 'prop4': ''}, 'RQIFZI': {'param1': 'RQI (μm)', 'param2': 'FZI (gráfico)', 'param3': '', 'param4': '', 'prop1': ['Permeabilidade', 'Porosidade (%)'], 'prop2': ['Permeabilidade', 'Porosidade (%)'], 'prop3': [], 'prop4': []}, 'TCoates': {'param1': 'FFI', 'param2': 'BVI', 'param3': 'Permeabilidade (mD)', 'param4': 'Swir (%)', 'prop1': ['Swir (%)', 'Porosidade (%)'], 'prop2': ['Swir (%)', 'Porosidade (%)'], 'prop3': ['Swir (%)', 'Porosidade (%)'], 'prop4': ['Permeabilidade (mD)', 'Porosidade (%)']}, 'KCarman': {'param1': 'Permeabilidade (mD)', 'param2': 'SVgr (cm-1)', 'param3': '', 'param4': '', 'prop1': ['Porosidade (%)', 'SVgr (cm-1)'], 'prop2': ['Permeabilidade (mD)', 'Porosidade (%)'], 'prop3': ['Permeabilidade (cm²)', 'Porosidade (decimal)'], 'prop4': []} } ready2calculate = Signal(bool) def __init__(self, _mode='KCarman'): super().__init__() self.mode = _mode self.subtitle = QLabel('Calcular:') self.label1 = QLabel() self.label2 = QLabel() self.label3 = QLabel() self.label4 = QLabel() self.labels = [self.label1, self.label2, self.label3, self.label4] for l in self.labels: l.setWordWrap(True) self.param1 = QRadioButton() self.param2 = QRadioButton() self.param3 = QRadioButton() self.param4 = QRadioButton() self.x_column = QLineEdit() self.y_column = QLineEdit() self.z_column = QLineEdit() self.destination_column = QLineEdit() self.results_l = QLabel('Resultados da análise: ') self.results = QTextEdit() self.unit_selector = Dropdown.Dropdown(['Darcy', 'SI']) self.run = QPushButton('Começar Análise') self.connections() self.changeMode(_mode) self.buildLayout() self.property_to_calculate = self.property_to_calculate = self.polymorphic_states[self.mode]['param1'] self.payload = {} stly_sheet = "QRadioButton::indicator {width: 13px; height: 13px;} QRadioButton::indicator::unchecked {image: url(:/images/radiobutton_unchecked.png)} QRadioButton::indicator:unchecked:hover {image: url(:/images/radiobutton_unchecked_hover.png);}" self.subtitle.setStyleSheet('color: white') self.label1.setStyleSheet('color: white') self.label2.setStyleSheet('color: white') self.label3.setStyleSheet('color: white') self.label4.setStyleSheet('color: white') self.param1.setStyleSheet('color: white') self.param2.setStyleSheet('color: white') self.param3.setStyleSheet('color: white') self.param4.setStyleSheet('color: white') self.x_column.setStyleSheet('background-color: white; color: black') self.y_column.setStyleSheet('background-color: white; color: black') self.z_column.setStyleSheet('background-color: white; color: black') self.results.setStyleSheet('background-color: white; color: black') self.setStyleSheet('color:white; font-family: Bahnschrift SemiLight Condensed; font-size: 14px;') def buildLayout(self): layout = QFormLayout() a = self.polymorphic_states[self.mode]['prop1'] b = self.polymorphic_states[self.mode]['prop2'] c = self.polymorphic_states[self.mode]['prop3'] d = self.polymorphic_states[self.mode]['prop4'] layout.addWidget(self.subtitle) if len(self.param1.text()) != 0: layout.addWidget(self.param1) if len(self.param2.text()) != 0: layout.addWidget(self.param2) if len(self.param3.text()) != 0: layout.addWidget(self.param3) if len(self.param4.text()) != 0: layout.addWidget(self.param4) if len(self.label1.text()) != 0: layout.addWidget(self.label1) layout.addWidget(self.x_column) if len(self.label2.text()) != 0: layout.addWidget(self.label2) layout.addWidget(self.y_column) if len(self.label3.text()) != 0: layout.addWidget(self.label3) layout.addWidget(self.z_column) #if len(self.label4.text()) != 0: #layout.addWidget(self.label4) #layout.addWidget(self.destination_column) if self.mode == 'RQIFZI': layout.addWidget(QLabel('Sistema de Unidades: ')) layout.addWidget(self.unit_selector) layout.addWidget(self.run) if self.mode == 'DParsons': layout.addWidget(self.results_l) layout.addWidget(self.results) if self.mode == 'Lucia': layout.addWidget(self.results_l) layout.addWidget(self.results) self.setLayout(layout) def connections(self): self.param1.clicked.connect(self.param1Active) self.param2.clicked.connect(self.param2Active) self.param3.clicked.connect(self.param3Active) self.param4.clicked.connect(self.param4Active) self.run.clicked.connect(self.collectPayload) def changeMode(self, _mode): self.mode = _mode self.param1.setText(self.polymorphic_states[self.mode]['param1']) self.param1.click() self.param2.setText(self.polymorphic_states[self.mode]['param2']) self.param3.setText(self.polymorphic_states[self.mode]['param3']) self.param4.setText(self.polymorphic_states[self.mode]['param4']) def param1Active(self): self.label1.setText('Selecione a coluna com os valores de ' + self.polymorphic_states[self.mode]['prop1'][0]) try: self.label2.setText('Selecione a coluna com os valores de ' + self.polymorphic_states[self.mode]['prop1'][1]) except IndexError: self.label2.setText('') try: self.label3.setText('Selecione a coluna com os valores de ' + self.polymorphic_states[self.mode]['prop1'][2]) except IndexError: self.label3.setText('') self.label4.setText('Selecione a coluna para os valores de ' + self.polymorphic_states[self.mode]['param1']) self.property_to_calculate = self.polymorphic_states[self.mode]['param1'] def param2Active(self): self.label1.setText('Selecione a coluna com os valores de ' + self.polymorphic_states[self.mode]['prop2'][0]) try: self.label2.setText('Selecione a coluna com os valores de ' + self.polymorphic_states[self.mode]['prop2'][1]) except IndexError: self.label2.setText('') try: self.label3.setText('Selecione a coluna com os valores de ' + self.polymorphic_states[self.mode]['prop2'][2]) except IndexError: self.label3.setText('') self.label4.setText('Selecione a coluna para os valores de ' + self.polymorphic_states[self.mode]['param2']) self.property_to_calculate = self.polymorphic_states[self.mode]['param2'] def param3Active(self): self.label1.setText('Selecione a coluna com os valores de ' + self.polymorphic_states[self.mode]['prop3'][0]) try: self.label2.setText('Selecione a coluna com os valores de ' + self.polymorphic_states[self.mode]['prop3'][1]) except IndexError: self.label2.setText('') try: self.label3.setText('Selecione a coluna com os valores de ' + self.polymorphic_states[self.mode]['prop3'][2]) except IndexError: self.label3.setText('') self.label4.setText('Selecione a coluna para os valores de ' + self.polymorphic_states[self.mode]['param3']) self.property_to_calculate = self.polymorphic_states[self.mode]['param3'] def param4Active(self): self.label1.setText('Selecione a coluna com os valores de ' + self.polymorphic_states[self.mode]['prop4'][0]) try: self.label2.setText('Selecione a coluna com os valores de ' + self.polymorphic_states[self.mode]['prop4'][1]) except IndexError: self.label2.setText('') try: self.label3.setText('Selecione a coluna com os valores de ' + self.polymorphic_states[self.mode]['prop4'][2]) except IndexError: self.label3.setText('') self.label4.setText('Selecione a coluna para os valores de ' + self.polymorphic_states[self.mode]['param4']) self.property_to_calculate = self.polymorphic_states[self.mode]['param4'] def collectPayload(self): payload = { 'calculate': self.property_to_calculate, 'x_column': self.x_column.text(), 'y_column': self.y_column.text(), 'z_column': self.z_column.text(), 'column_range': self.unit_selector.currentText(), 'output_selection': None, 'output_column': self.destination_column.text() } self.payload = payload print(payload) self.ready2calculate.emit(True)