コード例 #1
0
def test_calctype_not_impemented(qtbot, caplog):
    view = MainWindow(controller=None)
    qtbot.addWidget(view)
    testbutton = QRadioButton()
    testbutton.setObjectName('custom')
    buttongroup = view._ui.calctype.buttongroup
    buttongroup.addButton(testbutton)
    assert testbutton in buttongroup.buttons()
    testbutton.animateClick(msec=0)
    qtbot.wait(100)
    assert caplog.records[-1].levelname == 'ERROR'
    assert 'button name mismatch' in caplog.text
コード例 #2
0
 def configFilterTypeButtons(self,
                             name=u"default",
                             checked=False,
                             xPos=0,
                             yPos=0,
                             idButton=0):
     button = QRadioButton(self)
     button.setObjectName(name)
     button.setEnabled(True)
     button.setGeometry(QRect(xPos, yPos, 82, 17))
     button.setCursor(QCursor(Qt.PointingHandCursor))
     button.setChecked(checked)
     lam = lambda id=idButton: self.buttonChecked(id)
     self.connect(button, SIGNAL("clicked()"), lam)
     self.filterTypeButtons.addButton(button, idButton)
コード例 #3
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
コード例 #4
0
ファイル: bmd_statistics.py プロジェクト: maltesie/bridge2
class Ui_GroupBox(object):
    def setupUi(self, GroupBox):
        if not GroupBox.objectName():
            GroupBox.setObjectName(u"GroupBox")
        GroupBox.resize(535, 520)
        sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Minimum)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(GroupBox.sizePolicy().hasHeightForWidth())
        GroupBox.setSizePolicy(sizePolicy)
        self.verticalLayout_2 = QVBoxLayout(GroupBox)
        self.verticalLayout_2.setObjectName(u"verticalLayout_2")
        self.groupBox_occupancy_histogram = QGroupBox(GroupBox)
        self.groupBox_occupancy_histogram.setObjectName(
            u"groupBox_occupancy_histogram")
        self.verticalLayout = QVBoxLayout(self.groupBox_occupancy_histogram)
        self.verticalLayout.setObjectName(u"verticalLayout")
        self.horizontalLayout = QHBoxLayout()
        self.horizontalLayout.setObjectName(u"horizontalLayout")
        self.label_56 = QLabel(self.groupBox_occupancy_histogram)
        self.label_56.setObjectName(u"label_56")
        self.label_56.setMaximumSize(QSize(16777215, 16777215))
        self.label_56.setAlignment(Qt.AlignRight | Qt.AlignTrailing
                                   | Qt.AlignVCenter)

        self.horizontalLayout.addWidget(self.label_56)

        self.lineEdit_bins = QLineEdit(self.groupBox_occupancy_histogram)
        self.lineEdit_bins.setObjectName(u"lineEdit_bins")
        self.lineEdit_bins.setMinimumSize(QSize(50, 0))
        self.lineEdit_bins.setMaximumSize(QSize(50, 16777215))

        self.horizontalLayout.addWidget(self.lineEdit_bins)

        self.horizontalSpacer_3 = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                              QSizePolicy.Minimum)

        self.horizontalLayout.addItem(self.horizontalSpacer_3)

        self.label_55 = QLabel(self.groupBox_occupancy_histogram)
        self.label_55.setObjectName(u"label_55")
        self.label_55.setMaximumSize(QSize(16777215, 16777215))
        self.label_55.setAlignment(Qt.AlignRight | Qt.AlignTrailing
                                   | Qt.AlignVCenter)

        self.horizontalLayout.addWidget(self.label_55)

        self.lineEdit_minimum = QLineEdit(self.groupBox_occupancy_histogram)
        self.lineEdit_minimum.setObjectName(u"lineEdit_minimum")
        self.lineEdit_minimum.setMinimumSize(QSize(50, 0))
        self.lineEdit_minimum.setMaximumSize(QSize(50, 16777215))

        self.horizontalLayout.addWidget(self.lineEdit_minimum)

        self.horizontalSpacer_2 = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                              QSizePolicy.Minimum)

        self.horizontalLayout.addItem(self.horizontalSpacer_2)

        self.label_17 = QLabel(self.groupBox_occupancy_histogram)
        self.label_17.setObjectName(u"label_17")
        self.label_17.setAlignment(Qt.AlignRight | Qt.AlignTrailing
                                   | Qt.AlignVCenter)

        self.horizontalLayout.addWidget(self.label_17)

        self.lineEdit_maximum = QLineEdit(self.groupBox_occupancy_histogram)
        self.lineEdit_maximum.setObjectName(u"lineEdit_maximum")
        self.lineEdit_maximum.setMinimumSize(QSize(50, 0))
        self.lineEdit_maximum.setMaximumSize(QSize(50, 16777215))

        self.horizontalLayout.addWidget(self.lineEdit_maximum)

        self.verticalLayout.addLayout(self.horizontalLayout)

        self.horizontalLayout_7 = QHBoxLayout()
        self.horizontalLayout_7.setObjectName(u"horizontalLayout_7")
        self.checkBox_cumulative_histogram = QCheckBox(
            self.groupBox_occupancy_histogram)
        self.checkBox_cumulative_histogram.setObjectName(
            u"checkBox_cumulative_histogram")

        self.horizontalLayout_7.addWidget(self.checkBox_cumulative_histogram)

        self.horizontalSpacer_12 = QSpacerItem(40, 20, QSizePolicy.Fixed,
                                               QSizePolicy.Minimum)

        self.horizontalLayout_7.addItem(self.horizontalSpacer_12)

        self.checkBox_stacked_histogram = QCheckBox(
            self.groupBox_occupancy_histogram)
        self.checkBox_stacked_histogram.setObjectName(
            u"checkBox_stacked_histogram")

        self.horizontalLayout_7.addWidget(self.checkBox_stacked_histogram)

        self.horizontalSpacer_11 = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                               QSizePolicy.Minimum)

        self.horizontalLayout_7.addItem(self.horizontalSpacer_11)

        self.verticalLayout.addLayout(self.horizontalLayout_7)

        self.horizontalLayout_6 = QHBoxLayout()
        self.horizontalLayout_6.setObjectName(u"horizontalLayout_6")
        self.checkBox_color_segments_occupancy = QCheckBox(
            self.groupBox_occupancy_histogram)
        self.checkBox_color_segments_occupancy.setObjectName(
            u"checkBox_color_segments_occupancy")
        self.checkBox_color_segments_occupancy.setChecked(True)

        self.horizontalLayout_6.addWidget(
            self.checkBox_color_segments_occupancy)

        self.horizontalSpacer_9 = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                              QSizePolicy.Minimum)

        self.horizontalLayout_6.addItem(self.horizontalSpacer_9)

        self.verticalLayout.addLayout(self.horizontalLayout_6)

        self.horizontalLayout_2 = QHBoxLayout()
        self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
        self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                            QSizePolicy.Minimum)

        self.horizontalLayout_2.addItem(self.horizontalSpacer)

        self.pushButton_save_occupancy = QPushButton(
            self.groupBox_occupancy_histogram)
        self.pushButton_save_occupancy.setObjectName(
            u"pushButton_save_occupancy")

        self.horizontalLayout_2.addWidget(self.pushButton_save_occupancy)

        self.pushButton_plot_occupancy = QPushButton(
            self.groupBox_occupancy_histogram)
        self.pushButton_plot_occupancy.setObjectName(
            u"pushButton_plot_occupancy")
        self.pushButton_plot_occupancy.setAutoDefault(False)

        self.horizontalLayout_2.addWidget(self.pushButton_plot_occupancy)

        self.verticalLayout.addLayout(self.horizontalLayout_2)

        self.verticalLayout_2.addWidget(self.groupBox_occupancy_histogram)

        self.verticalSpacer_2 = QSpacerItem(20, 40, QSizePolicy.Minimum,
                                            QSizePolicy.Expanding)

        self.verticalLayout_2.addItem(self.verticalSpacer_2)

        self.groupBox_nb_connections = QGroupBox(GroupBox)
        self.groupBox_nb_connections.setObjectName(u"groupBox_nb_connections")
        self.verticalLayout_3 = QVBoxLayout(self.groupBox_nb_connections)
        self.verticalLayout_3.setObjectName(u"verticalLayout_3")
        self.horizontalLayout_5 = QHBoxLayout()
        self.horizontalLayout_5.setObjectName(u"horizontalLayout_5")
        self.checkBox_color_segments_timeseries = QCheckBox(
            self.groupBox_nb_connections)
        self.checkBox_color_segments_timeseries.setObjectName(
            u"checkBox_color_segments_timeseries")
        self.checkBox_color_segments_timeseries.setChecked(True)

        self.horizontalLayout_5.addWidget(
            self.checkBox_color_segments_timeseries)

        self.horizontalSpacer_7 = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                              QSizePolicy.Minimum)

        self.horizontalLayout_5.addItem(self.horizontalSpacer_7)

        self.verticalLayout_3.addLayout(self.horizontalLayout_5)

        self.horizontalLayout_4 = QHBoxLayout()
        self.horizontalLayout_4.setObjectName(u"horizontalLayout_4")
        self.horizontalSpacer_5 = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                              QSizePolicy.Minimum)

        self.horizontalLayout_4.addItem(self.horizontalSpacer_5)

        self.pushButton_save_timeseries = QPushButton(
            self.groupBox_nb_connections)
        self.pushButton_save_timeseries.setObjectName(
            u"pushButton_save_timeseries")

        self.horizontalLayout_4.addWidget(self.pushButton_save_timeseries)

        self.pushButton_plot_timeseries = QPushButton(
            self.groupBox_nb_connections)
        self.pushButton_plot_timeseries.setObjectName(
            u"pushButton_plot_timeseries")
        self.pushButton_plot_timeseries.setAutoDefault(False)

        self.horizontalLayout_4.addWidget(self.pushButton_plot_timeseries)

        self.verticalLayout_3.addLayout(self.horizontalLayout_4)

        self.verticalLayout_2.addWidget(self.groupBox_nb_connections)

        self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum,
                                          QSizePolicy.Expanding)

        self.verticalLayout_2.addItem(self.verticalSpacer)

        self.groupBox_joint_occupancy = QGroupBox(GroupBox)
        self.groupBox_joint_occupancy.setObjectName(
            u"groupBox_joint_occupancy")
        self.verticalLayout_4 = QVBoxLayout(self.groupBox_joint_occupancy)
        self.verticalLayout_4.setObjectName(u"verticalLayout_4")
        self.horizontalLayout_10 = QHBoxLayout()
        self.horizontalLayout_10.setObjectName(u"horizontalLayout_10")
        self.radioButton_scatter = QRadioButton(self.groupBox_joint_occupancy)
        self.radioButton_scatter.setObjectName(u"radioButton_scatter")
        self.radioButton_scatter.setChecked(True)

        self.horizontalLayout_10.addWidget(self.radioButton_scatter)

        self.label_3 = QLabel(self.groupBox_joint_occupancy)
        self.label_3.setObjectName(u"label_3")

        self.horizontalLayout_10.addWidget(self.label_3)

        self.lineEdit_scatter_size = QLineEdit(self.groupBox_joint_occupancy)
        self.lineEdit_scatter_size.setObjectName(u"lineEdit_scatter_size")
        self.lineEdit_scatter_size.setMaximumSize(QSize(50, 16777215))

        self.horizontalLayout_10.addWidget(self.lineEdit_scatter_size)

        self.horizontalSpacer_10 = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                               QSizePolicy.Minimum)

        self.horizontalLayout_10.addItem(self.horizontalSpacer_10)

        self.verticalLayout_4.addLayout(self.horizontalLayout_10)

        self.horizontalLayout_3 = QHBoxLayout()
        self.horizontalLayout_3.setObjectName(u"horizontalLayout_3")
        self.radioButton_heatmap = QRadioButton(self.groupBox_joint_occupancy)
        self.radioButton_heatmap.setObjectName(u"radioButton_heatmap")

        self.horizontalLayout_3.addWidget(self.radioButton_heatmap)

        self.horizontalSpacer_4 = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                              QSizePolicy.Minimum)

        self.horizontalLayout_3.addItem(self.horizontalSpacer_4)

        self.pushButton_save_jo = QPushButton(self.groupBox_joint_occupancy)
        self.pushButton_save_jo.setObjectName(u"pushButton_save_jo")

        self.horizontalLayout_3.addWidget(self.pushButton_save_jo)

        self.pushButton_plot_jo = QPushButton(self.groupBox_joint_occupancy)
        self.pushButton_plot_jo.setObjectName(u"pushButton_plot_jo")
        self.pushButton_plot_jo.setAutoDefault(False)

        self.horizontalLayout_3.addWidget(self.pushButton_plot_jo)

        self.verticalLayout_4.addLayout(self.horizontalLayout_3)

        self.verticalLayout_2.addWidget(self.groupBox_joint_occupancy)

        self.retranslateUi(GroupBox)

        QMetaObject.connectSlotsByName(GroupBox)

    # setupUi

    def retranslateUi(self, GroupBox):
        GroupBox.setWindowTitle(
            QCoreApplication.translate("GroupBox", u"GroupBox", None))
        self.groupBox_occupancy_histogram.setTitle(
            QCoreApplication.translate("GroupBox", u"Occupancy histogram",
                                       None))
        self.label_56.setText(
            QCoreApplication.translate("GroupBox", u"# of bins", None))
        self.lineEdit_bins.setText(
            QCoreApplication.translate("GroupBox", u"10", None))
        self.label_55.setText(
            QCoreApplication.translate("GroupBox", u"min. occupancy", None))
        self.lineEdit_minimum.setText(
            QCoreApplication.translate("GroupBox", u"0.0", None))
        self.label_17.setText(
            QCoreApplication.translate("GroupBox", u"max. occupancy", None))
        self.lineEdit_maximum.setText(
            QCoreApplication.translate("GroupBox", u"1.0", None))
        self.checkBox_cumulative_histogram.setText(
            QCoreApplication.translate("GroupBox", u"cumulative", None))
        self.checkBox_stacked_histogram.setText(
            QCoreApplication.translate("GroupBox", u"stacked", None))
        #if QT_CONFIG(tooltip)
        self.checkBox_color_segments_occupancy.setToolTip(
            QCoreApplication.translate(
                "GroupBox",
                u"<html><head/><body><p align=\"justify\">Toggle if histogram bars are colored by segment or molecule. With colors turned on, comparing to other analyses is not possible.</p></body></html>",
                None))
        #endif // QT_CONFIG(tooltip)
        self.checkBox_color_segments_occupancy.setText(
            QCoreApplication.translate("GroupBox", u"color by segment", None))
        self.pushButton_save_occupancy.setText(
            QCoreApplication.translate("GroupBox", u"Data", None))
        #if QT_CONFIG(tooltip)
        self.pushButton_plot_occupancy.setToolTip(
            QCoreApplication.translate(
                "GroupBox",
                u"<html><head/><body><p>Compute histogram of H bond occupancies. Counts the number of H bonds with an occupancy equal or greater than the respective value.</p></body></html>",
                None))
        #endif // QT_CONFIG(tooltip)
        self.pushButton_plot_occupancy.setText(
            QCoreApplication.translate("GroupBox", u"Plot", None))
        self.groupBox_nb_connections.setTitle(
            QCoreApplication.translate("GroupBox",
                                       u"Number of connections time series",
                                       None))
        #if QT_CONFIG(tooltip)
        self.checkBox_color_segments_timeseries.setToolTip(
            QCoreApplication.translate(
                "GroupBox",
                u"<html><head/><body><p align=\"justify\">Toggle if histogram bars are colored by segment or molecule. With colors turned on, comparing to other analyses is not possible.</p></body></html>",
                None))
        #endif // QT_CONFIG(tooltip)
        self.checkBox_color_segments_timeseries.setText(
            QCoreApplication.translate("GroupBox", u"color by segment", None))
        self.pushButton_save_timeseries.setText(
            QCoreApplication.translate("GroupBox", u"Data", None))
        #if QT_CONFIG(tooltip)
        self.pushButton_plot_timeseries.setToolTip(
            QCoreApplication.translate(
                "GroupBox",
                u"<html><head/><body><p align=\"justify\">Compute the number of H bonds per frame.</p></body></html>",
                None))
        #endif // QT_CONFIG(tooltip)
        self.pushButton_plot_timeseries.setText(
            QCoreApplication.translate("GroupBox", u"Plot", None))
        self.groupBox_joint_occupancy.setTitle(
            QCoreApplication.translate("GroupBox", u"Joint Occupancy", None))
        self.radioButton_scatter.setText(
            QCoreApplication.translate("GroupBox", u"scatter plot", None))
        self.label_3.setText(
            QCoreApplication.translate("GroupBox", u"with dot size", None))
        self.lineEdit_scatter_size.setText(
            QCoreApplication.translate("GroupBox", u"1", None))
        self.lineEdit_scatter_size.setPlaceholderText(
            QCoreApplication.translate("GroupBox", u"0 - 100", None))
        self.radioButton_heatmap.setText(
            QCoreApplication.translate("GroupBox", u"heatmap", None))
        self.pushButton_save_jo.setText(
            QCoreApplication.translate("GroupBox", u"Data", None))
        #if QT_CONFIG(tooltip)
        self.pushButton_plot_jo.setToolTip(
            QCoreApplication.translate(
                "GroupBox",
                u"<html><head/><body><p align=\"justify\">Compute the joint occupancy of the H bond network. The joint occupancy is true, if all H bonds of the network are present in a frame and false otherwise.</p></body></html>",
                None))
        #endif // QT_CONFIG(tooltip)
        self.pushButton_plot_jo.setText(
            QCoreApplication.translate("GroupBox", u"Plot", None))
コード例 #5
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()
コード例 #6
0
class Ui_GroupBox(object):
    def setupUi(self, GroupBox):
        if not GroupBox.objectName():
            GroupBox.setObjectName(u"GroupBox")
        GroupBox.resize(528, 576)
        sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Minimum)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(GroupBox.sizePolicy().hasHeightForWidth())
        GroupBox.setSizePolicy(sizePolicy)
        self.verticalLayout_2 = QVBoxLayout(GroupBox)
        self.verticalLayout_2.setObjectName(u"verticalLayout_2")
        self.groupBox = QGroupBox(GroupBox)
        self.groupBox.setObjectName(u"groupBox")
        self.verticalLayout_4 = QVBoxLayout(self.groupBox)
        self.verticalLayout_4.setObjectName(u"verticalLayout_4")
        self.horizontalLayout_7 = QHBoxLayout()
        self.horizontalLayout_7.setObjectName(u"horizontalLayout_7")
        self.horizontalSpacer_7 = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                              QSizePolicy.Minimum)

        self.horizontalLayout_7.addItem(self.horizontalSpacer_7)

        self.pushButton_degree_save = QPushButton(self.groupBox)
        self.pushButton_degree_save.setObjectName(u"pushButton_degree_save")

        self.horizontalLayout_7.addWidget(self.pushButton_degree_save)

        self.verticalLayout_4.addLayout(self.horizontalLayout_7)

        self.verticalLayout_2.addWidget(self.groupBox)

        self.verticalSpacer_2 = QSpacerItem(20, 40, QSizePolicy.Minimum,
                                            QSizePolicy.Expanding)

        self.verticalLayout_2.addItem(self.verticalSpacer_2)

        self.groupBox_degree = QGroupBox(GroupBox)
        self.groupBox_degree.setObjectName(u"groupBox_degree")
        self.verticalLayout_3 = QVBoxLayout(self.groupBox_degree)
        self.verticalLayout_3.setObjectName(u"verticalLayout_3")
        self.horizontalLayout_2 = QHBoxLayout()
        self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
        self.radioButton_betweenness = QRadioButton(self.groupBox_degree)
        self.radioButton_betweenness.setObjectName(u"radioButton_betweenness")

        self.horizontalLayout_2.addWidget(self.radioButton_betweenness)

        self.radioButton_degree = QRadioButton(self.groupBox_degree)
        self.radioButton_degree.setObjectName(u"radioButton_degree")
        self.radioButton_degree.setChecked(True)

        self.horizontalLayout_2.addWidget(self.radioButton_degree)

        self.horizontalSpacer_5 = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                              QSizePolicy.Minimum)

        self.horizontalLayout_2.addItem(self.horizontalSpacer_5)

        self.verticalLayout_3.addLayout(self.horizontalLayout_2)

        self.checkBox_averaged_frames = QCheckBox(self.groupBox_degree)
        self.checkBox_averaged_frames.setObjectName(
            u"checkBox_averaged_frames")
        self.checkBox_averaged_frames.setChecked(True)

        self.verticalLayout_3.addWidget(self.checkBox_averaged_frames)

        self.checkBox_normalized = QCheckBox(self.groupBox_degree)
        self.checkBox_normalized.setObjectName(u"checkBox_normalized")

        self.verticalLayout_3.addWidget(self.checkBox_normalized)

        self.groupBox_per_residue = QGroupBox(self.groupBox_degree)
        self.groupBox_per_residue.setObjectName(u"groupBox_per_residue")
        self.groupBox_per_residue.setCheckable(True)
        self.verticalLayout = QVBoxLayout(self.groupBox_per_residue)
        self.verticalLayout.setObjectName(u"verticalLayout")
        self.horizontalLayout_6 = QHBoxLayout()
        self.horizontalLayout_6.setObjectName(u"horizontalLayout_6")
        self.label_2 = QLabel(self.groupBox_per_residue)
        self.label_2.setObjectName(u"label_2")

        self.horizontalLayout_6.addWidget(self.label_2)

        self.comboBox = QComboBox(self.groupBox_per_residue)
        self.comboBox.setObjectName(u"comboBox")

        self.horizontalLayout_6.addWidget(self.comboBox)

        self.horizontalSpacer_2 = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                              QSizePolicy.Minimum)

        self.horizontalLayout_6.addItem(self.horizontalSpacer_2)

        self.verticalLayout.addLayout(self.horizontalLayout_6)

        self.horizontalLayout = QHBoxLayout()
        self.horizontalLayout.setObjectName(u"horizontalLayout")
        self.label_10 = QLabel(self.groupBox_per_residue)
        self.label_10.setObjectName(u"label_10")
        self.label_10.setAlignment(Qt.AlignRight | Qt.AlignTrailing
                                   | Qt.AlignVCenter)

        self.horizontalLayout.addWidget(self.label_10)

        self.lineEdit_degree_residue_ids = QLineEdit(self.groupBox_per_residue)
        self.lineEdit_degree_residue_ids.setObjectName(
            u"lineEdit_degree_residue_ids")

        self.horizontalLayout.addWidget(self.lineEdit_degree_residue_ids)

        self.horizontalSpacer_6 = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                              QSizePolicy.Minimum)

        self.horizontalLayout.addItem(self.horizontalSpacer_6)

        self.verticalLayout.addLayout(self.horizontalLayout)

        self.verticalLayout_3.addWidget(self.groupBox_per_residue)

        self.groupBox_histogram = QGroupBox(self.groupBox_degree)
        self.groupBox_histogram.setObjectName(u"groupBox_histogram")
        self.groupBox_histogram.setCheckable(True)
        self.groupBox_histogram.setChecked(False)
        self.verticalLayout_5 = QVBoxLayout(self.groupBox_histogram)
        self.verticalLayout_5.setObjectName(u"verticalLayout_5")
        self.horizontalLayout_3 = QHBoxLayout()
        self.horizontalLayout_3.setObjectName(u"horizontalLayout_3")
        self.label_56 = QLabel(self.groupBox_histogram)
        self.label_56.setObjectName(u"label_56")
        self.label_56.setMaximumSize(QSize(16777215, 16777215))
        self.label_56.setAlignment(Qt.AlignRight | Qt.AlignTrailing
                                   | Qt.AlignVCenter)

        self.horizontalLayout_3.addWidget(self.label_56)

        self.lineEdit_bins = QLineEdit(self.groupBox_histogram)
        self.lineEdit_bins.setObjectName(u"lineEdit_bins")
        self.lineEdit_bins.setMinimumSize(QSize(50, 0))
        self.lineEdit_bins.setMaximumSize(QSize(50, 16777215))

        self.horizontalLayout_3.addWidget(self.lineEdit_bins)

        self.label_55 = QLabel(self.groupBox_histogram)
        self.label_55.setObjectName(u"label_55")
        self.label_55.setMaximumSize(QSize(16777215, 16777215))
        self.label_55.setAlignment(Qt.AlignRight | Qt.AlignTrailing
                                   | Qt.AlignVCenter)

        self.horizontalLayout_3.addWidget(self.label_55)

        self.lineEdit_minimum = QLineEdit(self.groupBox_histogram)
        self.lineEdit_minimum.setObjectName(u"lineEdit_minimum")
        self.lineEdit_minimum.setMinimumSize(QSize(50, 0))
        self.lineEdit_minimum.setMaximumSize(QSize(50, 16777215))

        self.horizontalLayout_3.addWidget(self.lineEdit_minimum)

        self.label_17 = QLabel(self.groupBox_histogram)
        self.label_17.setObjectName(u"label_17")
        self.label_17.setAlignment(Qt.AlignRight | Qt.AlignTrailing
                                   | Qt.AlignVCenter)

        self.horizontalLayout_3.addWidget(self.label_17)

        self.lineEdit_maximum = QLineEdit(self.groupBox_histogram)
        self.lineEdit_maximum.setObjectName(u"lineEdit_maximum")
        self.lineEdit_maximum.setMinimumSize(QSize(50, 0))
        self.lineEdit_maximum.setMaximumSize(QSize(50, 16777215))

        self.horizontalLayout_3.addWidget(self.lineEdit_maximum)

        self.horizontalSpacer_3 = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                              QSizePolicy.Minimum)

        self.horizontalLayout_3.addItem(self.horizontalSpacer_3)

        self.verticalLayout_5.addLayout(self.horizontalLayout_3)

        self.horizontalLayout_8 = QHBoxLayout()
        self.horizontalLayout_8.setObjectName(u"horizontalLayout_8")
        self.checkBox_cumulative_histogram = QCheckBox(self.groupBox_histogram)
        self.checkBox_cumulative_histogram.setObjectName(
            u"checkBox_cumulative_histogram")

        self.horizontalLayout_8.addWidget(self.checkBox_cumulative_histogram)

        self.horizontalSpacer_12 = QSpacerItem(40, 20, QSizePolicy.Fixed,
                                               QSizePolicy.Minimum)

        self.horizontalLayout_8.addItem(self.horizontalSpacer_12)

        self.checkBox_stacked_histogram = QCheckBox(self.groupBox_histogram)
        self.checkBox_stacked_histogram.setObjectName(
            u"checkBox_stacked_histogram")

        self.horizontalLayout_8.addWidget(self.checkBox_stacked_histogram)

        self.horizontalSpacer_11 = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                               QSizePolicy.Minimum)

        self.horizontalLayout_8.addItem(self.horizontalSpacer_11)

        self.verticalLayout_5.addLayout(self.horizontalLayout_8)

        self.horizontalLayout_9 = QHBoxLayout()
        self.horizontalLayout_9.setObjectName(u"horizontalLayout_9")
        self.checkBox_color_segments_occupancy = QCheckBox(
            self.groupBox_histogram)
        self.checkBox_color_segments_occupancy.setObjectName(
            u"checkBox_color_segments_occupancy")
        self.checkBox_color_segments_occupancy.setChecked(True)

        self.horizontalLayout_9.addWidget(
            self.checkBox_color_segments_occupancy)

        self.horizontalSpacer_9 = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                              QSizePolicy.Minimum)

        self.horizontalLayout_9.addItem(self.horizontalSpacer_9)

        self.verticalLayout_5.addLayout(self.horizontalLayout_9)

        self.verticalLayout_3.addWidget(self.groupBox_histogram)

        self.horizontalLayout_5 = QHBoxLayout()
        self.horizontalLayout_5.setObjectName(u"horizontalLayout_5")
        self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                            QSizePolicy.Minimum)

        self.horizontalLayout_5.addItem(self.horizontalSpacer)

        self.pushButton_degree_plot = QPushButton(self.groupBox_degree)
        self.pushButton_degree_plot.setObjectName(u"pushButton_degree_plot")
        self.pushButton_degree_plot.setAutoDefault(False)

        self.horizontalLayout_5.addWidget(self.pushButton_degree_plot)

        self.verticalLayout_3.addLayout(self.horizontalLayout_5)

        self.verticalLayout_2.addWidget(self.groupBox_degree)

        self.retranslateUi(GroupBox)

        QMetaObject.connectSlotsByName(GroupBox)

    # setupUi

    def retranslateUi(self, GroupBox):
        GroupBox.setWindowTitle(
            QCoreApplication.translate("GroupBox", u"GroupBox", None))
        self.groupBox.setTitle(
            QCoreApplication.translate("GroupBox", u"All centrality measures",
                                       None))
        self.pushButton_degree_save.setText(
            QCoreApplication.translate("GroupBox", u"Data", None))
        self.groupBox_degree.setTitle(
            QCoreApplication.translate("GroupBox", u"Plots", None))
        self.radioButton_betweenness.setText(
            QCoreApplication.translate("GroupBox", u"betweenness centrality",
                                       None))
        self.radioButton_degree.setText(
            QCoreApplication.translate("GroupBox", u"degree centrality", None))
        #if QT_CONFIG(tooltip)
        self.checkBox_averaged_frames.setToolTip(
            QCoreApplication.translate(
                "GroupBox",
                u"<html><head/><body><p align=\"justify\">Toggle, if absolute number of connections or time averaged number of connections are used.</p></body></html>",
                None))
        #endif // QT_CONFIG(tooltip)
        self.checkBox_averaged_frames.setText(
            QCoreApplication.translate("GroupBox", u"average across frames",
                                       None))
        self.checkBox_normalized.setText(
            QCoreApplication.translate("GroupBox", u"normalized", None))
        self.groupBox_per_residue.setTitle(
            QCoreApplication.translate("GroupBox", u"Per Residue", None))
        self.label_2.setText(
            QCoreApplication.translate("GroupBox", u"segment: ", None))
        self.label_10.setText(
            QCoreApplication.translate("GroupBox", u"residue ids: ", None))
        self.lineEdit_degree_residue_ids.setPlaceholderText(
            QCoreApplication.translate("GroupBox", u"e.g. 0-12, 20, 70-90",
                                       None))
        self.groupBox_histogram.setTitle(
            QCoreApplication.translate("GroupBox", u"Histogram", None))
        self.label_56.setText(
            QCoreApplication.translate("GroupBox", u"# of bins", None))
        self.lineEdit_bins.setText(
            QCoreApplication.translate("GroupBox", u"10", None))
        self.label_55.setText(
            QCoreApplication.translate("GroupBox", u"min. value", None))
        self.lineEdit_minimum.setText(
            QCoreApplication.translate("GroupBox", u"0.0", None))
        self.label_17.setText(
            QCoreApplication.translate("GroupBox", u"max. value", None))
        self.lineEdit_maximum.setText(
            QCoreApplication.translate("GroupBox", u"1.0", None))
        self.checkBox_cumulative_histogram.setText(
            QCoreApplication.translate("GroupBox", u"cumulative", None))
        self.checkBox_stacked_histogram.setText(
            QCoreApplication.translate("GroupBox", u"stacked", None))
        #if QT_CONFIG(tooltip)
        self.checkBox_color_segments_occupancy.setToolTip(
            QCoreApplication.translate(
                "GroupBox",
                u"<html><head/><body><p align=\"justify\">Toggle if histogram bars are colored by segment or molecule. With colors turned on, comparing to other analyses is not possible.</p></body></html>",
                None))
        #endif // QT_CONFIG(tooltip)
        self.checkBox_color_segments_occupancy.setText(
            QCoreApplication.translate("GroupBox", u"color by segment", None))
        #if QT_CONFIG(tooltip)
        self.pushButton_degree_plot.setToolTip(
            QCoreApplication.translate(
                "GroupBox",
                u"<html><head/><body><p align=\"justify\">Compute the number of H bonds per residue. Results are colored by segment.</p></body></html>",
                None))
        #endif // QT_CONFIG(tooltip)
        self.pushButton_degree_plot.setText(
            QCoreApplication.translate("GroupBox", u"Plot", None))
コード例 #7
0
class Ui_dlg_new_tool(object):
    def setupUi(self, dlg_new_tool):
        if not dlg_new_tool.objectName():
            dlg_new_tool.setObjectName(u"dlg_new_tool")
        dlg_new_tool.resize(570, 463)
        dlg_new_tool.setModal(True)
        self.gridLayout_2 = QGridLayout(dlg_new_tool)
        self.gridLayout_2.setObjectName(u"gridLayout_2")
        self.gridLayout = QGridLayout()
        self.gridLayout.setObjectName(u"gridLayout")
        self.te_description = QTextEdit(dlg_new_tool)
        self.te_description.setObjectName(u"te_description")

        self.gridLayout.addWidget(self.te_description, 3, 0, 1, 6)

        self.label = QLabel(dlg_new_tool)
        self.label.setObjectName(u"label")

        self.gridLayout.addWidget(self.label, 0, 0, 1, 1)

        self.lbl_file_exists = QLabel(dlg_new_tool)
        self.lbl_file_exists.setObjectName(u"lbl_file_exists")
        self.lbl_file_exists.setPixmap(QPixmap(u"../resources/OK.png"))

        self.gridLayout.addWidget(self.lbl_file_exists, 0, 5, 1, 1)

        self.label_5 = QLabel(dlg_new_tool)
        self.label_5.setObjectName(u"label_5")

        self.gridLayout.addWidget(self.label_5, 0, 3, 1, 1)

        self.chk_mask_required = QCheckBox(dlg_new_tool)
        self.chk_mask_required.setObjectName(u"chk_mask_required")

        self.gridLayout.addWidget(self.chk_mask_required, 5, 0, 1, 6)

        self.label_4 = QLabel(dlg_new_tool)
        self.label_4.setObjectName(u"label_4")

        self.gridLayout.addWidget(self.label_4, 0, 2, 1, 1)

        self.le_tool_name = QLineEdit(dlg_new_tool)
        self.le_tool_name.setObjectName(u"le_tool_name")

        self.gridLayout.addWidget(self.le_tool_name, 0, 1, 1, 1)

        self.label_3 = QLabel(dlg_new_tool)
        self.label_3.setObjectName(u"label_3")

        self.gridLayout.addWidget(self.label_3, 1, 3, 1, 1)

        self.le_file_name = QLineEdit(dlg_new_tool)
        self.le_file_name.setObjectName(u"le_file_name")
        self.le_file_name.setReadOnly(True)

        self.gridLayout.addWidget(self.le_file_name, 0, 4, 1, 1)

        self.label_6 = QLabel(dlg_new_tool)
        self.label_6.setObjectName(u"label_6")
        font = QFont()
        font.setPointSize(8)
        self.label_6.setFont(font)

        self.gridLayout.addWidget(self.label_6, 1, 2, 1, 1)

        self.le_class_name = QLineEdit(dlg_new_tool)
        self.le_class_name.setObjectName(u"le_class_name")
        self.le_class_name.setReadOnly(True)

        self.gridLayout.addWidget(self.le_class_name, 1, 4, 1, 1)

        self.label_2 = QLabel(dlg_new_tool)
        self.label_2.setObjectName(u"label_2")

        self.gridLayout.addWidget(self.label_2, 2, 0, 1, 6)

        self.label_7 = QLabel(dlg_new_tool)
        self.label_7.setObjectName(u"label_7")

        self.gridLayout.addWidget(self.label_7, 4, 0, 1, 1)

        self.le_package_name = QLineEdit(dlg_new_tool)
        self.le_package_name.setObjectName(u"le_package_name")

        self.gridLayout.addWidget(self.le_package_name, 4, 1, 1, 5)

        self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 2)

        self.verticalLayout_4 = QVBoxLayout()
        self.verticalLayout_4.setObjectName(u"verticalLayout_4")
        self.groupBox = QGroupBox(dlg_new_tool)
        self.groupBox.setObjectName(u"groupBox")
        self.groupBox.setCheckable(False)
        self.verticalLayout = QVBoxLayout(self.groupBox)
        self.verticalLayout.setObjectName(u"verticalLayout")
        self.rb_output_image = QRadioButton(self.groupBox)
        self.rb_output_image.setObjectName(u"rb_output_image")
        self.rb_output_image.setChecked(True)

        self.verticalLayout.addWidget(self.rb_output_image)

        self.rb_output_mask = QRadioButton(self.groupBox)
        self.rb_output_mask.setObjectName(u"rb_output_mask")

        self.verticalLayout.addWidget(self.rb_output_mask)

        self.rb_output_data = QRadioButton(self.groupBox)
        self.rb_output_data.setObjectName(u"rb_output_data")

        self.verticalLayout.addWidget(self.rb_output_data)

        self.rb_output_none = QRadioButton(self.groupBox)
        self.rb_output_none.setObjectName(u"rb_output_none")

        self.verticalLayout.addWidget(self.rb_output_none)

        self.verticalLayout_4.addWidget(self.groupBox)

        self.gb_pipeline_tool_groups = QGroupBox(dlg_new_tool)
        self.gb_pipeline_tool_groups.setObjectName(u"gb_pipeline_tool_groups")

        self.verticalLayout_4.addWidget(self.gb_pipeline_tool_groups)

        self.verticalSpacer = QSpacerItem(
            20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding
        )

        self.verticalLayout_4.addItem(self.verticalSpacer)

        self.gridLayout_2.addLayout(self.verticalLayout_4, 1, 0, 1, 1)

        self.verticalLayout_3 = QVBoxLayout()
        self.verticalLayout_3.setObjectName(u"verticalLayout_3")
        self.groupBox_2 = QGroupBox(dlg_new_tool)
        self.groupBox_2.setObjectName(u"groupBox_2")
        self.verticalLayout_2 = QVBoxLayout(self.groupBox_2)
        self.verticalLayout_2.setObjectName(u"verticalLayout_2")
        self.rb_rt_yes = QRadioButton(self.groupBox_2)
        self.rb_rt_yes.setObjectName(u"rb_rt_yes")

        self.verticalLayout_2.addWidget(self.rb_rt_yes)

        self.rb_rt_no = QRadioButton(self.groupBox_2)
        self.rb_rt_no.setObjectName(u"rb_rt_no")
        self.rb_rt_no.setChecked(True)

        self.verticalLayout_2.addWidget(self.rb_rt_no)

        self.rb_rt_widget = QRadioButton(self.groupBox_2)
        self.rb_rt_widget.setObjectName(u"rb_rt_widget")

        self.verticalLayout_2.addWidget(self.rb_rt_widget)

        self.rb_rt_property = QRadioButton(self.groupBox_2)
        self.rb_rt_property.setObjectName(u"rb_rt_property")

        self.verticalLayout_2.addWidget(self.rb_rt_property)

        self.verticalLayout_3.addWidget(self.groupBox_2)

        self.gb_no_pipeline_tool_groups = QGroupBox(dlg_new_tool)
        self.gb_no_pipeline_tool_groups.setObjectName(u"gb_no_pipeline_tool_groups")

        self.verticalLayout_3.addWidget(self.gb_no_pipeline_tool_groups)

        self.verticalSpacer_2 = QSpacerItem(
            20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding
        )

        self.verticalLayout_3.addItem(self.verticalSpacer_2)

        self.gridLayout_2.addLayout(self.verticalLayout_3, 1, 1, 1, 1)

        self.horizontalLayout = QHBoxLayout()
        self.horizontalLayout.setObjectName(u"horizontalLayout")
        self.horizontalSpacer = QSpacerItem(
            40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum
        )

        self.horizontalLayout.addItem(self.horizontalSpacer)

        self.bt_save = QPushButton(dlg_new_tool)
        self.bt_save.setObjectName(u"bt_save")

        self.horizontalLayout.addWidget(self.bt_save)

        self.bt_cancel = QPushButton(dlg_new_tool)
        self.bt_cancel.setObjectName(u"bt_cancel")

        self.horizontalLayout.addWidget(self.bt_cancel)

        self.gridLayout_2.addLayout(self.horizontalLayout, 2, 1, 1, 1)

        self.gridLayout_2.setColumnStretch(0, 1)
        self.gridLayout_2.setColumnStretch(1, 1)

        self.retranslateUi(dlg_new_tool)

        QMetaObject.connectSlotsByName(dlg_new_tool)

    # setupUi

    def retranslateUi(self, dlg_new_tool):
        dlg_new_tool.setWindowTitle(
            QCoreApplication.translate("dlg_new_tool", u"New tool wizard", None)
        )
        self.te_description.setPlaceholderText(
            QCoreApplication.translate(
                "dlg_new_tool",
                u"Write your tool's description here.\\nYou can use HTML tags",
                None,
            )
        )
        self.label.setText(
            QCoreApplication.translate("dlg_new_tool", u"Tool name:", None)
        )
        self.lbl_file_exists.setText("")
        self.label_5.setText(
            QCoreApplication.translate("dlg_new_tool", u"File name:", None)
        )
        self.chk_mask_required.setText(
            QCoreApplication.translate("dlg_new_tool", u"Requires mask in input", None)
        )
        self.label_4.setText(u"\ud83e\udc62")
        self.label_6.setText(u"\ud83e\udc62")
        self.label_3.setText(
            QCoreApplication.translate("dlg_new_tool", u"Class name", None)
        )
        self.label_2.setText(
            QCoreApplication.translate("dlg_new_tool", u"Description:", None)
        )
        self.label_7.setText(
            QCoreApplication.translate("dlg_new_tool", u"Package:", None)
        )
        self.groupBox.setTitle(
            QCoreApplication.translate("dlg_new_tool", u"Output:", None)
        )
        self.rb_output_image.setText(
            QCoreApplication.translate("dlg_new_tool", u"Image", None)
        )
        self.rb_output_mask.setText(
            QCoreApplication.translate("dlg_new_tool", u"Mask", None)
        )
        self.rb_output_data.setText(
            QCoreApplication.translate("dlg_new_tool", u"Data", None)
        )
        self.rb_output_none.setText(
            QCoreApplication.translate("dlg_new_tool", u"None", None)
        )
        self.gb_pipeline_tool_groups.setTitle(
            QCoreApplication.translate(
                "dlg_new_tool", u"Groups that can be added to pipelines", None
            )
        )
        self.groupBox_2.setTitle(
            QCoreApplication.translate("dlg_new_tool", u"Real time:", None)
        )
        self.rb_rt_yes.setText(QCoreApplication.translate("dlg_new_tool", u"Yes", None))
        self.rb_rt_no.setText(QCoreApplication.translate("dlg_new_tool", u"No", None))
        self.rb_rt_widget.setText(
            QCoreApplication.translate("dlg_new_tool", u"Widget", None)
        )
        self.rb_rt_property.setText(
            QCoreApplication.translate("dlg_new_tool", u"Property", None)
        )
        self.gb_no_pipeline_tool_groups.setTitle(
            QCoreApplication.translate(
                "dlg_new_tool", u"Groups forbiden in pipelines", None
            )
        )
        self.bt_save.setText(QCoreApplication.translate("dlg_new_tool", u"Save", None))
        self.bt_cancel.setText(
            QCoreApplication.translate("dlg_new_tool", u"Close", None)
        )
コード例 #8
0
class AddPlayer(QWidget):
    def __init__(self, playerList, parent=None):

        super(AddPlayer, self).__init__(parent)

        self.playerList = playerList

        mainLayout = QHBoxLayout()
        mainLayout.setContentsMargins(0, 0, 0, 0)
        # self.setMaximumSize(600, 270)
        # self.setMinimumSize(600, 100)
        # self.resize(600, 270)
        self.setLayout(mainLayout)

        baseLayout = QGridLayout()
        mainLayout.addLayout(baseLayout)

        # Labels
        lblPlayerName = QLabel("Player name:")
        lblPlayerName.setObjectName("addPlayerLabels")
        baseLayout.addWidget(lblPlayerName, 0, 0)

        lblGender = QLabel("Gender:")
        lblGender.setObjectName("addPlayerLabels")
        baseLayout.addWidget(lblGender, 1, 0)

        lblPlayerGames = QLabel("Games played:")
        lblPlayerGames.setObjectName("addPlayerLabels")
        baseLayout.addWidget(lblPlayerGames, 2, 0)

        lblGamesWon = QLabel("Games won:")
        lblGamesWon.setObjectName("addPlayerLabels")
        baseLayout.addWidget(lblGamesWon, 3, 0)

        lblPlayedRounds = QLabel("Rounds played:")
        lblPlayedRounds.setObjectName("addPlayerLabels")
        baseLayout.addWidget(lblPlayedRounds, 4, 0)

        # Text fields
        self.txtPlayerName = QTextEdit()
        self.txtPlayerName.setObjectName("addPlayer_txtField")
        baseLayout.addWidget(self.txtPlayerName, 0, 1, 1, 2)
        self.txtPlayerName.setFixedHeight(35)

        self.rbtnMale = QRadioButton("Male")
        self.rbtnMale.setObjectName("addPlayerRadioBtn")
        baseLayout.addWidget(self.rbtnMale, 1, 1, alignment=Qt.AlignCenter)
        self.rbtnMale.setChecked(True)

        self.rbtnFemale = QRadioButton("Female")
        self.rbtnFemale.setObjectName("addPlayerRadioBtn")
        baseLayout.addWidget(self.rbtnFemale, 1, 2)

        self.txtPlayerGames = QTextEdit("0")
        self.txtPlayerGames.setObjectName("addPlayer_txtField")
        baseLayout.addWidget(self.txtPlayerGames, 2, 1, 1, 2)
        self.txtPlayerGames.setFixedHeight(35)

        self.txtPlayerWins = QTextEdit("0")
        self.txtPlayerWins.setObjectName("addPlayer_txtField")
        baseLayout.addWidget(self.txtPlayerWins, 3, 1, 1, 2)
        self.txtPlayerWins.setFixedHeight(35)

        self.txtPlayedRounds = QTextEdit("0")
        self.txtPlayedRounds.setObjectName("addPlayer_txtField")
        baseLayout.addWidget(self.txtPlayedRounds, 4, 1, 1, 2)
        self.txtPlayedRounds.setFixedHeight(35)
        self.txtPlayedRounds.setEnabled(False)

        # Buttons
        btnSavePlayer = QPushButton("Save")
        btnSavePlayer.setFixedHeight(50)
        baseLayout.addWidget(btnSavePlayer, 5, 0)
        btnSavePlayer.clicked.connect(self.savePlayer)

        btnCancel = QPushButton("Cancel")
        btnCancel.setFixedHeight(50)
        baseLayout.addWidget(btnCancel, 5, 1)
        btnCancel.clicked.connect(self.cancel)

    def clearAll(self):

        self.txtPlayerName.clear()
        self.txtPlayerWins.clear()
        self.txtPlayerGames.clear()

    def cancel(self):
        self.hide()
        self.playerList.btnAddPlayer.show()
        self.playerList.btnEditPlayer.show()
        self.playerList.browser.show()
        self.playerList.btnRemovePlayer.show()
        self.playerList.mainWindow.btnBack.show()
        self.playerList.mainWindow.btnStartGame.show()

        self.playerList.setMaximumSize(600, 800)
        self.playerList.browser.refreshView()

    def savePlayer(self):

        name = self.txtPlayerName.toPlainText()

        # check name
        if name:
            if len(name) < 1:
                raise TypeError
        else:
            msg1 = QMessageBox()
            msg1.setText("Player name is not given.")
            msg1.exec_()
            return

        # Check radiobuttons value
        if self.rbtnMale.isChecked():
            gender = "male"
        elif self.rbtnFemale.isChecked():
            gender = "female"
        else:
            msg1 = QMessageBox()
            msg1.setText("Select gender.")
            msg1.exec_()

        gamesPlayed = self.txtPlayerGames.toPlainText()

        # Check games played
        if gamesPlayed:

            try:
                gamesPlayed = int(gamesPlayed)

                if gamesPlayed < 0:
                    raise TypeError
                else:
                    gamesPlayed = str(gamesPlayed)
            except:
                msg2 = QMessageBox()
                msg2.setText(
                    "Invalid number in Games played.\n\nValid: 0-9999")
                msg2.exec_()
                return
        else:
            msg2 = QMessageBox()
            msg2.setText("Number of played games is not given.")
            msg2.exec_()
            return

        wins = self.txtPlayerWins.toPlainText()

        # Check number of wins
        if wins:
            try:
                wins = int(wins)
                if wins < 0:
                    raise TypeError
                else:
                    wins = str(wins)
            except:
                msg3 = QMessageBox()
                msg3.setText("Invalid number in Wins field.\n\nValid: 0-9999")
                msg3.exec_()
                return
        else:
            msg3 = QMessageBox()
            msg3.setText("Number of won games is not given.")
            msg3.exec_()
            return

        dbu.Database().addPlayer(name, gender, gamesPlayed, wins, 0)

        self.hide()
        self.playerList.btnAddPlayer.show()
        self.playerList.btnEditPlayer.show()
        self.playerList.browser.show()
        self.playerList.btnRemovePlayer.show()
        self.playerList.mainWindow.btnBack.show()
        self.playerList.mainWindow.btnStartGame.show()

        self.playerList.setMaximumSize(600, 850)
        self.playerList.browser.refreshView()