def test_GIVEN_no_input_WHEN_validating_geometry_file_THEN_returns_intermediate_and_emits_signal_with_false(): validator = GeometryFileValidator([]) validator.is_valid = Mock() assert validator.validate("", 0) == QValidator.Intermediate validator.is_valid.emit.assert_called_once_with(False)
def test_GIVEN_file_not_ending_with_correct_suffix_WHEN_validating_geometry_file_THEN_emits_signal_with_false(): file_types = {"OFF files": ["off", ["OFF"]]} validator = GeometryFileValidator(file_types) validator.is_valid = Mock() validator.is_file = lambda x: True assert validator.validate("something.json", 0) == QValidator.Intermediate validator.is_valid.emit.assert_called_once_with(False)
def test_GIVEN_invalid_stl_file_WHEN_validating_geometry_THEN_validity_signal_is_emitted_with_false(): validator = GeometryFileValidator(GEOMETRY_FILE_TYPES) validator.is_valid = Mock() # File with missing endloop statement invalid_stl_file = ( "solid dart\n" "facet normal 0.00000E+000 0.00000E+000 -1.00000E+000\n" "outer loop\n" "vertex 3.10000E+001 4.15500E+001 1.00000E+000\n" "vertex 3.10000E+001 1.00000E+001 1.00000E+000\n" "vertex 1.00000E+000 2.50000E-001 1.00000E+000\n" "endloop\n" "endfacet\n" "facet normal 0.00000E+000 0.00000E+000 -1.00000E+000\n" "outer loop\n" "vertex 3.10000E+001 4.15500E+001 1.00000E+000\n" "vertex 6.10000E+001 2.50000E-001 1.00000E+000\n" "vertex 3.10000E+001 1.00000E+001 1.00000E+000\n" "endloop\n" "endfacet\n" "facet normal 8.09000E-001 5.87800E-001 0.00000E+000\n" "outer loop\n" "vertex 3.10000E+001 4.15500E+001 1.00000E+000\n" "vertex 6.10000E+001 2.50000E-001 6.00000E+000\n" "vertex 6.10000E+001 2.50000E-001 1.00000E+000\n" "endfacet\n" "endsolid dart\n" ) validator.open_file = Mock(return_value=StringIO("".join(invalid_stl_file))) validator.is_file = Mock(return_value=True) assert validator.validate("test.stl", 0) == QValidator.Intermediate validator.is_valid.emit.assert_called_once_with(False)
def test_GIVEN_invalid_off_WHEN_validating_geometry_THEN_validity_signal_is_emitted_with_false(): validator = GeometryFileValidator(GEOMETRY_FILE_TYPES) validator.is_valid = Mock() # File missing a point invalid_off_file = ( "OFF\n" "# cube.off\n" "# A cube\n" "8 6 0\n" "-0.500000 -0.500000 0.500000\n" "0.500000 -0.500000 0.500000\n" "-0.500000 0.500000 0.500000\n" "0.500000 0.500000 0.500000\n" "-0.500000 0.500000 -0.500000\n" "0.500000 0.500000 -0.500000\n" "-0.500000 -0.500000 -0.500000\n" "4 0 1 3 2\n" "4 2 3 5 4\n" "4 4 5 7 6\n" "4 6 7 1 0\n" "4 1 7 5 3\n" "4 6 0 2 4\n" ) validator.open_file = Mock(return_value=StringIO("".join(invalid_off_file))) validator.is_file = Mock(return_value=True) assert validator.validate("test.off", 0) == QValidator.Intermediate validator.is_valid.emit.assert_called_once_with(False)
def test_GIVEN_blank_OFF_file_WHEN_validating_geometry_THEN_validity_signal_is_emitted_with_false(): validator = GeometryFileValidator(GEOMETRY_FILE_TYPES) validator.is_valid = Mock() blank_off_file = "" validator.open_file = Mock(return_value=StringIO("".join(blank_off_file))) validator.is_file = Mock(return_value=True) assert validator.validate("test.off", 0) == QValidator.Intermediate validator.is_valid.emit.assert_called_once_with(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 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)