コード例 #1
0
    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
コード例 #2
0
ファイル: apollo_ui.py プロジェクト: rzinkstok/fpga_agc
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()
コード例 #3
0
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())
コード例 #4
0
    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)
コード例 #5
0
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
コード例 #6
0
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()
コード例 #7
0
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)
コード例 #8
0
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())
コード例 #9
0
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)
コード例 #10
0
                       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_()
コード例 #11
0
ファイル: main.py プロジェクト: Mekkawy12/QueuesProject
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()
コード例 #12
0
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)