def _create_categories_boxes(self, size_policy): self._boxes_for_category = {} current_row = 0 for major_item_category in iterate_enum(ItemCategory): if not major_item_category.is_major_category and major_item_category != ItemCategory.ENERGY_TANK: continue category_button = QToolButton(self.major_items_box) category_button.setGeometry(QRect(20, 30, 24, 21)) category_button.setText("+") category_label = QLabel(self.major_items_box) category_label.setSizePolicy(size_policy) category_label.setText(major_item_category.long_name) category_box = QGroupBox(self.major_items_box) category_box.setSizePolicy(size_policy) category_box.setObjectName(f"category_box {major_item_category}") category_layout = QGridLayout(category_box) category_layout.setObjectName(f"category_layout {major_item_category}") self.major_items_layout.addWidget(category_button, 2 * current_row + 1, 0, 1, 1) self.major_items_layout.addWidget(category_label, 2 * current_row + 1, 1, 1, 1) self.major_items_layout.addWidget(category_box, 2 * current_row + 2, 0, 1, 2) self._boxes_for_category[major_item_category] = category_box, category_layout, {} category_button.clicked.connect(partial(_toggle_box_visibility, category_button, category_box)) category_box.setVisible(False) current_row += 1
def _create_categories_boxes(self, item_database: ItemDatabase, size_policy): self._boxes_for_category = {} categories = set() for major_item in item_database.major_items.values(): if not major_item.required: categories.add(major_item.item_category) all_categories = list(iterate_enum(ItemCategory)) current_row = 0 for major_item_category in sorted( categories, key=lambda it: all_categories.index(it)): category_button = QToolButton(self.major_items_box) category_button.setGeometry(QRect(20, 30, 24, 21)) category_button.setText("+") category_label = QLabel(self.major_items_box) category_label.setSizePolicy(size_policy) category_label.setText(major_item_category.long_name) category_box = QGroupBox(self.major_items_box) category_box.setSizePolicy(size_policy) category_box.setObjectName(f"category_box {major_item_category}") category_layout = QGridLayout(category_box) category_layout.setObjectName( f"category_layout {major_item_category}") self.major_items_layout.addWidget(category_button, 2 * current_row + 1, 0, 1, 1) self.major_items_layout.addWidget(category_label, 2 * current_row + 1, 1, 1, 1) self.major_items_layout.addWidget(category_box, 2 * current_row + 2, 0, 1, 2) self._boxes_for_category[ major_item_category] = category_box, category_layout, {} category_button.clicked.connect( partial(_toggle_box_visibility, category_button, category_box)) category_box.setVisible(False) current_row += 1
class MainWidget(QWidget): def __init__(self, parent=None): super(MainWidget, self).__init__(parent) self.chart = QtCharts.QChart() self.series = QtCharts.QBarSeries() self.main_layout = QGridLayout() self.button_layout = QGridLayout() self.font_layout = QFormLayout() self.font_size = QDoubleSpinBox() self.legend_posx = QDoubleSpinBox() self.legend_posy = QDoubleSpinBox() self.legend_width = QDoubleSpinBox() self.legend_height = QDoubleSpinBox() self.detach_legend_button = QPushButton("Toggle attached") self.detach_legend_button.clicked.connect(self.toggle_attached) self.button_layout.addWidget(self.detach_legend_button, 0, 0) self.add_set_button = QPushButton("add barset") self.add_set_button.clicked.connect(self.add_barset) self.button_layout.addWidget(self.add_set_button, 2, 0) self.remove_barset_button = QPushButton("remove barset") self.remove_barset_button.clicked.connect(self.remove_barset) self.button_layout.addWidget(self.remove_barset_button, 3, 0) self.align_button = QPushButton("Align (Bottom)") self.align_button.clicked.connect(self.set_legend_alignment) self.button_layout.addWidget(self.align_button, 4, 0) self.bold_button = QPushButton("Toggle bold") self.bold_button.clicked.connect(self.toggle_bold) self.button_layout.addWidget(self.bold_button, 8, 0) self.italic_button = QPushButton("Toggle italic") self.italic_button.clicked.connect(self.toggle_italic) self.button_layout.addWidget(self.italic_button, 9, 0) self.legend_posx.valueChanged.connect(self.update_legend_layout) self.legend_posy.valueChanged.connect(self.update_legend_layout) self.legend_width.valueChanged.connect(self.update_legend_layout) self.legend_height.valueChanged.connect(self.update_legend_layout) legend_layout = QFormLayout() legend_layout.addRow("HPos", self.legend_posx) legend_layout.addRow("VPos", self.legend_posy) legend_layout.addRow("Width", self.legend_width) legend_layout.addRow("Height", self.legend_height) self.legend_settings = QGroupBox("Detached legend") self.legend_settings.setLayout(legend_layout) self.button_layout.addWidget(self.legend_settings) self.legend_settings.setVisible(False) # Create chart view with the chart self.chart_view = QtCharts.QChartView(self.chart, self) # Create spinbox to modify font size self.font_size.setValue(self.chart.legend().font().pointSizeF()) self.font_size.valueChanged.connect(self.font_size_changed) self.font_layout.addRow("Legend font size", self.font_size) # Create layout for grid and detached legend self.main_layout.addLayout(self.button_layout, 0, 0) self.main_layout.addLayout(self.font_layout, 1, 0) self.main_layout.addWidget(self.chart_view, 0, 1, 3, 1) self.setLayout(self.main_layout) self.create_series() def create_series(self): self.add_barset() self.add_barset() self.add_barset() self.add_barset() self.chart.addSeries(self.series) self.chart.setTitle("Legend detach example") self.chart.createDefaultAxes() self.chart.legend().setVisible(True) self.chart.legend().setAlignment(Qt.AlignBottom) self.chart_view.setRenderHint(QPainter.Antialiasing) def show_legend_spinbox(self): self.legend_settings.setVisible(True) chart_viewrect = self.chart_view.rect() self.legend_posx.setMinimum(0) self.legend_posx.setMaximum(chart_viewrect.width()) self.legend_posx.setValue(150) self.legend_posy.setMinimum(0) self.legend_posy.setMaximum(chart_viewrect.height()) self.legend_posy.setValue(150) self.legend_width.setMinimum(0) self.legend_width.setMaximum(chart_viewrect.width()) self.legend_width.setValue(150) self.legend_height.setMinimum(0) self.legend_height.setMaximum(chart_viewrect.height()) self.legend_height.setValue(75) def hideLegendSpinbox(self): self.legend_settings.setVisible(False) def toggle_attached(self): legend = self.chart.legend() if legend.isAttachedToChart(): legend.detachFromChart() legend.setBackgroundVisible(True) legend.setBrush(QBrush(QColor(128, 128, 128, 128))) legend.setPen(QPen(QColor(192, 192, 192, 192))) self.show_legend_spinbox() self.update_legend_layout() else: legend.attachToChart() legend.setBackgroundVisible(False) self.hideLegendSpinbox() self.update() def add_barset(self): series_count = self.series.count() bar_set = QtCharts.QBarSet("set {}".format(series_count)) delta = series_count * 0.1 bar_set.append([1 + delta, 2 + delta, 3 + delta, 4 + delta]) self.series.append(bar_set) def remove_barset(self): sets = self.series.barSets() len_sets = len(sets) if len_sets > 0: self.series.remove(sets[len_sets - 1]) def set_legend_alignment(self): button = self.sender() legend = self.chart.legend() alignment = legend.alignment() if alignment == Qt.AlignTop: legend.setAlignment(Qt.AlignLeft) if button: button.setText("Align (Left)") elif alignment == Qt.AlignLeft: legend.setAlignment(Qt.AlignBottom) if button: button.setText("Align (Bottom)") elif alignment == Qt.AlignBottom: legend.setAlignment(Qt.AlignRight) if button: button.setText("Align (Right)") else: if button: button.setText("Align (Top)") legend.setAlignment(Qt.AlignTop) def toggle_bold(self): legend = self.chart.legend() font = legend.font() font.setBold(not font.bold()) legend.setFont(font) def toggle_italic(self): legend = self.chart.legend() font = legend.font() font.setItalic(not font.italic()) legend.setFont(font) def font_size_changed(self): legend = self.chart.legend() font = legend.font() font_size = self.font_size.value() if font_size < 1: font_size = 1 font.setPointSizeF(font_size) legend.setFont(font) def update_legend_layout(self): legend = self.chart.legend() rect = QRectF(self.legend_posx.value(), self.legend_posy.value(), self.legend_width.value(), self.legend_height.value()) legend.setGeometry(rect) legend.update()
class StreamFieldsWidget(QDialog): """ A stream widget containing schema-specific properties. """ def __init__(self, parent, show_only_f142_stream: bool = False): super().__init__() self.setParent(parent) self.setLayout(QGridLayout()) self.setWindowModality(Qt.WindowModal) self.setModal(True) self._show_only_f142_stream = show_only_f142_stream self.minimum_spinbox_value = 0 self.maximum_spinbox_value = 100_000_000 self.advanced_options_enabled = False self.hs00_unimplemented_label = QLabel( "hs00 (Event histograms) has not yet been fully implemented.") self.schema_label = QLabel("Schema: ") self.schema_combo = DropDownList() self.schema_validator = SchemaSelectionValidator() self.schema_combo.setValidator(self.schema_validator) self.schema_validator.is_valid.connect( partial(validate_general_widget, self.schema_combo)) self.topic_label = QLabel("Topic: ") self.topic_line_edit = QLineEdit() self.topic_validator = NoEmptyStringValidator() self.topic_line_edit.setValidator(self.topic_validator) self.topic_validator.is_valid.connect( partial( validate_line_edit, self.topic_line_edit, tooltip_on_reject="Topic name can not be empty.", )) validate_line_edit(self.topic_line_edit, False) self.source_label = QLabel("Source: ") self.source_line_edit = QLineEdit() self.source_validator = NoEmptyStringValidator() self.source_line_edit.setValidator(self.source_validator) self.source_validator.is_valid.connect( partial( validate_line_edit, self.source_line_edit, tooltip_on_reject="Source name can not be empty.", )) validate_line_edit(self.source_line_edit, False) self.array_size_label = QLabel("Array size: ") self.array_size_spinbox = QSpinBox() self.array_size_spinbox.setMaximum(np.iinfo(np.int32).max) self.array_size_table = QTableWidget(1, 3) self.array_size_table.setHorizontalHeaderLabels(["x", "y", "z"]) self.array_size_table.setVerticalHeaderLabels([""]) table_height = self.array_size_table.sizeHintForRow( 0) + self.array_size_table.sizeHintForRow(1) self.array_size_table.setMaximumHeight(table_height) self.array_size_table.setFrameStyle(QFrame.NoFrame) self.array_size_table.horizontalHeader().setSectionResizeMode( QHeaderView.Stretch) self.array_size_table.resizeColumnsToContents() self.array_size_table.resizeRowsToContents() self.array_size_table.setItemDelegate( ValueDelegate(int, self.array_size_table)) self.type_label = QLabel("Type: ") self.type_combo = QComboBox() self.type_combo.addItems(F142_TYPES) self.type_combo.setCurrentText("double") self.value_units_edit = QLineEdit() self.value_units_label = QLabel("Value Units:") self.show_advanced_options_button = QPushButton( text="Show/hide advanced options") self.show_advanced_options_button.setCheckable(True) self.show_advanced_options_button.clicked.connect( self.advanced_options_button_clicked) self._set_up_f142_group_box() self._set_up_ev42_group_box() self.scalar_radio = QRadioButton(text=SCALAR) self.scalar_radio.clicked.connect(partial(self._show_array_size, False)) self.scalar_radio.setChecked(True) self.scalar_radio.clicked.emit() self.array_radio = QRadioButton(text=ARRAY) self.array_radio.clicked.connect(partial(self._show_array_size, True)) self.schema_combo.currentTextChanged.connect(self._schema_type_changed) if self._show_only_f142_stream: self.schema_combo.addItems([StreamModules.F142.value]) else: self.schema_combo.addItems([e.value for e in StreamModules]) self.ok_button = QPushButton("OK") self.ok_button.clicked.connect(self.parent().close) self.layout().addWidget(self.schema_label, 0, 0) self.layout().addWidget(self.schema_combo, 0, 1) self.layout().addWidget(self.topic_label, 1, 0) self.layout().addWidget(self.topic_line_edit, 1, 1) self.layout().addWidget(self.source_label, 2, 0) self.layout().addWidget(self.source_line_edit, 2, 1) self.layout().addWidget(self.value_units_label, 3, 0) self.layout().addWidget(self.value_units_edit, 3, 1) self.value_units_label.setVisible(False) self.value_units_edit.setVisible(False) self.layout().addWidget(self.type_label, 4, 0) self.layout().addWidget(self.type_combo, 4, 1) self.layout().addWidget(self.scalar_radio, 5, 0) self.layout().addWidget(self.array_radio, 5, 1) self.layout().addWidget(self.array_size_label, 6, 0) self.layout().addWidget(self.array_size_spinbox, 6, 1) self.layout().addWidget(self.array_size_table, 6, 1) self.layout().addWidget(self.hs00_unimplemented_label, 7, 0, 1, 2) # Spans both rows self.layout().addWidget(self.show_advanced_options_button, 8, 0, 1, 2) self.layout().addWidget(self.f142_advanced_group_box, 9, 0, 1, 2) self.layout().addWidget(self.ev42_advanced_group_box, 10, 0, 1, 2) self.layout().addWidget(self.ok_button, 11, 0, 1, 2) self._schema_type_changed(self.schema_combo.currentText()) self.parent().parent().field_name_edit.setVisible(False) def advanced_options_button_clicked(self): self._show_advanced_options( show=self.show_advanced_options_button.isChecked()) def _set_up_ev42_group_box(self): """ Sets up the UI for ev42 advanced options. """ self.ev42_advanced_group_box = QGroupBox( parent=self.show_advanced_options_button) self.ev42_advanced_group_box.setLayout(QFormLayout()) self.ev42_adc_pulse_debug_label = QLabel(ADC_PULSE_DEBUG) self.ev42_adc_pulse_debug_checkbox = QCheckBox() self.ev42_advanced_group_box.layout().addRow( self.ev42_adc_pulse_debug_label, self.ev42_adc_pulse_debug_checkbox) self.ev42_chunk_size_spinner = ( self.create_label_and_spinbox_for_advanced_option( CHUNK_SIZE, self.ev42_advanced_group_box)) self.ev42_cue_interval_spinner = ( self.create_label_and_spinbox_for_advanced_option( CUE_INTERVAL, self.ev42_advanced_group_box)) def create_label_and_spinbox_for_advanced_option(self, nexus_string: str, group_box: QGroupBox): """ Creates a SpinBox with a label and adds them to GroupBox then returns the SpinBox. :param nexus_string: The nexus string label for the SpinBox. :param group_box: The GroupBox that the label and SpinBox should be added to. :return: The newly created SpinBox. """ label = QLabel(nexus_string) spinner = QSpinBox() spinner.setRange(self.minimum_spinbox_value, self.maximum_spinbox_value) group_box.layout().addRow(label, spinner) return spinner def _set_up_f142_group_box(self): """ Sets up the UI for the f142 advanced options. """ self.f142_advanced_group_box = QGroupBox( parent=self.show_advanced_options_button) self.f142_advanced_group_box.setLayout(QFormLayout()) self.f142_chunk_size_spinner = ( self.create_label_and_spinbox_for_advanced_option( CHUNK_SIZE, self.f142_advanced_group_box)) self.f142_cue_interval_spinner = ( self.create_label_and_spinbox_for_advanced_option( CUE_INTERVAL, self.f142_advanced_group_box)) def _show_advanced_options(self, show): schema = self.schema_combo.currentText() if schema == WriterModules.F142.value: self.f142_advanced_group_box.setVisible(show) elif schema == WriterModules.EV42.value: self.ev42_advanced_group_box.setVisible(show) self.advanced_options_enabled = show def _show_array_size(self, show: bool): self.array_size_spinbox.setVisible(show) self.array_size_label.setVisible(show) def _schema_type_changed(self, schema: str): self.parent().setWindowTitle(f"Editing {schema} stream field") self.hs00_unimplemented_label.setVisible(False) self.f142_advanced_group_box.setVisible(False) self.ev42_advanced_group_box.setVisible(False) self.show_advanced_options_button.setVisible(False) self.show_advanced_options_button.setChecked(False) self.value_units_label.setVisible(False) self.value_units_edit.setVisible(False) self.array_size_table.setVisible(False) if schema == WriterModules.F142.value: self.value_units_label.setVisible(True) self.value_units_edit.setVisible(True) self._set_edits_visible(True, True) self.show_advanced_options_button.setVisible(True) self.f142_advanced_group_box.setVisible(False) elif schema == WriterModules.EV42.value: self._set_edits_visible(True, False) self.show_advanced_options_button.setVisible(True) self.ev42_advanced_group_box.setVisible(False) elif schema == WriterModules.ADAR.value: self._set_edits_visible(True, False) self._show_array_size_table(True) elif schema == WriterModules.HS00.value: self._set_edits_visible(True, False) self.hs00_unimplemented_label.setVisible(True) elif schema == WriterModules.NS10.value: self._set_edits_visible(True, False, "nicos/<device>/<parameter>") elif (schema == WriterModules.TDCTIME.value or schema == WriterModules.SENV.value): self._set_edits_visible(True, False) def _show_array_size_table(self, show: bool): self.array_size_label.setVisible(show) self.array_size_table.setVisible(show) def _set_edits_visible(self, source: bool, type: bool, source_hint=None): self.source_label.setVisible(source) self.source_line_edit.setVisible(source) self.type_label.setVisible(type) self.type_combo.setVisible(type) self.array_radio.setVisible(type) self.scalar_radio.setVisible(type) if source_hint: self.source_line_edit.setPlaceholderText(source_hint) else: self.source_line_edit.setPlaceholderText("") def get_stream_module(self, parent) -> StreamModule: """ Create the stream module :return: The created stream module """ source = self.source_line_edit.text() topic = self.topic_line_edit.text() stream: StreamModule = None type = self.type_combo.currentText() current_schema = self.schema_combo.currentText() if current_schema == WriterModules.F142.value: value_units = self.value_units_edit.text() array_size = self.array_size_spinbox.value() stream = F142Stream( parent_node=parent, source=source, topic=topic, type=type, value_units=value_units, array_size=array_size, ) if array_size: stream.array_size = array_size if self.advanced_options_enabled: self.record_advanced_f142_values(stream) elif current_schema == WriterModules.ADAR.value: array_size = [] for i in range(self.array_size_table.columnCount()): table_value = self.array_size_table.item(0, i) if table_value: array_size.append(int(table_value.text())) stream = ADARStream(parent_node=parent, source=source, topic=topic) stream.array_size = array_size elif current_schema == WriterModules.EV42.value: stream = EV42Stream(parent_node=parent, source=source, topic=topic) if self.advanced_options_enabled: self.record_advanced_ev42_values(stream) elif current_schema == WriterModules.NS10.value: stream = NS10Stream(parent_node=parent, source=source, topic=topic) elif current_schema == WriterModules.SENV.value: stream = SENVStream(parent_node=parent, source=source, topic=topic) elif current_schema == WriterModules.HS00.value: stream = HS00Stream( # type: ignore parent=parent, source=source, topic=topic, data_type=NotImplemented, edge_type=NotImplemented, error_type=NotImplemented, shape=[], ) elif current_schema == WriterModules.TDCTIME.value: stream = TDCTStream(parent_node=parent, source=source, topic=topic) return stream def record_advanced_f142_values(self, stream: F142Stream): """ Save the advanced f142 properties to the stream data object. :param stream: The stream data object to be modified. """ stream.chunk_size = self.f142_chunk_size_spinner.value() stream.cue_interval = self.f142_cue_interval_spinner.value() def record_advanced_ev42_values(self, stream: EV42Stream): """ Save the advanced ev42 properties to the stream data object. :param stream: The stream data object to be modified. """ stream.adc_pulse_debug = self.ev42_adc_pulse_debug_checkbox.isChecked() stream.chunk_size = self.ev42_chunk_size_spinner.value() stream.cue_interval = self.ev42_cue_interval_spinner.value() def fill_in_existing_ev42_fields(self, field: EV42Stream): """ Fill in specific existing ev42 fields into the new UI field. :param field: The stream group """ if check_if_advanced_options_should_be_enabled( [field.adc_pulse_debug, field.chunk_size, field.cue_interval]): self._show_advanced_options(True) self._fill_existing_advanced_ev42_fields(field) def _fill_existing_advanced_ev42_fields(self, field: EV42Stream): """ Fill the fields in the interface with the existing ev42 stream data. :param field: The ev42 stream data object. """ self.ev42_adc_pulse_debug_checkbox.setChecked(field.adc_pulse_debug) self.ev42_chunk_size_spinner.setValue(field.chunk_size) self.ev42_cue_interval_spinner.setValue(field.cue_interval) def fill_in_existing_f142_fields(self, field: F142Stream): """ Fill in specific existing f142 fields into the new UI field. :param field: The stream group """ self.type_combo.setCurrentText(field.type) if field.array_size is not None: self.array_radio.setChecked(True) self.scalar_radio.setChecked(False) self.array_size_spinbox.setValue(field.array_size) else: self.array_radio.setChecked(False) self.scalar_radio.setChecked(True) if field.value_units is not None: self.value_units_edit.setText(field.value_units) if check_if_advanced_options_should_be_enabled( [field.chunk_size, field.cue_interval]): self._show_advanced_options(True) self._fill_existing_advanced_f142_fields(field) def _fill_existing_advanced_f142_fields(self, field: F142Stream): """ Fill the advanced fields in the interface with the existing f142 stream data. :param field: The f412 stream data object. """ self.f142_chunk_size_spinner.setValue(field.chunk_size) self.f142_cue_interval_spinner.setValue(field.cue_interval) def update_existing_stream_info(self, field): """ Fill in stream fields and properties into the new UI field. :param field: The stream group """ if isinstance(field, Group): field = field.children[0] if hasattr(field, "parent_node") and isinstance( field.parent_node, Group): self.schema_validator.set_group(field.parent_node) else: self.schema_validator.set_group(None) schema = field.writer_module self.schema_combo.setCurrentText(schema) self.schema_validator.validate(schema, 0) self.topic_line_edit.setText(field.topic) self.topic_validator.validate(field.topic, 0) self.source_line_edit.setText(field.source) self.source_validator.validate(field.source, 0) if schema == WriterModules.F142.value: self.fill_in_existing_f142_fields(field) elif schema == WriterModules.EV42.value: self.fill_in_existing_ev42_fields(field) elif schema == WriterModules.ADAR.value: for i, val in enumerate(field.array_size): self.array_size_table.setItem(0, i, QTableWidgetItem(str(val)))
class IntroductionPage(QtWidgets.QWizardPage): def __init__(self, *args, **kwargs): super(IntroductionPage, self).__init__(*args, **kwargs) # ____COMBO BOX____ self.radioButtonsContent = QGroupBox('new auction OR load auction') self.radioButtonNew = QRadioButton('new') self.radioButtonLoad = QRadioButton('load') self.radioHBox = QHBoxLayout() self.radioHBox.addWidget(self.radioButtonNew, 0) self.radioHBox.addWidget(self.radioButtonLoad, 1) self.radioButtonsContent.setLayout(self.radioHBox) self.radioButtonNew.toggled self.radioButtonNew.toggled.connect(self.changeViewFromRadio) # ___________________SELECT NUMBER OF CONTENDER_________________________ self.newViewContent = QGroupBox('new auction:') self.newViewContent.setVisible(False) self.titleNumberOfContenders = QLabel('Select number of contenders') self.numberOfContenders = QComboBox() self.numberOfContenders.addItems([ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12' ]) self.newViewBoxLayout = QHBoxLayout() self.newViewBoxLayout.addWidget(self.titleNumberOfContenders, 0) self.newViewBoxLayout.addWidget(self.numberOfContenders, 1) self.newViewContent.setLayout(self.newViewBoxLayout) self.registerField("contenderCount*", self.numberOfContenders) # ___________________LOAD DATA_________________________ self.loadViewContent = QGroupBox('Load data:') self.loadViewContent.setVisible(False) self.titleLoadData = QLabel("Select folder with save") self.loadButton = QPushButton() self.loadButton.setText("search saved file") self.loadViewBoxLayout = QVBoxLayout() self.loadViewBoxLayout.addWidget(self.titleLoadData) self.loadViewBoxLayout.addWidget(self.loadButton) self.loadViewContent.setLayout(self.loadViewBoxLayout) # ___Add Elements to layout___ self.layout = QVBoxLayout() self.layout.addWidget(self.radioButtonsContent) self.layout.addWidget(self.newViewContent) self.layout.addWidget(self.loadViewContent) self.setLayout(self.layout) def checkableNew(self): self.newViewContent.setVisible(True) self.loadViewContent.setVisible(False) def checkableLoad(self): self.newViewContent.setVisible(False) self.loadViewContent.setVisible(True) @Slot() def loadDataClicked(self): print("newAuctionSetted to False") @Slot() def changeViewFromRadio(self, IsRadioButtonNew): if IsRadioButtonNew: print("new RadioButton clicked") self.checkableNew() else: print("load RadioButton clicked") self.checkableLoad() def nextId(self): # return the id of the next page, retrun 1 because Wizard.class1 has problems if self.radioButtonNew.isChecked(): return 1 else: return 2
def _create_ammo_pickup_boxes(self, size_policy, item_database: ItemDatabase): """ Creates the GroupBox with SpinBoxes for selecting the pickup count of all the ammo :param item_database: :return: """ self._ammo_maximum_spinboxes = collections.defaultdict(list) self._ammo_pickup_widgets = {} resource_database = default_prime2_resource_database() for ammo in item_database.ammo.values(): title_layout = QHBoxLayout() title_layout.setObjectName(f"{ammo.name} Title Horizontal Layout") expand_ammo_button = QToolButton(self.ammo_box) expand_ammo_button.setGeometry(QRect(20, 30, 24, 21)) expand_ammo_button.setText("+") title_layout.addWidget(expand_ammo_button) category_label = QLabel(self.ammo_box) category_label.setSizePolicy(size_policy) category_label.setText(ammo.name + "s") title_layout.addWidget(category_label) pickup_box = QGroupBox(self.ammo_box) pickup_box.setSizePolicy(size_policy) layout = QGridLayout(pickup_box) layout.setObjectName(f"{ammo.name} Box Layout") current_row = 0 for ammo_item in ammo.items: item = resource_database.get_by_type_and_index(ResourceType.ITEM, ammo_item) target_count_label = QLabel(pickup_box) target_count_label.setText(f"{item.long_name} Target" if len(ammo.items) > 1 else "Target count") maximum_spinbox = QSpinBox(pickup_box) maximum_spinbox.setMaximum(ammo.maximum) maximum_spinbox.valueChanged.connect(partial(self._on_update_ammo_maximum_spinbox, ammo_item)) self._ammo_maximum_spinboxes[ammo_item].append(maximum_spinbox) layout.addWidget(target_count_label, current_row, 0) layout.addWidget(maximum_spinbox, current_row, 1) current_row += 1 count_label = QLabel(pickup_box) count_label.setText("Pickup Count") count_label.setToolTip("How many instances of this expansion should be placed.") pickup_spinbox = QSpinBox(pickup_box) pickup_spinbox.setMaximum(AmmoState.maximum_pickup_count()) pickup_spinbox.valueChanged.connect(partial(self._on_update_ammo_pickup_spinbox, ammo)) layout.addWidget(count_label, current_row, 0) layout.addWidget(pickup_spinbox, current_row, 1) current_row += 1 if ammo.temporaries: require_major_item_check = QCheckBox(pickup_box) require_major_item_check.setText("Requires the major item to work?") require_major_item_check.stateChanged.connect(partial(self._on_update_ammo_require_major_item, ammo)) layout.addWidget(require_major_item_check, current_row, 0, 1, 2) current_row += 1 else: require_major_item_check = None expected_count = QLabel(pickup_box) expected_count.setWordWrap(True) expected_count.setText(_EXPECTED_COUNT_TEXT_TEMPLATE) expected_count.setToolTip("Some expansions may provide 1 extra, even with no variance, if the total count " "is not divisible by the pickup count.") layout.addWidget(expected_count, current_row, 0, 1, 2) current_row += 1 self._ammo_pickup_widgets[ammo] = (pickup_spinbox, expected_count, expand_ammo_button, category_label, pickup_box, require_major_item_check) expand_ammo_button.clicked.connect(partial(_toggle_box_visibility, expand_ammo_button, pickup_box)) pickup_box.setVisible(False) self.ammo_layout.addLayout(title_layout) self.ammo_layout.addWidget(pickup_box)
def _toggle_box_visibility(toggle_button: QToolButton, box: QGroupBox): box.setVisible(not box.isVisible()) toggle_button.setText("-" if box.isVisible() else "+")
class CategoricalImagesWidget(QWidget): def __init__(self, parent: "QWidget" = None): super().__init__(parent) self._main_layout = QVBoxLayout() self._main_layout.addWidget(QLabel("Not Implemented")) self._train_dir_loader = FileLoaderGroup("Train", pick_directories=True) self._test_dir_loader = FileLoaderGroup("Test", pick_directories=True) self._validation_dir_loader = FileLoaderGroup("Validation", pick_directories=True) self._organization_combobox = QComboBox() self._organization_combobox.addItem( "Use Folder name as category", CategoricalImgDatasetIO.Organization.CategoryOnFolders, ) self._organization_combobox.addItem( "Use Filename as category", CategoricalImgDatasetIO.Organization.CategoryOnFilename, ) self._category_regex_extractor_group = QGroupBox( "Category Extractor Regex") self._category_regex_extractor_layout = QVBoxLayout() self._category_regex_extractor_group.setLayout( self._category_regex_extractor_layout) self._category_regex_textbox = QLineEdit("(.*)") self._category_regex_layout = QFormLayout() self._category_regex_layout.addRow( "Regex:", self._category_regex_textbox, ) self._regex_test_input_textbox = QLineEdit() self._regex_test_output_textbox = QLineEdit() self._regex_test_output_textbox.setReadOnly(True) self._regex_test_layout = QHBoxLayout() self._regex_test_layout.addWidget(QLabel("Test: (Filename) ")) self._regex_test_layout.addWidget(self._regex_test_input_textbox) self._regex_test_layout.addWidget(QLabel(" => (Category): ")) self._regex_test_layout.addWidget(self._regex_test_output_textbox) self._category_regex_extractor_layout.addLayout( self._category_regex_layout) self._category_regex_extractor_layout.addLayout( self._regex_test_layout) self._main_layout = QVBoxLayout() self._main_layout.setContentsMargins(0, 0, 0, 0) self._main_layout.addWidget(self._train_dir_loader) self._main_layout.addWidget(self._test_dir_loader) self._main_layout.addWidget(self._validation_dir_loader) self._main_layout.addWidget(self._organization_combobox) self._main_layout.addWidget(self._category_regex_extractor_group) self.setLayout(self._main_layout) self._category_regex_textbox.textChanged.connect( lambda: self._reload_regex()) self._regex_test_input_textbox.textChanged.connect( lambda: self._reload_regex()) self._organization_combobox.currentIndexChanged[int].connect( lambda: self._update_organization_widgets()) self._reload_regex() self._update_organization_widgets() def load_ttv(self, name: str, x_type: DataType, y_type: DataType): LOGGER.debug("Loading TTV %s", name) def load_dataset(dataset_dir): return ( # Subdir # Organization # Categories CategoricalImgDatasetIO().set_x_type(x_type).set_y_type( y_type).set_organization( self._organization_combobox.currentData() ).set_filename_category_regex( self._category_regex_textbox.text() ).load(dataset_dir) # Absolute path set on filename ) train = load_dataset(self._train_dir_loader.path) test = load_dataset(self._test_dir_loader.path) validation = load_dataset(self._validation_dir_loader.path) return TTVSets(name, train, test, validation) def _reload_regex(self): regex_string = self._category_regex_textbox.text() input_text = self._regex_test_input_textbox.text() match = re.match(regex_string, input_text) if match: try: self._regex_test_output_textbox.setText(match.group(1)) except KeyError: self._regex_test_output_textbox.setText(match.group(0)) else: self._regex_test_output_textbox.setText("[No match]") def update_widgets(self, ttv_dir: str, ttv_description: dict): def update_file_loader_path(dir_loader, dataset_dir, dataset_description): if not dataset_dir: dir_loader.path = "" return if self._organization_combobox.currentIndex() == 0: dataset_dir_path = os.path.join(ttv_dir, dataset_dir) else: dataset_dir_path = ttv_dir dir_loader.path = dataset_dir_path update_file_loader_path(self._train_dir_loader, "train", ttv_description["train"]) update_file_loader_path(self._test_dir_loader, "test", ttv_description["test"]) update_file_loader_path(self._validation_dir_loader, "validation", ttv_description["validation"]) self._update_organization_widgets() def _update_organization_widgets(self): if self._organization_combobox.currentIndex() == 1: self._category_regex_extractor_group.setVisible(True) else: self._category_regex_extractor_group.setVisible(False)
class StreamFieldsWidget(QDialog): """ A stream widget containing schema-specific properties. """ def __init__(self, parent): super().__init__() self.setParent(parent) self.setLayout(QGridLayout()) self.setWindowModality(Qt.WindowModal) self.setModal(True) self.minimum_spinbox_value = 0 self.maximum_spinbox_value = 100_000_000 self.advanced_options_enabled = False self.hs00_unimplemented_label = QLabel( "hs00 (Event histograms) has not yet been fully implemented.") self.schema_label = QLabel("Schema: ") self.schema_combo = QComboBox() self.topic_label = QLabel("Topic: ") self.topic_line_edit = QLineEdit() self.topic_line_edit.setPlaceholderText( "[broker][:port, default=9092]/topic") self.source_label = QLabel("Source: ") self.source_line_edit = QLineEdit() self.array_size_label = QLabel("Array size") self.array_size_spinbox = QSpinBox() self.array_size_spinbox.setMaximum(np.iinfo(np.int32).max) self.type_label = QLabel("Type: ") self.type_combo = QComboBox() self.type_combo.addItems(F142_TYPES) self.type_combo.setCurrentText("double") self.value_units_edit = QLineEdit() self.value_units_label = QLabel("Value Units:") self.show_advanced_options_button = QPushButton( text="Show/hide advanced options") self.show_advanced_options_button.setCheckable(True) self.show_advanced_options_button.clicked.connect( self.advanced_options_button_clicked) self._set_up_f142_group_box() self._set_up_ev42_group_box() self.scalar_radio = QRadioButton(text="Scalar") self.scalar_radio.clicked.connect(partial(self._show_array_size, False)) self.scalar_radio.setChecked(True) self.scalar_radio.clicked.emit() self.array_radio = QRadioButton(text="Array") self.array_radio.clicked.connect(partial(self._show_array_size, True)) self.schema_combo.currentTextChanged.connect(self._schema_type_changed) self.schema_combo.addItems([e.value for e in WriterModules]) self.ok_button = QPushButton("OK") self.ok_button.clicked.connect(self.parent().close) self.layout().addWidget(self.schema_label, 0, 0) self.layout().addWidget(self.schema_combo, 0, 1) self.layout().addWidget(self.topic_label, 1, 0) self.layout().addWidget(self.topic_line_edit, 1, 1) self.layout().addWidget(self.source_label, 2, 0) self.layout().addWidget(self.source_line_edit, 2, 1) self.layout().addWidget(self.value_units_label, 3, 0) self.layout().addWidget(self.value_units_edit, 3, 1) self.value_units_label.setVisible(False) self.value_units_edit.setVisible(False) self.layout().addWidget(self.type_label, 4, 0) self.layout().addWidget(self.type_combo, 4, 1) self.layout().addWidget(self.scalar_radio, 5, 0) self.layout().addWidget(self.array_radio, 5, 1) self.layout().addWidget(self.array_size_label, 6, 0) self.layout().addWidget(self.array_size_spinbox, 6, 1) self.layout().addWidget(self.hs00_unimplemented_label, 7, 0, 1, 2) # Spans both rows self.layout().addWidget(self.show_advanced_options_button, 8, 0, 1, 2) self.layout().addWidget(self.f142_advanced_group_box, 9, 0, 1, 2) self.layout().addWidget(self.ev42_advanced_group_box, 10, 0, 1, 2) self.layout().addWidget(self.ok_button, 11, 0, 1, 2) self._schema_type_changed(self.schema_combo.currentText()) def advanced_options_button_clicked(self): self._show_advanced_options( show=self.show_advanced_options_button.isChecked()) def _set_up_ev42_group_box(self): """ Sets up the UI for ev42 advanced options. """ self.ev42_nexus_elements = [ NEXUS_INDICES_INDEX_EVERY_MB, NEXUS_INDICES_INDEX_EVERY_KB, NEXUS_CHUNK_CHUNK_MB, NEXUS_CHUNK_CHUNK_KB, ] self.ev42_nexus_to_spinner_ui_element = {} self.ev42_advanced_group_box = QGroupBox( parent=self.show_advanced_options_button) self.ev42_advanced_group_box.setLayout(QFormLayout()) self.ev42_adc_pulse_debug_label = QLabel(ADC_PULSE_DEBUG) self.ev42_adc_pulse_debug_checkbox = QCheckBox() self.ev42_advanced_group_box.layout().addRow( self.ev42_adc_pulse_debug_label, self.ev42_adc_pulse_debug_checkbox) self.add_labels_and_spinboxes_for_advanced_options( self.ev42_nexus_elements, self.ev42_advanced_group_box, self.ev42_nexus_to_spinner_ui_element, ) def add_labels_and_spinboxes_for_advanced_options(self, elements, group_box, nexus_to_spinner): for nexus_string in elements: label = QLabel(nexus_string) spinner = QSpinBox() spinner.setRange(self.minimum_spinbox_value, self.maximum_spinbox_value) group_box.layout().addRow(label, spinner) nexus_to_spinner[nexus_string] = spinner def _set_up_f142_group_box(self): """ Sets up the UI for the f142 advanced options. """ self.f142_advanced_group_box = QGroupBox( parent=self.show_advanced_options_button) self.f142_advanced_group_box.setLayout(QFormLayout()) self.f142_nexus_to_spinner_ui_element = {} self.f142_nexus_elements = [ NEXUS_INDICES_INDEX_EVERY_MB, NEXUS_INDICES_INDEX_EVERY_KB, STORE_LATEST_INTO, ] self.add_labels_and_spinboxes_for_advanced_options( self.f142_nexus_elements, self.f142_advanced_group_box, self.f142_nexus_to_spinner_ui_element, ) def _show_advanced_options(self, show): schema = self.schema_combo.currentText() if schema == WriterModules.F142.value: self.f142_advanced_group_box.setVisible(show) elif schema == WriterModules.EV42.value: self.ev42_advanced_group_box.setVisible(show) self.advanced_options_enabled = show def _show_array_size(self, show: bool): self.array_size_spinbox.setVisible(show) self.array_size_label.setVisible(show) def _schema_type_changed(self, schema: str): self.parent().setWindowTitle(f"Editing {schema} stream field") self.hs00_unimplemented_label.setVisible(False) self.f142_advanced_group_box.setVisible(False) self.ev42_advanced_group_box.setVisible(False) self.show_advanced_options_button.setVisible(False) self.show_advanced_options_button.setChecked(False) self.value_units_label.setVisible(False) self.value_units_edit.setVisible(False) if schema == WriterModules.F142.value: self.value_units_label.setVisible(True) self.value_units_edit.setVisible(True) self._set_edits_visible(True, True) self.show_advanced_options_button.setVisible(True) self.f142_advanced_group_box.setVisible(False) elif schema == WriterModules.EV42.value: self._set_edits_visible(True, False) self.show_advanced_options_button.setVisible(True) self.ev42_advanced_group_box.setVisible(False) elif schema == WriterModules.HS00.value: self._set_edits_visible(True, False) self.hs00_unimplemented_label.setVisible(True) elif schema == WriterModules.NS10.value: self._set_edits_visible(True, False, "nicos/<device>/<parameter>") elif (schema == WriterModules.TDCTIME.value or schema == WriterModules.SENV.value): self._set_edits_visible(True, False) def _set_edits_visible(self, source: bool, type: bool, source_hint=None): self.source_label.setVisible(source) self.source_line_edit.setVisible(source) self.type_label.setVisible(type) self.type_combo.setVisible(type) self.array_radio.setVisible(type) self.scalar_radio.setVisible(type) if source_hint: self.source_line_edit.setPlaceholderText(source_hint) else: self.source_line_edit.setPlaceholderText("") def get_stream_group(self) -> h5py.Group: """ Create the stream group with a temporary in-memory HDF5 file. :return: The created HDF group. """ temp_file = create_temporary_in_memory_file() group = temp_file.create_group("children") group.create_dataset(name="type", dtype=STRING_DTYPE, data="stream") stream_group = group.create_group( self.parent().parent().field_name_edit.text()) stream_group.attrs[CommonAttrs.NX_CLASS] = CommonAttrs.NC_STREAM stream_group.create_dataset(name="topic", dtype=STRING_DTYPE, data=self.topic_line_edit.text()) stream_group.create_dataset( name="writer_module", dtype=STRING_DTYPE, data=self.schema_combo.currentText(), ) schema = self.schema_combo.currentText() stream_group.create_dataset("source", dtype=STRING_DTYPE, data=self.source_line_edit.text()) if schema == WriterModules.F142.value: self._create_f142_fields(stream_group) elif schema == WriterModules.EV42.value: self._create_ev42_fields(stream_group) return stream_group def _create_ev42_fields(self, stream_group: h5py.Group): """ Create ev42 fields in the given group if advanced options are specified. :param stream_group: The group to apply fields to. """ if self.advanced_options_enabled: if self.ev42_adc_pulse_debug_checkbox.isChecked(): stream_group.create_dataset( ADC_PULSE_DEBUG, dtype=bool, data=self.ev42_adc_pulse_debug_checkbox.isChecked(), ) self._create_dataset_from_spinner( stream_group, self.ev42_nexus_to_spinner_ui_element) def _create_f142_fields(self, stream_group: h5py.Group): """ Create f142 fields in the given group if advanced options are specified. :param stream_group: The group to apply fields to. """ stream_group.create_dataset("type", dtype=STRING_DTYPE, data=self.type_combo.currentText()) if self.array_radio.isChecked(): stream_group.create_dataset("array_size", data=self.array_size_spinbox.value()) if self.value_units_edit.text(): stream_group.create_dataset("value_units", data=self.value_units_edit.text()) if self.advanced_options_enabled: self._create_dataset_from_spinner( stream_group, self.f142_nexus_to_spinner_ui_element) @staticmethod def _create_dataset_from_spinner(stream_group: h5py.Group, nexus_to_spinner_dict: Dict[str, QSpinBox]): for (nexus_string, ui_element) in nexus_to_spinner_dict.items(): if ui_element.value() > 0: stream_group.create_dataset(nexus_string, dtype=int, data=ui_element.value()) def fill_in_existing_ev42_fields(self, field: h5py.Group): """ Fill in specific existing ev42 fields into the new UI field. :param field: The stream group :param new_ui_field: The new UI field to be filled in """ all_ev42_elements = list(self.ev42_nexus_elements) all_ev42_elements.append(ADC_PULSE_DEBUG) if check_if_advanced_options_should_be_enabled(all_ev42_elements, field): self._show_advanced_options(True) if ADC_PULSE_DEBUG in field.keys(): self.ev42_adc_pulse_debug_checkbox.setChecked( bool(field[ADC_PULSE_DEBUG][()])) fill_in_advanced_options( self.ev42_nexus_to_spinner_ui_element.items(), field) def fill_in_existing_f142_fields(self, field: h5py.Group): """ Fill in specific existing f142 fields into the new UI field. :param field: The stream group :param new_ui_field: The new UI field to be filled in """ self.type_combo.setCurrentText(field["type"][()]) if "array_size" in field.keys(): self.array_radio.setChecked(True) self.scalar_radio.setChecked(False) self.array_size_spinbox.setValue(field["array_size"][()]) else: self.array_radio.setChecked(False) self.scalar_radio.setChecked(True) if check_if_advanced_options_should_be_enabled( self.f142_nexus_elements, field): self._show_advanced_options(True) fill_in_advanced_options( self.f142_nexus_to_spinner_ui_element.items(), field) def update_existing_stream_info(self, field: h5py.Group): """ Fill in stream fields and properties into the new UI field. :param field: The stream group :param new_ui_field: The new UI field to be filled in """ schema = field["writer_module"][()] self.schema_combo.setCurrentText(str(schema)) self.topic_line_edit.setText(str(field["topic"][()])) self.source_line_edit.setText(str(field["source"][()])) if schema == WriterModules.F142.value: self.fill_in_existing_f142_fields(field) elif schema == WriterModules.EV42.value: self.fill_in_existing_ev42_fields(field)
class Window(QDialog): def __init__(self): super(Window, self).__init__() self.label = QLabel('Enter Your Age') self.lineEdit = QLineEdit() self.label1 = QLabel('Year of Birth') self.combo1 = QComboBox() self.okButton = QPushButton('OK') self.moreButton = QPushButton('More') self.moreButton.setCheckable(True) self.groupBox = QGroupBox() self.groupBox.setTitle('Details') self.nameLabel = QLabel('Name') self.nameLineEdit = QLineEdit() self.label3 = QLabel('Year of Birth') self.combo2 = QComboBox() self.topLayout1 = QHBoxLayout() self.topLayout1.addWidget(self.label) self.topLayout1.addWidget(self.lineEdit) self.topLayout2 = QHBoxLayout() self.topLayout2.addWidget(self.label1) self.topLayout2.addWidget(self.combo1) for x in range(ord('A'), ord('F')): self.combo1.addItem(str(chr(x))) self.leftLayout = QVBoxLayout() self.leftLayout.addLayout(self.topLayout1) self.leftLayout.addLayout(self.topLayout2) self.leftLayout.addStretch() self.rightLayout = QVBoxLayout() self.rightLayout.addWidget(self.okButton) self.rightLayout.addWidget(self.moreButton) self.bottomLayout1 = QHBoxLayout() self.bottomLayout1.addWidget(self.nameLabel) self.bottomLayout1.addWidget(self.nameLineEdit) self.bottomLayout2 = QHBoxLayout() self.bottomLayout2.addWidget(self.label3) self.bottomLayout2.addWidget(self.combo2) self.combo2.addItem("None") self.bottomLayout = QVBoxLayout() self.bottomLayout.addLayout(self.bottomLayout1) self.bottomLayout.addLayout(self.bottomLayout2) self.groupBox.setLayout(self.bottomLayout) self.groupBox.setVisible(False) self.moreButton.toggled.connect(lambda v: self.groupBox.setVisible(v)) self.combo2.setMinimumSize(self.combo2.sizeHint()) self.mainLayout = QGridLayout() self.mainLayout.addLayout(self.leftLayout, 0, 0) self.mainLayout.addLayout(self.rightLayout, 0, 1) # self.mainLayout.addLayout(self.bottomLayout, 1, 0) self.mainLayout.addWidget(self.groupBox) self.mainLayout.setSizeConstraint(QLayout.SetFixedSize) self.setLayout(self.mainLayout) def title(self): return 'Window'
class TestWidget(QWidget): def __init__(self, parent=None, options=None): super(TestWidget, self).__init__(parent) self.options = options self.results = [] self.tests = [] self.index = 0 self.total_tests = 1 self.total_try = 0 self.total_spin = QSpinBox(self) self.total_spin.setMinimum(10) self.total_spin.setMaximum(1000) self.total_spin.setValue(self.options.total_default) self.total_spin.setSingleStep(10) # for sync two total spins self.options.total_spin_test = self.total_spin self.index_label = QLabel(self.tr('Test #')) self.start = QPushButton(self.tr('Start')) self.stop = QPushButton(self.tr('Stop')) self.next = QPushButton(self.tr('Next')) self.clear = QPushButton(self.tr('Clear')) self.correct = QLabel() self.smile_face = QPixmap(self.resource_path('./images/smile.png')) self.sad_face = QPixmap(self.resource_path('./images/sad.png')) self.correct.setPixmap(self.smile_face) self.start.setDefault(True) self.next.setEnabled(False) self.clear.setEnabled(False) self.stop.setEnabled(False) self.formula = QLineEdit() self.formula.setAlignment(Qt.AlignRight) self.formula.setReadOnly(True) min_height = 50 self.formula.setMinimumHeight(min_height) self.answer = QLineEdit() self.answer.setMinimumHeight(min_height) self.answer.setFixedWidth(70) self.answer.setValidator(QIntValidator()) self.keyboard_cb = QCheckBox(self.tr('Keyboard')) self.keyboard_cb.setChecked(True) self.keyboard_cb.stateChanged.connect(self.show_keyboard) keyboard_layout = QGridLayout() for i, row in enumerate( ((7, 8, 9), (4, 5, 6), (1, 2, 3), (0, 'C', '='))): for j, key in enumerate(row): btn = QPushButton(str(key)) if key == 'C': btn.clicked.connect(self.key_clear) elif key == '=': btn.clicked.connect(self.next_test) else: btn.clicked.connect(self.key_enter) keyboard_layout.addWidget(btn, i, j) self.keyboard_box = QGroupBox() self.keyboard_box.setLayout(keyboard_layout) layout = QGridLayout() row = 0 hbox = QHBoxLayout() hbox.addWidget(QLabel(self.tr('Total tests'))) hbox.addWidget(self.total_spin) layout.addWidget(self.index_label, row, 0) layout.addLayout(hbox, row, 1) layout.addWidget(self.start, row, 2) layout.addWidget(self.stop, row, 3) layout.addWidget(self.keyboard_cb, row, 4) layout.addWidget(self.keyboard_box, row, 5, 3, 1) row += 1 layout.addWidget(self.formula, row, 0, 1, 3) layout.addWidget(self.answer, row, 3) layout.addWidget(self.correct, row, 4) row += 1 layout.addWidget(self.clear, row, 3) layout.addWidget(self.next, row, 4) row += 1 layout.setColumnStretch(0, 1) self.setLayout(layout) self.start.clicked.connect(self.start_test) self.stop.clicked.connect(self.stop_test) self.next.clicked.connect(self.next_test) self.clear.clicked.connect(self.key_clear) self.total_spin.valueChanged.connect(self.sync_total) self.answer.returnPressed.connect(self.next_test) def resource_path(self, relative_path): try: # PyInstaller creates a temp folder and stores path in _MEIPASS base_path = sys._MEIPASS except Exception: base_path = os.path.abspath(".") if re.match(r'Windows', platform.platform()): return str(PureWindowsPath("%s/%s" % (base_path, relative_path))) else: return os.path.join(base_path, relative_path) @Slot() def show_keyboard(self): if self.keyboard_cb.isChecked(): self.keyboard_box.setVisible(True) else: self.keyboard_box.setVisible(False) @Slot() def key_clear(self): self.answer.clear() @Slot() def key_enter(self): self.answer.setText('%s%s' % (self.answer.text(), self.sender().text())) @Slot() def sync_total(self): self.options.total.setValue(self.total_spin.value()) @Slot() def next_test(self): answer = self.answer.text() if not answer: self.options.err_dialog(self.tr('must answer before click next')) return None last_formula = self.tests[self.index] correct = int(answer) == formula.eval_expr(last_formula) if correct: self.correct.setPixmap(self.smile_face) self.answer.clear() self.index += 1 if self.index < self.total_tests: self.set_test(self.index) self.index_label.setText(self.tr('Test %d' % (self.index + 1))) else: self.correct.setPixmap(self.sad_face) self.total_try += 1 msg = self.tr('Last: %s = %s Rate: %s' % (last_formula, answer, self.correct_rate())) self.status_bar.showMessage(self.convert_operator(msg)) if self.index == self.total_tests: self.show_summary() self.stop_test() return def correct_rate(self): return '{0:.0%}'.format(self.index / self.total_try) def show_summary(self): msg = self.tr('Total attempt: %s Correct: %s Rate: %s' % (self.total_try, self.index, self.correct_rate())) self.options.info_dialog(msg) @Slot() def start_test(self): (filename, upper_limit, lower_limit, n_number, total_tests, operators) = self.options.collect_input() self.total_tests = total_tests # skip filename check in test mode filename = True err_msg = self.options.check_input(filename, upper_limit, lower_limit, operators) if err_msg: self.options.err_dialog(err_msg) else: self.tests, self.results = formula.gen_test( operators, upper_limit, lower_limit, n_number, total_tests) for w in (self.next, self.start, self.stop, self.clear): self.toggle_enable(w) self.set_test(self.index) self.index_label.setText(self.tr('Test %d' % (self.index + 1))) self.next.setDefault(True) def set_test(self, index): text = self.convert_operator(self.tests[index]) self.formula.setText(text) def convert_operator(self, formula): text = re.sub(r'\*', '×', formula) return re.sub(r'\/', '÷', text) def toggle_enable(self, w): if w.isEnabled(): w.setEnabled(False) else: w.setEnabled(True) @Slot() def stop_test(self): for w in (self.next, self.start, self.stop, self.clear): self.toggle_enable(w) self.formula.clear() self.answer.clear() self.status_bar.clearMessage() self.index = 0 self.correct_try = 0 self.total_try = 0 self.index_label.setText(self.tr('Test #'))