Exemplo n.º 1
0
    def save_to_filewriter_json(self):
        filename = file_dialog(True, "Save Filewriter JSON File",
                               JSON_FILE_TYPES)
        if filename:
            dialog = QDialog()
            dialog.setModal(True)
            dialog.setLayout(QGridLayout())
            command_widget = FilewriterCommandWidget()
            dialog.layout().addWidget(command_widget)

            dialog.exec_()
            (
                nexus_file_name,
                broker,
                start_time,
                stop_time,
                service_id,
                abort_on_uninitialised_stream,
                use_swmr,
            ) = command_widget.get_arguments()
            with open(filename, "w") as file:
                filewriter_json_writer.generate_json(
                    self.instrument,
                    file,
                    nexus_file_name=nexus_file_name,
                    broker=broker,
                    start_time=start_time,
                    stop_time=stop_time,
                    service_id=service_id,
                    abort_uninitialised=abort_on_uninitialised_stream,
                    use_swmr=use_swmr,
                )
Exemplo n.º 2
0
 def create_new_show(self):
     w = QDialog()
     w.setWindowTitle("Create New Show")
     w.setLayout(QFormLayout())
     show_name = QLineEdit("New Show")
     w.layout().addRow(QLabel("New Show Title:"), show_name)
     prod_days = QSpinBox()
     w.layout().addRow(QLabel("Days of production:"), prod_days)
     calendar_input = QCalendarWidget()
     w.layout().addRow(QLabel("Start date:"))
     w.layout().addRow(calendar_input)
     if self.shows:  # If a show has already been created.
         previous_show = self.shows[-1]
         prod_days.setValue(previous_show.prod_days)
     accept = QPushButton("Create")
     accept.clicked.connect(w.accept)
     reject = QPushButton("Cancel")
     reject.clicked.connect(w.reject)
     w.layout().addRow(accept, reject)
     if w.exec_() == QDialog.Accepted:
         print("New show name:", show_name.text(), "Days of pre-production",
               prod_days.value())
         selected_date = calendar_input.selectedDate()
         start_date = datetime.date(selected_date.year(),
                                    selected_date.month(),
                                    selected_date.day())
         self.shows.append(
             Show(show_name.text(), prod_days.value(), start_date))
Exemplo n.º 3
0
    def get_connector(self, importee):
        """Shows a QDialog to select a connector for the given source file.
        Mimics similar routine in `spine_io.widgets.import_widget.ImportDialog`

        Args:
            importee (str): Label of the file acting as an importee

        Returns:
            Asynchronous data reader class for the given importee
        """
        connector_list = [
            CSVConnector, ExcelConnector, GdxConnector, JSONConnector
        ]  # add others as needed
        connector_names = [c.DISPLAY_NAME for c in connector_list]
        dialog = QDialog(self._toolbox)
        dialog.setLayout(QVBoxLayout())
        connector_list_wg = QListWidget()
        connector_list_wg.addItems(connector_names)
        # Set current item in `connector_list_wg` based on file extension
        _filename, file_extension = os.path.splitext(importee)
        file_extension = file_extension.lower()
        if file_extension.startswith(".xls"):
            row = connector_list.index(ExcelConnector)
        elif file_extension in (".csv", ".dat", ".txt"):
            row = connector_list.index(CSVConnector)
        elif file_extension == ".gdx":
            row = connector_list.index(GdxConnector)
        elif file_extension == ".json":
            row = connector_list.index(JSONConnector)
        else:
            row = None
        if row is not None:
            connector_list_wg.setCurrentRow(row)
        button_box = QDialogButtonBox(QDialogButtonBox.Ok
                                      | QDialogButtonBox.Cancel)
        button_box.button(QDialogButtonBox.Ok).clicked.connect(dialog.accept)
        button_box.button(QDialogButtonBox.Cancel).clicked.connect(
            dialog.reject)
        connector_list_wg.doubleClicked.connect(dialog.accept)
        dialog.layout().addWidget(connector_list_wg)
        dialog.layout().addWidget(button_box)
        _dirname, filename = os.path.split(importee)
        dialog.setWindowTitle("Select connector for '{}'".format(filename))
        answer = dialog.exec_()
        if answer:
            row = connector_list_wg.currentIndex().row()
            return connector_list[row]
Exemplo n.º 4
0
 def get_date(self, is_start):
     w = QDialog()
     w.setLayout(QFormLayout())
     calendar_input = QCalendarWidget()
     w.layout().addRow(calendar_input)
     accept_button = QPushButton("Accept")
     accept_button.clicked.connect(w.accept)
     cancel_button = QPushButton("Cancel")
     cancel_button.clicked.connect(w.reject)
     w.layout().addRow(accept_button, cancel_button)
     if w.exec() == QDialog.Accepted:
         selected_date = calendar_input.selectedDate()
         new_date = datetime.date(selected_date.year(),
                                  selected_date.month(),
                                  selected_date.day())
         print("New date is", new_date)
         if is_start:
             self.start_date = new_date
             self.start_button.setText(str(new_date))
             if self.end_date:
                 print("Number of days is", self.end_date - self.start_date)
                 self.calendar_view.setColumnCount(
                     (self.end_date - self.start_date).days)
                 date_labels = [
                     str(date) for date in date_iterator(
                         self.start_date, self.end_date)
                 ]
                 self.calendar_view.setHorizontalHeaderLabels(date_labels)
         else:
             self.end_date = new_date
             self.end_button.setText(str(new_date))
             if self.start_date:
                 print("Number of days is",
                       (self.end_date - self.start_date).days)
                 self.calendar_view.setColumnCount(
                     (self.end_date - self.start_date).days)
                 date_labels = [
                     str(date) for date in date_iterator(
                         self.start_date, self.end_date)
                 ]
                 self.calendar_view.setHorizontalHeaderLabels(date_labels)
Exemplo n.º 5
0
 def add_position(self):
     w = QDialog()
     w.setWindowTitle("Create New Position")
     w.setLayout(QFormLayout())
     pos_name = QLineEdit("New Position")
     w.layout().addRow(QLabel("Position Name:"), pos_name)
     pre_pro_days = QSpinBox()
     post_pro_days = QSpinBox()
     w.layout().addRow(QLabel("Days of pre-production:"), pre_pro_days)
     w.layout().addRow(QLabel("Days of immediate post-production:"),
                       post_pro_days)
     accept = QPushButton("Create")
     accept.clicked.connect(w.accept)
     reject = QPushButton("Cancel")
     reject.clicked.connect(w.reject)
     w.layout().addRow(accept, reject)
     if w.exec_() == QDialog.Accepted:
         print("Days of pre-production", pre_pro_days.value(),
               "Days of post-productions", post_pro_days.value())
         new_pos_item = QListWidgetItem(pos_name.text())
         new_pos_item.setFlags(new_pos_item.flags() | Qt.ItemIsEditable)
         self.pos_list_widget.addItem(new_pos_item)
Exemplo n.º 6
0
 def add_crew_member(self):
     w = QDialog()
     w.setWindowTitle("Add New Crew Member")
     w.setLayout(QFormLayout())
     crew_name = QLineEdit("New Crew Member")
     w.layout().addRow(QLabel("Crew Member Name:"), crew_name)
     specialization = QComboBox()
     specialization.addItems([
         "Directing", "Cinematography", "Producing", "Production Design",
         "Editing", "Visual Effects"
     ])
     w.layout().addRow(QLabel("Specialization:"), specialization)
     accept = QPushButton("Create")
     accept.clicked.connect(w.accept)
     reject = QPushButton("Cancel")
     reject.clicked.connect(w.reject)
     w.layout().addRow(accept, reject)
     if w.exec_() == QDialog.Accepted:
         new_crew_item = QListWidgetItem(crew_name.text())
         new_crew_item.setFlags(new_crew_item.flags() | Qt.ItemIsEditable)
         self.crew_list_widget.addItem(new_crew_item)
Exemplo n.º 7
0
class FieldWidget(QFrame):
    # Used for deletion of field
    something_clicked = Signal()

    def dataset_type_changed(self, _):
        self.value_line_edit.validator(
        ).dataset_type_combo = self.value_type_combo
        self.value_line_edit.validator(
        ).field_type_combo = self.field_type_combo
        self.value_line_edit.validator().validate(self.value_line_edit.text(),
                                                  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()

    def _set_up_name_validator(self):
        field_widgets = []
        for i in range(self.parent().count()):
            field_widgets.append(self.parent().itemWidget(
                self.parent().item(i)))

        self.field_name_edit.setValidator(
            NameValidator(field_widgets, invalid_names=INVALID_FIELD_NAMES))
        self.field_name_edit.validator().is_valid.connect(
            partial(
                validate_line_edit,
                self.field_name_edit,
                tooltip_on_accept="Field name is valid.",
                tooltip_on_reject=f"Field name is not valid",
            ))

    @property
    def field_type(self) -> FieldType:
        return FieldType(self.field_type_combo.currentText())

    @field_type.setter
    def field_type(self, field_type: str):
        self.field_type_combo.setCurrentText(field_type)
        self.field_type_changed()

    @property
    def name(self) -> str:
        return self.field_name_edit.text()

    @name.setter
    def name(self, name: str):
        self.field_name_edit.setText(name)

    @property
    def dtype(self) -> Union[h5py.Datatype, h5py.SoftLink, h5py.Group]:
        if self.field_type == FieldType.scalar_dataset:
            return self.value.dtype
        if self.field_type == FieldType.array_dataset:
            return self.table_view.model.array.dtype
        if self.field_type == FieldType.link:
            return h5py.SoftLink
        if self.field_type == FieldType.kafka_stream:
            return h5py.Group

    @dtype.setter
    def dtype(self, dtype: h5py.Datatype):
        type_map = {
            np.object: "String",
            np.float64: "Float",
            np.int64: "Integer"
        }
        for item in type_map.keys():
            if dtype == item:
                self.value_type_combo.setCurrentText(type_map[item])
                return
        self.value_type_combo.setCurrentText(
            next(key for key, value in DATASET_TYPE.items() if value == dtype))

    @property
    def attrs(self) -> h5py.Dataset.attrs:
        return self.value.attrs

    @attrs.setter
    def attrs(self, field: h5py.Dataset):
        self.attrs_dialog.fill_existing_attrs(field)

    @property
    def value(self) -> Union[h5py.Dataset, h5py.Group, h5py.SoftLink]:
        return_object = None
        if self.field_type == FieldType.scalar_dataset:
            dtype = DATASET_TYPE[self.value_type_combo.currentText()]
            val = self.value_line_edit.text()
            if dtype == h5py.special_dtype(vlen=str):
                return_object = create_temporary_in_memory_file(
                ).create_dataset(name=self.name, dtype=dtype, data=val)
            else:
                return_object = create_temporary_in_memory_file(
                ).create_dataset(name=self.name, dtype=dtype, data=dtype(val))
        elif self.field_type == FieldType.array_dataset:
            # Squeeze the array so 1D arrays can exist. Should not affect dimensional arrays.
            return_object = create_temporary_in_memory_file().create_dataset(
                name=self.name, data=np.squeeze(self.table_view.model.array))
        elif self.field_type == FieldType.kafka_stream:
            return_object = self.streams_widget.get_stream_group()
        elif self.field_type == FieldType.link:
            return_object = h5py.SoftLink(self.value_line_edit.text())
        else:
            logging.error(f"unknown field type: {self.name}")
        if self.field_type != FieldType.link:
            for attr_name, attr_value in self.attrs_dialog.get_attrs().items():
                self.instrument.nexus.set_attribute_value(
                    return_object, attr_name, attr_value)
            if self.units and self.units is not None:
                self.instrument.nexus.set_attribute_value(
                    return_object, CommonAttrs.UNITS, self.units)
        return return_object

    @value.setter
    def value(self, value):
        if self.field_type == FieldType.scalar_dataset:
            self.value_line_edit.setText(to_string(value))
        elif self.field_type == FieldType.array_dataset:
            self.table_view.model.array = value
        elif self.field_type == FieldType.link:
            self.value_line_edit.setText(value)

    @property
    def units(self):
        return self.units_line_edit.text()

    @units.setter
    def units(self, new_units):
        self.units_line_edit.setText(new_units)

    def eventFilter(self, watched: QObject, event: QEvent) -> bool:
        if event.type() == QEvent.MouseButtonPress:
            self.something_clicked.emit()
            return True
        else:
            return False

    def field_type_changed(self):
        self.edit_dialog = QDialog(parent=self)
        self._set_up_value_validator(False)
        if self.field_type == FieldType.scalar_dataset:
            self.set_visibility(True, False, False, True)
        elif self.field_type == FieldType.array_dataset:
            self.set_visibility(False, False, True, True)
            self.table_view = ArrayDatasetTableWidget()
        elif self.field_type == FieldType.kafka_stream:
            self.set_visibility(False,
                                False,
                                True,
                                False,
                                show_name_line_edit=True)
            self.streams_widget = StreamFieldsWidget(self.edit_dialog)
        elif self.field_type == FieldType.link:
            self.set_visibility(True, False, False, False)
            self._set_up_value_validator(True)
        elif self.field_type == FieldType.nx_class:
            self.set_visibility(False, True, False, False)

    def _set_up_value_validator(self, is_link: bool):
        self.value_line_edit.setValidator(None)
        if is_link:
            self.value_line_edit.setValidator(
                HDFLocationExistsValidator(self.instrument.nexus.nexus_file,
                                           self.field_type_combo))

            tooltip_on_accept = "Valid HDF path"
            tooltip_on_reject = "HDF Path is not valid"
        else:
            self.value_line_edit.setValidator(
                FieldValueValidator(
                    self.field_type_combo,
                    self.value_type_combo,
                    FieldType.scalar_dataset.value,
                ))
            tooltip_on_accept = "Value is cast-able to numpy type."
            tooltip_on_reject = "Value is not cast-able to selected numpy type."

        self.value_line_edit.validator().is_valid.connect(
            partial(
                validate_line_edit,
                self.value_line_edit,
                tooltip_on_accept=tooltip_on_accept,
                tooltip_on_reject=tooltip_on_reject,
            ))
        self.value_line_edit.validator().validate(self.value_line_edit.text(),
                                                  None)

    def set_visibility(
        self,
        show_value_line_edit: bool,
        show_nx_class_combo: bool,
        show_edit_button: bool,
        show_value_type_combo: bool,
        show_name_line_edit: bool = True,
    ):
        self.value_line_edit.setVisible(show_value_line_edit)
        self.nx_class_combo.setVisible(show_nx_class_combo)
        self.edit_button.setVisible(show_edit_button)
        self.value_type_combo.setVisible(show_value_type_combo)
        self.field_name_edit.setVisible(show_name_line_edit
                                        and not self.hide_name_field)

    def show_edit_dialog(self):
        if self.field_type == FieldType.array_dataset:
            self.edit_dialog.setLayout(QGridLayout())
            self.table_view.model.update_array_dtype(
                DATASET_TYPE[self.value_type_combo.currentText()])
            self.edit_dialog.layout().addWidget(self.table_view)
            self.edit_dialog.setWindowTitle(
                f"Edit {self.value_type_combo.currentText()} Array field")
        elif self.field_type == FieldType.kafka_stream:
            self.edit_dialog.setLayout(QFormLayout())
            self.edit_dialog.layout().addWidget(self.streams_widget)
        elif self.field_type.currentText() == FieldType.nx_class:
            # TODO: show nx class panels
            pass
        self.edit_dialog.show()

    def show_attrs_dialog(self):
        self.attrs_dialog.show()
Exemplo n.º 8
0
class FieldWidget(QFrame):
    # Used for deletion of field
    something_clicked = Signal()
    enable_3d_value_spinbox = Signal(bool)

    def dataset_type_changed(self, _):
        self.value_line_edit.validator(
        ).dataset_type_combo = self.value_type_combo
        self.value_line_edit.validator(
        ).field_type_combo = self.field_type_combo
        self.value_line_edit.validator().validate(self.value_line_edit.text(),
                                                  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 _set_up_name_validator(
            self, existing_objects: List[Union["FieldWidget",
                                               FileWriterModule]]):
        self.field_name_edit.setValidator(
            NameValidator(existing_objects, invalid_names=INVALID_FIELD_NAMES))
        self.field_name_edit.validator().is_valid.connect(
            partial(
                validate_line_edit,
                self.field_name_edit,
                tooltip_on_accept="Field name is valid.",
                tooltip_on_reject="Field name is not valid",
            ))

    @property
    def field_type(self) -> FieldType:
        return FieldType(self.field_type_combo.currentText())

    @field_type.setter
    def field_type(self, field_type: FieldType):
        self.field_type_combo.setCurrentText(field_type.value)
        self.field_type_changed()

    @property
    def name(self) -> str:
        return self.field_name_edit.text()

    @name.setter
    def name(self, name: str):
        self.field_name_edit.setText(name)

    @property
    def dtype(self) -> str:
        return self.value_type_combo.currentText()

    @dtype.setter
    def dtype(self, dtype: str):
        self.value_type_combo.setCurrentText(dtype)

    @property
    def attrs(self):
        return self.value.attributes

    @attrs.setter
    def attrs(self, field: Dataset):
        self.attrs_dialog.fill_existing_attrs(field)

    @property
    def value(self) -> Union[FileWriterModule, None]:
        dtype = self.value_type_combo.currentText()
        return_object: FileWriterModule
        if self.field_type == FieldType.scalar_dataset:
            val = self.value_line_edit.text()
            return_object = Dataset(
                parent_node=self._node_parent,
                name=self.name,
                type=dtype,
                values=val,
            )
        elif self.field_type == FieldType.array_dataset:
            # Squeeze the array so 1D arrays can exist. Should not affect dimensional arrays.
            array = np.squeeze(self.table_view.model.array)
            return_object = Dataset(
                parent_node=self._node_parent,
                name=self.name,
                type=dtype,
                values=array,
            )
        elif self.field_type == FieldType.kafka_stream:
            return_object = self.streams_widget.get_stream_module(
                self._node_parent)
        elif self.field_type == FieldType.link:
            return_object = Link(
                parent_node=self._node_parent,
                name=self.name,
                source=self.value_line_edit.text(),
            )
        else:
            logging.error(f"unknown field type: {self.name}")
            return None

        if self.field_type != FieldType.link:
            for name, value, dtype in self.attrs_dialog.get_attrs():
                return_object.attributes.set_attribute_value(
                    attribute_name=name,
                    attribute_value=value,
                    attribute_type=dtype,
                )
            if self.units and self.units is not None:
                return_object.attributes.set_attribute_value(
                    CommonAttrs.UNITS, self.units)
        return return_object

    @value.setter
    def value(self, value):
        if self.field_type == FieldType.scalar_dataset:
            self.value_line_edit.setText(to_string(value))
        elif self.field_type == FieldType.array_dataset:
            self.table_view.model.array = value
        elif self.field_type == FieldType.link:
            self.value_line_edit.setText(value)

    @property
    def units(self) -> str:
        return self.units_line_edit.text()

    @units.setter
    def units(self, new_units: str):
        self.units_line_edit.setText(new_units)

    def update_default_type(self):
        self.value_type_combo.setCurrentText(
            self.default_field_types_dict.get(self.field_name_edit.text(),
                                              "double"))

    def eventFilter(self, watched: QObject, event: QEvent) -> bool:
        if event.type() == QEvent.MouseButtonPress:
            self.something_clicked.emit()
            return True
        else:
            return False

    def field_type_is_scalar(self) -> bool:
        return self.field_type == FieldType.scalar_dataset

    def field_type_changed(self):
        self.edit_dialog = QDialog(parent=self)
        self.edit_dialog.setModal(True)
        self._set_up_value_validator(False)
        self.enable_3d_value_spinbox.emit(not self.field_type_is_scalar())

        if self.field_type == FieldType.scalar_dataset:
            self.set_visibility(True, False, False, True)
        elif self.field_type == FieldType.array_dataset:
            self.set_visibility(False, False, True, True)
            self.table_view = ArrayDatasetTableWidget()
        elif self.field_type == FieldType.kafka_stream:
            self.set_visibility(False,
                                False,
                                True,
                                False,
                                show_name_line_edit=True)
            self.streams_widget = StreamFieldsWidget(
                self.edit_dialog,
                show_only_f142_stream=self._show_only_f142_stream)
        elif self.field_type == FieldType.link:
            self.set_visibility(
                True,
                False,
                False,
                False,
                show_unit_line_edit=False,
                show_attrs_edit=False,
            )
            self._set_up_value_validator(False)

    def _set_up_value_validator(self, is_link: bool):
        self.value_line_edit.setValidator(None)
        if is_link:
            return
        else:
            self.value_line_edit.setValidator(
                FieldValueValidator(
                    self.field_type_combo,
                    self.value_type_combo,
                    FieldType.scalar_dataset.value,
                ))
            tooltip_on_accept = "Value is cast-able to numpy type."
            tooltip_on_reject = "Value is not cast-able to selected numpy type."

        self.value_line_edit.validator().is_valid.connect(
            partial(
                validate_line_edit,
                self.value_line_edit,
                tooltip_on_accept=tooltip_on_accept,
                tooltip_on_reject=tooltip_on_reject,
            ))
        self.value_line_edit.validator().validate(self.value_line_edit.text(),
                                                  None)

    def set_visibility(
        self,
        show_value_line_edit: bool,
        show_nx_class_combo: bool,
        show_edit_button: bool,
        show_value_type_combo: bool,
        show_name_line_edit: bool = True,
        show_attrs_edit: bool = True,
        show_unit_line_edit: bool = True,
    ):
        self.value_line_edit.setVisible(show_value_line_edit)
        self.nx_class_combo.setVisible(show_nx_class_combo)
        self.edit_button.setVisible(show_edit_button)
        self.value_type_combo.setVisible(show_value_type_combo)
        self.units_line_edit.setVisible(show_unit_line_edit)
        self.attrs_button.setVisible(show_attrs_edit)
        self.field_name_edit.setVisible(show_name_line_edit
                                        and not self.hide_name_field)

    def show_edit_dialog(self):
        if self.field_type == FieldType.array_dataset:
            self.edit_dialog.setLayout(QGridLayout())
            self.table_view.model.update_array_dtype(
                VALUE_TYPE_TO_NP[self.value_type_combo.currentText()])
            self.edit_dialog.layout().addWidget(self.table_view)
            self.edit_dialog.setWindowTitle(
                f"Edit {self.value_type_combo.currentText()} Array field")
        elif self.field_type == FieldType.kafka_stream:
            self.edit_dialog.setLayout(QFormLayout())
            self.edit_dialog.layout().addWidget(self.streams_widget)
        if self.edit_dialog.isVisible():
            self.edit_dialog.raise_()
        else:
            self.edit_dialog.show()

    def show_attrs_dialog(self):
        self.attrs_dialog.show()
Exemplo n.º 9
0
class DatePicker(QWidget):

    selectionChanged = Signal()

    def __init__(self, parent=None):
        super(DatePicker, self).__init__(parent)
        self.button = QPushButton(self)
        icon = QIcon("logo.svg")
        self.button.setIcon(icon)
        self.setFixedSize(32, 32)
        self.button.setFixedSize(32, 32)
        self.button.setIconSize(QSize(22, 22))

        self.__margin__ = 5

        self.dialog = QDialog()
        self.dialog.setWindowFlags(Qt.Window | Qt.FramelessWindowHint
                                   | Qt.Popup)
        self.dialog.setFixedSize(480, 240)
        self.dialog.setLayout(QHBoxLayout())
        self.calender = QCalendarWidget(self)
        self.dialog.layout().addWidget(self.calender)
        self.dialog.layout().setContentsMargins(0, 0, 0, 0)
        self.dialog.layout().setSpacing(0)

        self.button.clicked.connect(self, SLOT("showCalender()"))

        self.calender.selectionChanged.connect(self.__emitSelectionChanged__)

    @Slot()
    def showCalender(self):
        print('in show')

        p = self.mapToGlobal(QPoint(0, self.height() + self.__margin__))

        self.dialog.setGeometry(p.x(), p.y(), 0, 0)
        self.dialog.show()

    def setIcon(self, icon):
        if type(icon) is QIcon:
            self.button.setIcon(icon)
        elif type(icon) is str:
            self.button.setIcon(QIcon(icon))
        else:
            raise Exception(
                'Wrong argument type, icon should be either PySide2.QtGui.QIcon or str "string"'
            )

    def icon(self):
        return self.button.icon()

    def setIconSize(self, iconsize):
        if type(iconsize) is QSize:
            self.button.setIconSize(iconsize)
        elif type(iconsize) is int:
            self.button.setIcon(QSize(iconsize, iconsize))
        elif type(type) is iter:
            import collections
            if isinstance(iconsize, collections.Iterable):
                if len(iconsize) == 1:
                    self.setIconSize(iconsize[0])
                elif len(iconsize) == 2:
                    self.setIconSize(QSize(iconsize[0], iconsize[1]))
                else:
                    raise Exception()
        else:
            raise Exception(
                "Wrong argument type, iconSize should be either PySide2.QtCore.QSize or int value or width and height "
                "or iterable contains one QSize, one int or two int values for width and height respectively"
            )

    def iconSize(self):
        return self.button.iconSize()

    def setFirstDayOfWeek(self, dayOfWeek):
        if type(dayOfWeek) is Qt.DayOfWeek:
            self.calender.setFirstDayOfWeek(dayOfWeek)
        elif type(dayOfWeek) is int:
            if dayOfWeek < 1 or dayOfWeek > 7:
                raise Exception(
                    "Wrong argument, dayOfWeek should be from 1 to 7 (Monday --> Sunday)"
                )
            self.calender.setFirstDayOfWeek(Qt.DayOfWeek(dayOfWeek))
        else:
            raise Exception(
                "Wrong type, dayOfWeek should be either PySide2.QtCore.Qt.DayOf or int (1 --> 7) (Monday --> Sunday)"
            )

    def firstDayOfWeek(self):
        self.calender.firstDayOfWeek()

    def selectedDate(self):

        self.calender.selectedDate()

    def setSelectedDate(self, args, kwargs):
        self.calender.setSelectedDate(args, kwargs)

    def minimumDate(self):
        self.calender.minimumDate()

    def setMinimumDate(self):
        self.calender.setMinimumDate()

    def selectedDate(self):

        return self.calender.selectedDate()

    def __emitSelectionChanged__(self):
        self.selectionChanged.emit()
Exemplo n.º 10
0
    def getRundown(self, silent=False):
        rtext = ""
        self.rundownCount = 0
        for _condi, _pkdf in self.pk_extracted_by_condi.items():

            _Np = len(_pkdf.index)
            _NROI = len(_pkdf.columns)
            ten_percent = int(_Np / 10)
            rtext += "{} condition, 10% of peaks count is {} peaks\n".format(
                _condi, ten_percent)
            # look at first 5 peaks
            _firsttenpc = _pkdf.iloc[0:ten_percent].describe().loc["mean"]
            # look at last 5 peaks
            _lasttenpc = _pkdf.iloc[-1 - ten_percent:-1].describe().loc["mean"]

            _tdf = self.tracedata[_condi]
            _max = _tdf.max()
            _SD = _tdf.std()

            _bestSNR = _max / _SD
            _startSNR = _firsttenpc / _SD
            _endSNR = _lasttenpc / _SD
            #print ("ff, lf : {} {}".format(_firstfive, _lastfive))

            _rundownRatio = _lasttenpc.div(_firsttenpc).sort_values()
            self.rundownCount += _rundownRatio[
                _rundownRatio < self.rundownThreshold].count()

            _rd_SNR = pd.concat([_rundownRatio, _bestSNR, _startSNR, _endSNR],
                                axis=1)
            _rd_SNR.columns = [
                'Rundown', 'Best SNR', 'Initial SNR', 'Final SNR'
            ]

            rtext += "Rundown (amplitude ratio: last 10% / first 10%) and signal to noise ratio (start, end)\nfor {} ROIs (ROIs with worst rundown first):\n{}\n\n".format(
                _NROI,
                _rd_SNR.round(2).to_string())

        rtext += "Total number of traces with rundown worse than threshold ({}): {}\n".format(
            self.rundownThreshold, self.rundownCount)

        print(rtext)

        if not silent:
            ###Make a pop up window of these results
            qmb = QDialog()
            qmb.setWindowTitle('Rundown {}'.format(self.name))
            qmb.setGeometry(800, 600, 600, 600)
            self.rundownText = QtGui.QTextEdit()
            font = QtGui.QFont()
            font.setFamily('Courier')
            font.setFixedPitch(True)
            font.setPointSize(12)
            self.rundownText.setCurrentFont(font)
            self.rundownText.setText(rtext)
            self.rundownText.setReadOnly(True)

            #add buttons, make it the right size
            qmb.layout = QVBoxLayout()
            qmb.layout.addWidget(self.rundownText)
            qmb.setLayout(qmb.layout)
            qmb.exec_()
Exemplo n.º 11
0
class MainWindow(Ui_MainWindow, QMainWindow):
    def __init__(self, instrument: Instrument, nx_classes: Dict):
        super().__init__()
        self.instrument = instrument
        self.nx_classes = nx_classes

    def setupUi(self, main_window):
        super().setupUi(main_window)

        self.export_to_nexus_file_action.triggered.connect(
            self.save_to_nexus_file)
        self.open_nexus_file_action.triggered.connect(self.open_nexus_file)
        self.open_json_file_action.triggered.connect(self.open_json_file)
        self.open_idf_file_action.triggered.connect(self.open_idf_file)
        self.export_to_filewriter_JSON_action.triggered.connect(
            self.save_to_filewriter_json)
        self.export_to_forwarder_JSON_action.triggered.connect(
            self.save_to_forwarder_json)

        # Clear the 3d view when closed
        QApplication.instance().aboutToQuit.connect(self.sceneWidget.delete)

        self.widget = silx.gui.hdf5.Hdf5TreeView()
        self.widget.setAcceptDrops(True)
        self.widget.setDragEnabled(True)
        self.treemodel = self.widget.findHdf5TreeModel()
        self.treemodel.setDatasetDragEnabled(True)
        self.treemodel.setFileDropEnabled(True)
        self.treemodel.setFileMoveEnabled(True)
        self.treemodel.insertH5pyObject(self.instrument.nexus.nexus_file)
        self.instrument.nexus.file_changed.connect(
            self.update_nexus_file_structure_view)
        self.silx_tab_layout.addWidget(self.widget)
        self.instrument.nexus.show_entries_dialog.connect(
            self.show_entries_dialog)

        self.instrument.nexus.component_added.connect(
            self.sceneWidget.add_component)
        self.instrument.nexus.component_removed.connect(
            self.sceneWidget.delete_component)
        self.component_tree_view_tab.set_up_model(self.instrument)
        self.instrument.nexus.transformation_changed.connect(
            self._update_transformations_3d_view)

        self.widget.setVisible(True)

        self._set_up_file_writer_control_window(main_window)
        self.file_writer_control_window = None

    def _set_up_file_writer_control_window(self, main_window):
        try:
            import confluent_kafka  # noqa: F401

            self.control_file_writer_action = QAction(main_window)
            self.control_file_writer_action.setText("Control file-writer")
            self.file_menu.addAction(self.control_file_writer_action)
            self.control_file_writer_action.triggered.connect(
                self.show_control_file_writer_window)
        except ImportError:
            pass

    def show_control_file_writer_window(self):
        if self.file_writer_control_window is None:
            from nexus_constructor.file_writer_ctrl_window import FileWriterCtrl

            self.file_writer_ctrl_window = FileWriterCtrl(
                self.instrument, QSettings("ess", "nexus-constructor"))
            self.file_writer_ctrl_window.show()

    def show_edit_component_dialog(self):
        selected_component = self.component_tree_view_tab.component_tree_view.selectedIndexes(
        )[0].internalPointer()
        self.show_add_component_window(selected_component)

    def show_entries_dialog(self, map_of_entries: dict, nexus_file: h5py.File):
        """
        Shows the entries dialog when loading a nexus file if there are multiple entries.
        :param map_of_entries: A map of the entry groups, with the key being the name of the group and value being the actual h5py group object.
        :param nexus_file: A reference to the nexus file.
        """
        self.entries_dialog = QDialog()
        self.entries_dialog.setMinimumWidth(400)
        self.entries_dialog.setWindowTitle(
            "Multiple Entries found. Please choose the entry name from the list."
        )
        combo = QComboBox()

        # Populate the combo box with the names of the entry groups.
        [combo.addItem(x) for x in map_of_entries.keys()]
        ok_button = QPushButton()

        ok_button.setText("OK")
        ok_button.clicked.connect(self.entries_dialog.close)

        def _load_current_entry():
            self.instrument.nexus.load_file(
                map_of_entries[combo.currentText()], nexus_file)
            self._update_views()

        # Connect the clicked signal of the ok_button to instrument.load_file and pass the file and entry group object.
        ok_button.clicked.connect(_load_current_entry)

        self.entries_dialog.setLayout(QGridLayout())

        self.entries_dialog.layout().addWidget(QLabel("Entry:"))
        self.entries_dialog.layout().addWidget(combo)
        self.entries_dialog.layout().addWidget(ok_button)
        self.entries_dialog.show()

    def update_nexus_file_structure_view(self, nexus_file):
        self.treemodel.clear()
        self.treemodel.insertH5pyObject(nexus_file)

    def save_to_nexus_file(self):
        filename = file_dialog(True, "Save Nexus File", NEXUS_FILE_TYPES)
        self.instrument.nexus.save_file(filename)

    def open_idf_file(self):
        filename = file_dialog(False, "Open IDF file", {"IDF files": ["xml"]})
        self._load_idf(filename)

    def _load_idf(self, filename):
        try:
            builder = NexusBuilder(
                str(uuid.uuid4()),
                idf_file=filename,
                file_in_memory=True,
                nx_entry_name="entry",
            )
            builder.add_instrument_geometry_from_idf()
            self.instrument.nexus.load_nexus_file(builder.target_file)
            self._update_views()
            QMessageBox.warning(
                self,
                "Mantid IDF loaded",
                "Please manually check the instrument for accuracy.",
            )
        except Exception:
            QMessageBox.critical(self, "IDF Error",
                                 "Error whilst loading IDF file")

    def save_to_filewriter_json(self):
        filename = file_dialog(True, "Save Filewriter JSON File",
                               JSON_FILE_TYPES)
        if filename:
            with open(filename, "w") as file:
                filewriter_json_writer.write_nexus_structure_to_json(
                    self.instrument, file)

    def save_to_forwarder_json(self):
        filename = file_dialog(True, "Save Forwarder JSON File",
                               JSON_FILE_TYPES)
        if filename:
            provider_type, ok_pressed = QInputDialog.getItem(
                None,
                "Provider type",
                "Select provider type for PVs",
                ["ca", "pva"],
                0,
                False,
            )
            default_broker, ok_pressed = QInputDialog.getText(
                None,
                "Default broker",
                "Default Broker: (This will only be used for streams that do not already have a broker)",
                text="broker:port",
                echo=QLineEdit.Normal,
            )
            if ok_pressed:
                with open(filename, "w") as file:
                    nexus_constructor.json.forwarder_json_writer.generate_forwarder_command(
                        file,
                        self.instrument.nexus.entry,
                        provider_type=provider_type,
                        default_broker=default_broker,
                    )

    def open_nexus_file(self):
        filename = file_dialog(False, "Open Nexus File", NEXUS_FILE_TYPES)
        existing_file = self.instrument.nexus.nexus_file
        if self.instrument.nexus.open_file(filename):
            self._update_views()
            existing_file.close()

    def open_json_file(self):
        filename = file_dialog(False, "Open File Writer JSON File",
                               JSON_FILE_TYPES)
        if filename:
            with open(filename, "r") as json_file:
                json_data = json_file.read()

                try:
                    nexus_file = json_to_nexus(json_data)
                except Exception as exception:
                    show_warning_dialog(
                        "Provided file not recognised as valid JSON",
                        "Invalid JSON",
                        f"{exception}",
                        parent=self,
                    )
                    return

                existing_file = self.instrument.nexus.nexus_file
                if self.instrument.nexus.load_nexus_file(nexus_file):
                    self._update_views()
                    existing_file.close()

    def _update_transformations_3d_view(self):
        self.sceneWidget.clear_all_transformations()
        for component in self.instrument.get_component_list():
            if component.name != "sample":
                self.sceneWidget.add_transformation(component.name,
                                                    component.transform)

    def _update_views(self):
        self.sceneWidget.clear_all_transformations()
        self.sceneWidget.clear_all_components()
        self.component_tree_view_tab.set_up_model(self.instrument)
        self._update_3d_view_with_component_shapes()

    def _update_3d_view_with_component_shapes(self):
        for component in self.instrument.get_component_list():
            shape, positions = component.shape
            self.sceneWidget.add_component(component.name, shape, positions)
            self.sceneWidget.add_transformation(component.name,
                                                component.transform)

    def show_add_component_window(self, component: Component = None):
        self.add_component_window = QDialog()
        self.add_component_window.ui = AddComponentDialog(
            self.instrument,
            self.component_tree_view_tab.component_model,
            component,
            nx_classes=self.nx_classes,
            parent=self,
        )
        self.add_component_window.ui.setupUi(self.add_component_window)
        self.add_component_window.show()
Exemplo n.º 12
0
from hwi_qt.except_hook import except_hook
from hwi_qt.logging import log
from hwi_qt.selectable_text import SelectableText
from hwi_qt.sync_button import SyncButton

if __name__ == '__main__':
    devices = commands.enumerate()
    print(devices)

    sys.excepthook = except_hook

    log.info('Starting hwi-qt')
    app = QApplication(sys.argv)

    dialog = QDialog()
    dialog.layout = QGridLayout()

    for device in devices:
        name = device['type'] + '-' + device['fingerprint']
        text = SelectableText(name)
        dialog.layout.addWidget(text, 0, 0)

        button = SyncButton('Sync', 'Syncing...')
        dialog.layout.addLayout(button, 0, 1)

    dialog.setLayout(dialog.layout)

    dialog.show()

    sys.exit(app.exec_())