def test_UI_GIVEN_valid_command_WHEN_sending_command_THEN_command_producer_sends_command( qtbot, instrument): window = FileWriterCtrl(instrument) qtbot.addWidget(window) window.command_producer = Mock() broker = "broker1:9092/topic1" service_id = "12345678" window.command_widget.broker_line_edit.setText(broker) window.command_widget.start_time_enabled.setChecked(False) window.command_widget.stop_time_enabled.setChecked(False) window.command_widget.service_id_lineedit.setText(service_id) window.send_command() window.command_producer.send_command.assert_called_once() sent_msg = window.command_producer.send_command.call_args_list[0][0][0] res = json.loads(sent_msg) assert res["cmd"] == "FileWriter_new" assert res["nexus_structure"] assert res["nexus_structure"]["children"] assert res["broker"] == broker assert res["service_id"] == service_id assert not window.command_widget.ok_button.isEnabled()
def test_UI_GIVEN_valid_command_WHEN_sending_command_THEN_command_producer_sends_command( qtbot, instrument, settings ): window = FileWriterCtrl(instrument, settings) qtbot.addWidget(window) window.command_producer = Mock() broker = "broker1:9092/topic1" service_id = "12345678" window.command_widget.broker_line_edit.setText(broker) window.command_widget.start_time_enabled.setChecked(False) window.command_widget.stop_time_enabled.setChecked(False) window.command_widget.service_id_lineedit.setText(service_id) window.send_command() window.command_producer.send_command.assert_called_once() sent_msg = window.command_producer.send_command.call_args_list[0][0][0] res = run_start_pl72.deserialise_pl72(sent_msg) assert res.nexus_structure assert "children" in res.nexus_structure assert res.broker == broker assert res.service_id == service_id assert not window.command_widget.ok_button.isEnabled()
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 test_UI_GIVEN_time_string_WHEN_setting_time_THEN_last_time_is_stored( test_input, qtbot): model = QStandardItemModel() qtbot.addWidget(model) current_time = "12345678" new_time = "23456789" FileWriterCtrl._set_time(model, test_input, current_time, new_time) assert test_input.last_time == current_time
def test_UI_GIVEN_no_files_WHEN_stop_file_writing_is_clicked_THEN_button_is_disabled( qtbot, instrument): window = FileWriterCtrl(instrument) qtbot.addWidget(window) window.files_list.selectedIndexes = lambda: [] window.file_list_clicked() assert not window.stop_file_writing_button.isEnabled()
def test_UI_GIVEN_invalid_broker_WHEN_command_broker_timer_callback_is_called_THEN_nothing_happens( qtbot, instrument): window = FileWriterCtrl(instrument) qtbot.addWidget(window) window.command_producer = None window.command_broker_edit.setText("invalid") window.command_broker_timer_changed(DummyInterface) assert window.command_producer is None
def test_UI_GIVEN_valid_broker_WHEN_status_broker_timer_callback_is_called_THEN_consumer_is_created( qtbot, instrument): window = FileWriterCtrl(instrument) qtbot.addWidget(window) window.command_broker_change_timer.stop() window.status_broker_change_timer.stop() window.status_consumer = 1 # anything that's not None window.status_broker_edit.setText("valid:9092/topic1") window.status_broker_timer_changed(DummyInterface) assert isinstance(window.status_consumer, DummyInterface)
def test_UI_GIVEN_files_WHEN_stop_file_writing_is_clicked_THEN_button_is_enabled( qtbot, instrument): window = FileWriterCtrl(instrument) qtbot.addWidget(window) window.files_list.selectedIndexes = lambda: [ 1, 2, 3, ] # Can be any list so doesn't matter what's in here window.file_list_clicked() assert window.stop_file_writing_button.isEnabled()
def test_UI_stored_settings_are_shown_in_window(qtbot, instrument, settings): command_broker = "broker:9092/topic2" status_broker = "broker2:9092/topic3" file_broker = "broker3:9092/topic4" use_start_time = True use_stop_time = False filename = "test2.nxs" settings.setValue(FileWriterSettings.STATUS_BROKER_ADDR, status_broker) settings.setValue(FileWriterSettings.COMMAND_BROKER_ADDR, command_broker) settings.setValue(FileWriterSettings.FILE_NAME, filename) settings.setValue(FileWriterSettings.USE_START_TIME, use_start_time) settings.setValue(FileWriterSettings.USE_STOP_TIME, use_stop_time) settings.setValue(FileWriterSettings.FILE_BROKER_ADDR, file_broker) # _restore_settings should be called on construction window = FileWriterCtrl(instrument, settings) qtbot.addWidget(window) assert window.status_broker_edit.text() == status_broker assert window.command_broker_edit.text() == command_broker assert use_start_time == window.command_widget.start_time_enabled.isChecked() assert use_stop_time == window.command_widget.stop_time_enabled.isChecked() assert filename == window.command_widget.nexus_file_name_edit.text() assert file_broker == window.command_widget.broker_line_edit.text()
def test_UI_GIVEN_nothing_WHEN_creating_filewriter_control_window_THEN_broker_validators_are_set_correctly( qtbot, instrument, settings ): window = FileWriterCtrl(instrument, settings) qtbot.addWidget(window) assert isinstance(window.status_broker_edit.validator(), BrokerAndTopicValidator) assert isinstance(window.command_broker_edit.validator(), BrokerAndTopicValidator) assert ( window.command_broker_edit.validator() != window.status_broker_edit.validator() ) # make sure they are different objects so that both edits are validated independently from each other.
def test_UI_GIVEN_nothing_WHEN_creating_filewriter_control_window_THEN_broker_field_defaults_are_set_correctly( qtbot, instrument): window = FileWriterCtrl(instrument) qtbot.addWidget(window) assert not window.command_broker_edit.text() assert window.command_broker_led.is_off() assert not window.command_broker_change_timer.isActive() assert not window.status_broker_edit.text() assert window.status_broker_led.is_off() assert not window.status_broker_change_timer.isActive()
def test_UI_settings_are_saved_when_store_settings_is_called( qtbot, instrument, settings ): window = FileWriterCtrl(instrument, settings) qtbot.addWidget(window) command_broker = "broker:9092/topic1" window.command_broker_edit.setText(command_broker) status_broker = "broker2:9092/topic2" window.status_broker_edit.setText(status_broker) file_broker = "broker3:9092/topic3" window.command_widget.broker_line_edit.setText(file_broker) use_start_time = True window.command_widget.start_time_enabled.setChecked(use_start_time) use_stop_time = True window.command_widget.stop_time_enabled.setChecked(use_stop_time) filename = "test.nxs" window.command_widget.nexus_file_name_edit.setText(filename) window._store_settings() assert settings.value(FileWriterSettings.COMMAND_BROKER_ADDR) == command_broker assert settings.value(FileWriterSettings.STATUS_BROKER_ADDR) == status_broker assert settings.value(FileWriterSettings.FILE_BROKER_ADDR) == file_broker assert ( extract_bool_from_qsettings(settings.value(FileWriterSettings.USE_START_TIME)) == use_start_time ) assert ( extract_bool_from_qsettings(settings.value(FileWriterSettings.USE_STOP_TIME)) == use_stop_time ) assert settings.value(FileWriterSettings.FILE_NAME) == filename
def test_UI_GIVEN_command_producer_WHEN_checking_connection_status_THEN_command_led_is_turned_on( qtbot, instrument): window = FileWriterCtrl(instrument) qtbot.addWidget(window) window.command_producer = Mock() window.status_consumer = None window.command_producer.connected = True window._check_connection_status() assert window.command_broker_led.is_on()
def test_UI_GIVEN_no_status_consumer_and_no_command_producer_WHEN_checking_status_connection_THEN_both_leds_are_turned_off( qtbot, instrument): window = FileWriterCtrl(instrument) qtbot.addWidget(window) window.status_consumer = None window.command_producer = None window._check_connection_status() assert window.status_broker_led.is_off() assert window.command_broker_led.is_off()
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) self.file_writer_ctrl_window.show()
def test_UI_disable_stop_button_when_no_files_are_selected(qtbot, instrument, settings): window = FileWriterCtrl(instrument, settings) qtbot.addWidget(window) assert not window.files_list.selectedIndexes() assert not window.stop_file_writing_button.isEnabled()
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()