def test_GIVEN_suggestion_callable_WHEN_validating_line_edit_THEN_callable_is_called( ): line_edit = DummyLineEdit() suggestion = Mock(side_effect="test") validate_line_edit( line_edit, False, tooltip_on_reject="Suggestion: ", suggestion_callable=suggestion, ) assert suggestion.called_once()
def test_GIVEN_suggestion_callable_WHEN_validating_line_edit_with_valid_line_edit_THEN_callable_is_not_called_even_if_suggestion_in_name( ): line_edit = DummyLineEdit() suggestion = Mock(side_effect="test") validate_line_edit( line_edit, True, tooltip_on_reject="Suggestion: ", suggestion_callable=suggestion, ) assert suggestion.not_called()
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 setupUi(self, parent_dialog, pixel_options: PixelOptions = PixelOptions()): """ Sets up push buttons and validators for the add component window. """ super().setupUi(parent_dialog) # Connect the button calls with functions self.ok_button.clicked.connect(self.on_ok) # Disable by default as component name will be missing at the very least. self.ok_button.setEnabled(False) # Set default URL to nexus base classes in web view #self.webEngineView.setUrl( # QUrl( # "http://download.nexusformat.org/doc/html/classes/base_classes/index.html" # ) #) self.meshRadioButton.clicked.connect(self.show_mesh_fields) self.CylinderRadioButton.clicked.connect(self.show_cylinder_fields) self.noShapeRadioButton.clicked.connect(self.show_no_geometry_fields) self.fileBrowseButton.clicked.connect(self.mesh_file_picker) self.fileLineEdit.setValidator(GeometryFileValidator(GEOMETRY_FILE_TYPES)) self.fileLineEdit.validator().is_valid.connect( partial(validate_line_edit, self.fileLineEdit) ) self.fileLineEdit.textChanged.connect(self.populate_pixel_mapping_if_necessary) self.componentTypeComboBox.currentIndexChanged.connect(self.on_nx_class_changed) # Set default geometry type and show the related fields. self.noShapeRadioButton.setChecked(True) self.show_no_geometry_fields() component_list = self.instrument.get_component_list().copy() if self.component_to_edit: for item in component_list: if item.name == self.component_to_edit.name: component_list.remove(item) name_validator = NameValidator(component_list) self.nameLineEdit.setValidator(name_validator) self.nameLineEdit.validator().is_valid.connect( partial( validate_line_edit, self.nameLineEdit, tooltip_on_accept="Component name is valid.", tooltip_on_reject=f"Component name is not valid. Suggestion: ", suggestion_callable=self.generate_name_suggestion, ) ) validate_line_edit(self.fileLineEdit, False) self.unitsLineEdit.setValidator(UnitValidator()) self.unitsLineEdit.validator().is_valid.connect( partial( validate_line_edit, self.unitsLineEdit, tooltip_on_reject="Units not valid", tooltip_on_accept="Units Valid", ) ) self.componentTypeComboBox.addItems(list(self.nx_component_classes.keys())) self.componentTypeComboBox.currentIndexChanged.connect( self.change_pixel_options_visibility ) # Set whatever the default nx_class is so the fields autocompleter can use the possible fields in the nx_class self.on_nx_class_changed() self.fieldsListWidget.itemClicked.connect(self.select_field) self.pixel_options = pixel_options self.pixel_options.setupUi(self.pixelOptionsWidget) self.pixelOptionsWidget.ui = self.pixel_options if self.component_to_edit: parent_dialog.setWindowTitle( f"Edit Component: {get_name_of_node(self.component_to_edit.group)}" ) self.ok_button.setText("Edit Component") self._fill_existing_entries() if self.get_pixel_visibility_condition(): self.pixel_options.fill_existing_entries(self.component_to_edit) self.ok_validator = OkValidator( self.noShapeRadioButton, self.meshRadioButton, self.pixel_options.validator ) self.ok_validator.is_valid.connect(self.ok_button.setEnabled) self.nameLineEdit.validator().is_valid.connect(self.ok_validator.set_name_valid) [ button.clicked.connect(self.ok_validator.validate_ok) for button in [ self.meshRadioButton, self.CylinderRadioButton, self.noShapeRadioButton, ] ] self.unitsLineEdit.validator().is_valid.connect( self.ok_validator.set_units_valid ) self.fileLineEdit.validator().is_valid.connect(self.ok_validator.set_file_valid) self.fileLineEdit.validator().is_valid.connect(self.set_file_valid) # Validate the default values set by the UI self.unitsLineEdit.validator().validate(self.unitsLineEdit.text(), 0) self.nameLineEdit.validator().validate(self.nameLineEdit.text(), 0) self.fileLineEdit.validator().validate(self.fileLineEdit.text(), 0) self.addFieldPushButton.clicked.connect(self.add_field) self.removeFieldPushButton.clicked.connect(self.remove_field) # Connect the pixel mapping press signal the populate pixel mapping method self.pixel_options.pixel_mapping_button_pressed.connect( self.populate_pixel_mapping_if_necessary ) self.cylinderCountSpinBox.valueChanged.connect( self.populate_pixel_mapping_if_necessary ) self.meshRadioButton.clicked.connect(self.set_pixel_related_changes) self.CylinderRadioButton.clicked.connect(self.set_pixel_related_changes) self.noShapeRadioButton.clicked.connect(self.set_pixel_related_changes) self.change_pixel_options_visibility()
def test_GIVEN_invalid_WHEN_validating_line_edit_with_no_tooltip_THEN_tooltip_is_not_changed( ): line_edit = DummyLineEdit() validate_line_edit(line_edit, False) assert line_edit.toolTip == ""
def test_GIVEN_invalid_WHEN_validating_line_edit_with_tooltip_THEN_line_edit_tooltip_is_changed( ): tooltip = "this is invalid" line_edit = DummyLineEdit() validate_line_edit(line_edit, False, tooltip_on_reject=tooltip) assert line_edit.toolTip == tooltip
def test_GIVEN_valid_WHEN_validating_line_edit_THEN_line_edit_turns_white(): line_edit = DummyLineEdit() validate_line_edit(line_edit, True) assert "background-color: #FFFFFF" in line_edit.stylesheet
def test_GIVEN_invalid_WHEN_validating_line_edit_THEN_line_edit_turns_red(): line_edit = DummyLineEdit() validate_line_edit(line_edit, False) assert "background-color: #f6989d" in line_edit.stylesheet
def setupUi(self, pixel_options: PixelOptions = PixelOptions()): """Sets up push buttons and validators for the add component window.""" # Connect the button calls with functions self.ok_button.clicked.connect(self.on_ok) # Disable by default as component name will be missing at the very least. self.ok_button.setEnabled(False) # Set default URL to nexus base classes in web view self.webEngineView.setUrl( QUrl( "http://download.nexusformat.org/doc/html/classes/base_classes/index.html" )) self.placeholder_checkbox.stateChanged.connect( self._disable_fields_and_buttons) self.meshRadioButton.clicked.connect(self.show_mesh_fields) self.boxRadioButton.clicked.connect(self.show_box_fields) self.CylinderRadioButton.clicked.connect(self.show_cylinder_fields) self.noShapeRadioButton.clicked.connect(self.show_no_geometry_fields) self.fileBrowseButton.clicked.connect(self.mesh_file_picker) self.fileLineEdit.setValidator( GeometryFileValidator(GEOMETRY_FILE_TYPES)) self.fileLineEdit.validator().is_valid.connect( partial(validate_line_edit, self.fileLineEdit)) self.fileLineEdit.textChanged.connect( self.populate_pixel_mapping_if_necessary) self.componentTypeComboBox.currentIndexChanged.connect( self.on_nx_class_changed) # Set default geometry type and show the related fields. self.noShapeRadioButton.setChecked(True) self.show_no_geometry_fields() validate_line_edit(self.fileLineEdit, False) self.unitsLineEdit.setValidator( UnitValidator(expected_dimensionality=METRES)) self.unitsLineEdit.validator().is_valid.connect( partial( validate_line_edit, self.unitsLineEdit, tooltip_on_reject="Units not valid", tooltip_on_accept="Units Valid", )) self.componentTypeComboBox.currentIndexChanged.connect( self.change_pixel_options_visibility) # Set whatever the default nx_class is so the fields autocompleter can use the possible fields in the nx_class self.nx_class_changed.connect(self.set_shape_button_visibility) self.on_nx_class_changed() self.fieldsListWidget.itemClicked.connect(self.select_field) self.pixel_options = pixel_options if self.pixel_options: self.pixel_options.setupUi(self.pixelOptionsWidget) self.pixelOptionsWidget.ui = self.pixel_options self.ok_validator = OkValidator(self.noShapeRadioButton, self.meshRadioButton, self.pixel_options.validator) c_group = self._group_container.group if not self.initial_edit: self.setWindowTitle(f"Edit group: {c_group.name}") self.placeholder_checkbox.setChecked(c_group.group_placeholder) self._fill_existing_entries() if (self.get_pixel_visibility_condition() and self.pixel_options and isinstance(c_group, Component)): self.pixel_options.fill_existing_entries(c_group) if c_group.nx_class in NX_CLASSES_WITH_PLACEHOLDERS: self.placeholder_checkbox.setVisible(True) else: self.ok_validator.set_nx_class_valid(False) self.componentTypeComboBox.validator().is_valid.connect( self.ok_validator.set_nx_class_valid) self.componentTypeComboBox.validator().validate( self.componentTypeComboBox.currentText(), 0) self.ok_validator.is_valid.connect(self.ok_button.setEnabled) self.nameLineEdit.validator().is_valid.connect( self.ok_validator.set_name_valid) [ button.clicked.connect(self.ok_validator.validate_ok) for button in [ self.meshRadioButton, self.CylinderRadioButton, self.noShapeRadioButton, self.boxRadioButton, ] ] self.unitsLineEdit.validator().is_valid.connect( self.ok_validator.set_units_valid) self.fileLineEdit.validator().is_valid.connect( self.ok_validator.set_file_valid) self.fileLineEdit.validator().is_valid.connect(self.set_file_valid) # Validate the default values set by the UI self.unitsLineEdit.validator().validate(self.unitsLineEdit.text(), 0) self.nameLineEdit.validator().validate(self.nameLineEdit.text(), 0) if not c_group: self.fileLineEdit.validator().validate(self.fileLineEdit.text(), 0) else: text = (SKIP_VALIDATION if c_group.has_pixel_shape() and not self.fileLineEdit.text() else self.fileLineEdit.text()) self.fileLineEdit.validator().validate(text, 0) self.addFieldPushButton.clicked.connect(self.add_field) self.removeFieldPushButton.clicked.connect(self.remove_field) # Connect the pixel mapping press signal the populate pixel mapping method if self.pixel_options: self.pixel_options.pixel_mapping_button_pressed.connect( self.populate_pixel_mapping_if_necessary) self.cylinderCountSpinBox.valueChanged.connect( self.populate_pixel_mapping_if_necessary) self.meshRadioButton.clicked.connect(self.set_pixel_related_changes) self.CylinderRadioButton.clicked.connect( self.set_pixel_related_changes) self.noShapeRadioButton.clicked.connect(self.set_pixel_related_changes) self.boxRadioButton.clicked.connect(self.set_pixel_related_changes) self.change_pixel_options_visibility() self.setAttribute(Qt.WA_DeleteOnClose)