예제 #1
0
def test_unit_validator_with_metres_set_as_expected_dimensionality():
    validator = UnitValidator(expected_dimensionality=METRES)

    lengths = ["mile", "cm", "centimetre", "yard", "km"]
    not_lengths = [
        "minute",
        "hour",
        "ounce",
        "stone",
        "pound",
        "amp",
        "abc",
        "c",
        "3.0",
        "123",
        "",
        "`?@#",
        "}",
        "2 metres",
    ]

    for unit in lengths:
        assert validator.validate(unit, 0) == QValidator.Acceptable

    for unit in not_lengths:
        assert validator.validate(unit, 0) == QValidator.Intermediate
def test_unit_validator():
    validator = UnitValidator()

    lengths = ["mile", "cm", "centimetre", "yard", "km"]
    not_lengths = [
        "minute",
        "hour",
        "ounce",
        "stone",
        "pound",
        "amp",
        "abc",
        "c",
        "3.0",
        "123",
        "",
        "`?@#",
        "}",
        "2 metres",
    ]

    for unit in lengths:
        assert validator.validate(unit, 0) == QValidator.Acceptable

    for unit in not_lengths:
        assert validator.validate(unit, 0) == QValidator.Intermediate
예제 #3
0
def test_unit_validator_with_no_expected_dimensionality():
    validator = UnitValidator()

    valid_units = ["deg", "m", "cm", "dm", "rad"]

    invalid_units = ["asdfghj", "degre", "2 degrees"]

    for unit in valid_units:
        assert validator.validate(unit, 0) == QValidator.Acceptable

    for unit in invalid_units:
        assert validator.validate(unit, 0) == QValidator.Intermediate
    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()
예제 #5
0
    def __init__(
        self,
        possible_field_names=None,
        parent: QListWidget = None,
        instrument: "Instrument" = None,  # noqa: F821
        hide_name_field: bool = False,
    ):
        super(FieldWidget, self).__init__(parent)

        if possible_field_names is None:
            possible_field_names = []

        self.edit_dialog = QDialog(parent=self)
        self.attrs_dialog = FieldAttrsDialog(parent=self)
        self.instrument = instrument

        self.field_name_edit = FieldNameLineEdit(possible_field_names)
        self.hide_name_field = hide_name_field
        if hide_name_field:
            self.name = str(uuid.uuid4())

        self.units_line_edit = QLineEdit()
        self.unit_validator = UnitValidator()
        self.units_line_edit.setValidator(self.unit_validator)

        self.unit_validator.is_valid.connect(
            partial(validate_line_edit, self.units_line_edit))
        self.units_line_edit.setPlaceholderText(CommonAttrs.UNITS)

        self.field_type_combo = QComboBox()
        self.field_type_combo.addItems([item.value for item in FieldType])
        self.field_type_combo.currentIndexChanged.connect(
            self.field_type_changed)

        fix_horizontal_size = QSizePolicy()
        fix_horizontal_size.setHorizontalPolicy(QSizePolicy.Fixed)
        self.field_type_combo.setSizePolicy(fix_horizontal_size)

        self.value_type_combo = QComboBox()
        self.value_type_combo.addItems(list(DATASET_TYPE.keys()))
        self.value_type_combo.currentIndexChanged.connect(
            self.dataset_type_changed)

        self.value_line_edit = QLineEdit()
        self.value_line_edit.setPlaceholderText("value")

        self._set_up_value_validator(False)
        self.dataset_type_changed(0)

        self.nx_class_combo = QComboBox()

        self.edit_button = QPushButton("Edit")
        edit_button_size = 50
        self.edit_button.setMaximumSize(edit_button_size, edit_button_size)
        self.edit_button.setSizePolicy(fix_horizontal_size)
        self.edit_button.clicked.connect(self.show_edit_dialog)

        self.attrs_button = QPushButton("Attrs")
        self.attrs_button.setMaximumSize(edit_button_size, edit_button_size)
        self.attrs_button.setSizePolicy(fix_horizontal_size)
        self.attrs_button.clicked.connect(self.show_attrs_dialog)

        self.layout = QHBoxLayout()
        self.layout.addWidget(self.field_name_edit)
        self.layout.addWidget(self.field_type_combo)
        self.layout.addWidget(self.value_line_edit)
        self.layout.addWidget(self.nx_class_combo)
        self.layout.addWidget(self.edit_button)
        self.layout.addWidget(self.value_type_combo)
        self.layout.addWidget(self.units_line_edit)
        self.layout.addWidget(self.attrs_button)

        self.layout.setAlignment(Qt.AlignLeft)
        self.setLayout(self.layout)

        self.setFrameShadow(QFrame.Raised)
        self.setFrameShape(QFrame.StyledPanel)

        # Allow selecting this field widget in a list by clicking on it's contents
        self.field_name_edit.installEventFilter(self)
        if parent is not None:
            self._set_up_name_validator()
            self.field_name_edit.validator().is_valid.emit(False)

        self.value_line_edit.installEventFilter(self)
        self.nx_class_combo.installEventFilter(self)

        # These cause odd double-clicking behaviour when using an event filter so just connecting to the clicked() signals instead.
        self.edit_button.clicked.connect(self.something_clicked)
        self.value_type_combo.highlighted.connect(self.something_clicked)
        self.field_type_combo.highlighted.connect(self.something_clicked)

        # Set the layout for the default field type
        self.field_type_changed()
예제 #6
0
    def __init__(
        self,
        node_parent,
        possible_fields=None,
        parent: QListWidget = None,
        parent_dataset: Dataset = None,
        hide_name_field: bool = False,
        show_only_f142_stream: bool = False,
    ):
        super(FieldWidget, self).__init__(parent)

        possible_field_names = []
        self.default_field_types_dict = {}
        self.streams_widget: StreamFieldsWidget = None
        if possible_fields:
            possible_field_names, default_field_types = zip(*possible_fields)
            self.default_field_types_dict = dict(
                zip(possible_field_names, default_field_types))
        self._show_only_f142_stream = show_only_f142_stream
        self._node_parent = node_parent

        self.edit_dialog = QDialog(parent=self)
        self.attrs_dialog = FieldAttrsDialog(parent=self)
        if self.parent() is not None and self.parent().parent() is not None:
            self.parent().parent().destroyed.connect(self.edit_dialog.close)
            self.parent().parent().destroyed.connect(self.attrs_dialog.close)

        self.field_name_edit = FieldNameLineEdit(possible_field_names)
        if self.default_field_types_dict:
            self.field_name_edit.textChanged.connect(self.update_default_type)
        self.hide_name_field = hide_name_field
        if hide_name_field:
            self.name = str(uuid.uuid4())

        self.units_line_edit = QLineEdit()
        self.unit_validator = UnitValidator()
        self.units_line_edit.setValidator(self.unit_validator)
        self.units_line_edit.setMinimumWidth(20)
        self.units_line_edit.setMaximumWidth(50)
        unit_size_policy = QSizePolicy()
        unit_size_policy.setHorizontalPolicy(QSizePolicy.Preferred)
        unit_size_policy.setHorizontalStretch(1)
        self.units_line_edit.setSizePolicy(unit_size_policy)

        self.unit_validator.is_valid.connect(
            partial(validate_line_edit, self.units_line_edit))
        self.units_line_edit.setPlaceholderText(CommonAttrs.UNITS)

        self.field_type_combo: QComboBox = QComboBox()
        self.field_type_combo.addItems([item.value for item in FieldType])
        self.field_type_combo.currentIndexChanged.connect(
            self.field_type_changed)

        fix_horizontal_size = QSizePolicy()
        fix_horizontal_size.setHorizontalPolicy(QSizePolicy.Fixed)
        self.field_type_combo.setSizePolicy(fix_horizontal_size)

        self.value_type_combo: QComboBox = QComboBox()
        self.value_type_combo.addItems(list(VALUE_TYPE_TO_NP))
        for i, item in enumerate(VALUE_TYPE_TO_NP.keys()):
            if item == ValueTypes.DOUBLE:
                self.value_type_combo.setCurrentIndex(i)
                break
        self.value_type_combo.currentIndexChanged.connect(
            self.dataset_type_changed)

        self.value_line_edit: QLineEdit = QLineEdit()
        self.value_line_edit.setPlaceholderText("value")

        value_size_policy = QSizePolicy()
        value_size_policy.setHorizontalPolicy(QSizePolicy.Preferred)
        value_size_policy.setHorizontalStretch(2)
        self.value_line_edit.setSizePolicy(value_size_policy)

        self._set_up_value_validator(False)
        self.dataset_type_changed(0)

        self.nx_class_combo = QComboBox()

        self.edit_button = QPushButton("Edit")

        edit_button_size = 50
        self.edit_button.setMaximumSize(edit_button_size, edit_button_size)
        self.edit_button.setSizePolicy(fix_horizontal_size)
        self.edit_button.clicked.connect(self.show_edit_dialog)

        self.attrs_button = QPushButton("Attrs")
        self.attrs_button.setMaximumSize(edit_button_size, edit_button_size)
        self.attrs_button.setSizePolicy(fix_horizontal_size)
        self.attrs_button.clicked.connect(self.show_attrs_dialog)

        self.layout = QHBoxLayout()
        self.layout.addWidget(self.field_name_edit)
        self.layout.addWidget(self.field_type_combo)
        self.layout.addWidget(self.value_line_edit)
        self.layout.addWidget(self.nx_class_combo)
        self.layout.addWidget(self.edit_button)
        self.layout.addWidget(self.value_type_combo)
        self.layout.addWidget(self.units_line_edit)
        self.layout.addWidget(self.attrs_button)

        self.layout.setAlignment(Qt.AlignLeft)
        self.setLayout(self.layout)

        self.setFrameShadow(QFrame.Raised)
        self.setFrameShape(QFrame.StyledPanel)

        # Allow selecting this field widget in a list by clicking on it's contents
        self.field_name_edit.installEventFilter(self)
        existing_objects = []
        emit = False
        if isinstance(parent, QListWidget):
            for i in range(self.parent().count()):
                new_field_widget = self.parent().itemWidget(
                    self.parent().item(i))
                if new_field_widget is not self and hasattr(
                        new_field_widget, "name"):
                    existing_objects.append(new_field_widget)
        elif isinstance(self._node_parent, Group):
            for child in self._node_parent.children:
                if child is not parent_dataset and hasattr(child, "name"):
                    existing_objects.append(child)
            emit = True
        self._set_up_name_validator(existing_objects=existing_objects)
        self.field_name_edit.validator().is_valid.emit(emit)

        self.value_line_edit.installEventFilter(self)
        self.nx_class_combo.installEventFilter(self)

        # These cause odd double-clicking behaviour when using an event filter so just connecting to the clicked() signals instead.
        self.edit_button.clicked.connect(self.something_clicked)
        self.value_type_combo.highlighted.connect(self.something_clicked)
        self.field_type_combo.highlighted.connect(self.something_clicked)

        # Set the layout for the default field type
        self.field_type_changed()
    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)