diff --git a/Jenkinsfile b/Jenkinsfile index 6f3588834..280433cf7 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -17,9 +17,10 @@ properties([ ]) container_build_nodes = [ - 'centos7': ContainerBuildNode.getDefaultContainerBuildNode('centos7') + 'centos7': ContainerBuildNode.getDefaultContainerBuildNode('centos7-gcc8') ] + pipeline_builder = new PipelineBuilder(this, container_build_nodes) builders = pipeline_builder.createBuilders { container -> diff --git a/nexus_constructor/main_window.py b/nexus_constructor/main_window.py index 0d2151c44..975a39d03 100644 --- a/nexus_constructor/main_window.py +++ b/nexus_constructor/main_window.py @@ -184,7 +184,7 @@ def _update_3d_view_with_component_shapes(self): self.sceneWidget.add_transformation(component.name, component.qtransform) def show_add_component_window(self, component: Component = None): - self.add_component_window = QDialog() + self.add_component_window = QDialogCustom() self.add_component_window.ui = AddComponentDialog( self.model, self.component_tree_view_tab.component_model, @@ -194,3 +194,43 @@ def show_add_component_window(self, component: Component = None): ) self.add_component_window.ui.setupUi(self.add_component_window) self.add_component_window.show() + + +class QDialogCustom(QDialog): + """ + Custom QDialog class that enables the possibility to properly produce + a message box in the component editor to the users, + asking if they are sure to quit editing component when exiting. + """ + + def __init__(self): + super().__init__() + self._is_accepting_component = True + + def disable_msg_box(self): + self._is_accepting_component = False + + def close_without_msg_box(self): + """ + Close widget without producing the message box in closeEvent method. + """ + self.disable_msg_box() + self.close() + + def closeEvent(self, event): + """ + Overriding closeEvent function in the superclass to produce a message box prompting + the user to exit the add/edit component window. This message box pops up + when the user exits by pressing the window close (X) button. + """ + if not self._is_accepting_component: + event.accept() + return + quit_msg = "Are you sure you want to exit the component editor?" + reply = QMessageBox.question( + self, "Message", quit_msg, QMessageBox.Yes, QMessageBox.No + ) + if reply == QMessageBox.Yes: + event.accept() + else: + event.ignore() diff --git a/tests/conftest.py b/tests/conftest.py index 1529791aa..7cd0a7081 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,8 +1,8 @@ from unittest.mock import Mock import pytest -from PySide2.QtWidgets import QDialog +from nexus_constructor.main_window import QDialogCustom as QDialog from nexus_constructor.model.instrument import Instrument from nexus_constructor.model.model import Model from nexus_constructor.pixel_options import PixelOptions @@ -12,7 +12,9 @@ @pytest.fixture(scope="function") def template(qtbot) -> QDialog: - return QDialog() + q_dialog = QDialog() + q_dialog.disable_msg_box() + return q_dialog @pytest.fixture(scope="function") diff --git a/tests/ui_tests/test_ui_add_component_window.py b/tests/ui_tests/test_ui_add_component_window.py index 20c7a2227..5013c0b24 100644 --- a/tests/ui_tests/test_ui_add_component_window.py +++ b/tests/ui_tests/test_ui_add_component_window.py @@ -8,7 +8,7 @@ from mock import Mock, call, mock_open, patch from PySide2.QtCore import Qt from PySide2.QtGui import QVector3D -from PySide2.QtWidgets import QDialog, QMainWindow, QRadioButton +from PySide2.QtWidgets import QMainWindow, QRadioButton from pytestqt.qtbot import QtBot from nexus_constructor import component_type @@ -19,6 +19,7 @@ from nexus_constructor.geometry.pixel_data_utils import PIXEL_FIELDS from nexus_constructor.instrument_view.instrument_view import InstrumentView from nexus_constructor.main_window import MainWindow +from nexus_constructor.main_window import QDialogCustom as QDialog from nexus_constructor.model.component import Component from nexus_constructor.model.entry import Entry from nexus_constructor.model.geometry import ( @@ -86,7 +87,7 @@ else: NO_PIXEL_OPTIONS[component_class] = i -# Select a subset of the component class to use in parameterised tests +# Select a subset of the component class to use in parameterised tests. # Should include any for which the UI is specialised _components_subset = {"NXdetector", "NXdisk_chopper", "NXsensor"} COMPONENT_TYPES_SUBSET = { @@ -193,7 +194,7 @@ def mock_component(): def enter_component_name( qtbot: pytestqt.qtbot.QtBot, - template: PySide2.QtWidgets.QDialog, + template: QDialog, dialog: AddComponentDialog, component_name: str, ): @@ -239,7 +240,7 @@ def get_shape_type_button(dialog: AddComponentDialog, button_name: str): def make_pixel_options_disappear( qtbot: pytestqt.qtbot.QtBot, dialog: AddComponentDialog, - template: PySide2.QtWidgets.QDialog, + template: QDialog, component_index: int, ): """ @@ -258,7 +259,7 @@ def make_pixel_options_appear( qtbot: pytestqt.qtbot.QtBot, button: QRadioButton, dialog: AddComponentDialog, - template: PySide2.QtWidgets.QDialog, + template: QDialog, pixel_options_index: int = PIXEL_OPTIONS["NXdetector"], ): """ @@ -294,7 +295,7 @@ def enter_units(qtbot: pytestqt.qtbot.QtBot, dialog: AddComponentDialog, units: def enter_file_path( qtbot: pytestqt.qtbot.QtBot, dialog: AddComponentDialog, - template: PySide2.QtWidgets.QDialog, + template: QDialog, file_path: str, file_contents: str, ): @@ -317,7 +318,7 @@ def enter_file_path( def enter_disk_chopper_fields( qtbot: pytestqt.qtbot.QtBot, dialog: AddComponentDialog, - template: PySide2.QtWidgets.QDialog, + template: QDialog, component_name: str = "ThisIsADiskChopper", ): """ diff --git a/ui/add_component.py b/ui/add_component.py index 9941ec14e..d9947e981 100644 --- a/ui/add_component.py +++ b/ui/add_component.py @@ -230,7 +230,9 @@ def setupUi(self, AddComponentDialog): self.retranslateUi(AddComponentDialog) QtCore.QObject.connect( - self.ok_button, QtCore.SIGNAL("clicked()"), AddComponentDialog.close + self.ok_button, + QtCore.SIGNAL("clicked()"), + AddComponentDialog.close_without_msg_box, ) QtCore.QMetaObject.connectSlotsByName(AddComponentDialog)