From 26d365925004838017fdd5c12052faafcbc6e96a Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Fri, 4 Feb 2022 22:06:06 +0000 Subject: [PATCH] Prevent the user from closing the display window --- openlp/core/display/window.py | 9 ++++++ openlp/core/ui/mainwindow.py | 4 +-- openlp/core/ui/slidecontroller.py | 20 ++++++++----- tests/openlp_core/display/test_window.py | 31 ++++++++++++++++++++ tests/openlp_core/ui/test_slidecontroller.py | 19 ++++++++++++ 5 files changed, 73 insertions(+), 10 deletions(-) diff --git a/openlp/core/display/window.py b/openlp/core/display/window.py index 9db2ec433..3de5fff84 100644 --- a/openlp/core/display/window.py +++ b/openlp/core/display/window.py @@ -89,6 +89,7 @@ class DisplayWindow(QtWidgets.QWidget, RegistryProperties, LogMixin): # Need to import this inline to get around a QtWebEngine issue from openlp.core.display.webengine import WebEngineView self._is_initialised = False + self._is_manual_close = False self._can_show_startup_screen = can_show_startup_screen self._fbo = None self.setWindowTitle(translate('OpenLP.DisplayWindow', 'Display Window')) @@ -130,6 +131,13 @@ class DisplayWindow(QtWidgets.QWidget, RegistryProperties, LogMixin): if len(ScreenList()) > 1 or self.settings.value('core/display on monitor'): self.show() + def closeEvent(self, event): + """ + Override the closeEvent method to prevent the window from being closed by the user + """ + if not self._is_manual_close: + event.ignore() + def _fix_font_name(self, font_name): """ Do some font machinations to see if we can fix the font name @@ -150,6 +158,7 @@ class DisplayWindow(QtWidgets.QWidget, RegistryProperties, LogMixin): if self.is_display: Registry().remove_function('live_display_hide', self.hide_display) Registry().remove_function('live_display_show', self.show_display) + self._is_manual_close = True @property def is_initialised(self): diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 011bbfbcf..7c53e2f4c 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -1096,9 +1096,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, LogMixin, RegistryPropert if self.new_data_path: self.change_data_directory() # Close down the display - if self.live_controller.display: - self.live_controller.display.close() - # self.live_controller.display = None + self.live_controller.close_displays() # Clean temporary files used by services self.service_manager_contents.clean_up() if is_win(): diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 3d5ea5a50..3d300827e 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -174,13 +174,8 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties): """ if not self.is_live: return - if self.displays: - # Delete any existing displays - for display in self.displays: - display.deregister_display() - display.setParent(None) - del display - self.displays = [] + # Delete any existing displays + self.close_displays() for screen in self.screens: if screen.is_display: display = DisplayWindow(self, screen) @@ -189,6 +184,17 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties): if self.display: self.__add_actions_to_widget(self.display) + def close_displays(self): + """ + Close all open displays + """ + for display in self.displays: + display.deregister_display() + display.setParent(None) + display.close() + del display + self.displays = [] + @property def display(self): return self.displays[0] if self.displays else None diff --git a/tests/openlp_core/display/test_window.py b/tests/openlp_core/display/test_window.py index 301c34d15..97fd938a5 100644 --- a/tests/openlp_core/display/test_window.py +++ b/tests/openlp_core/display/test_window.py @@ -666,3 +666,34 @@ def test_display_watcher_please_repaint(display_window_env, mock_settings): # THEN: Qt update for the webview should have been triggered assert display_window.webview.update.call_count == 1 + + +def test_close_event_ignores_event(display_window_env, mock_settings): + """ + Test that when the window receives a close event, it ignores it + """ + # GIVEN: A DisplayWindow instance and a mocked event + display_window = DisplayWindow() + mocked_event = MagicMock() + + # WHEN: The closeEvent() method is called + display_window.closeEvent(mocked_event) + + # THEN: The event should have been ignored + mocked_event.ignore.assert_called_once() + + +def test_close_event_accepts_event_manual_close(display_window_env, mock_settings): + """ + Test that when the window receives a close event due to manually being closed, it accepts it + """ + # GIVEN: A DisplayWindow instance and a mocked event + display_window = DisplayWindow() + mocked_event = MagicMock() + + # WHEN: The closeEvent() method is called + display_window._is_manual_close = True + display_window.closeEvent(mocked_event) + + # THEN: The event should have been ignored + assert mocked_event.ignore.called is False diff --git a/tests/openlp_core/ui/test_slidecontroller.py b/tests/openlp_core/ui/test_slidecontroller.py index 01206e1c1..61ecaf210 100644 --- a/tests/openlp_core/ui/test_slidecontroller.py +++ b/tests/openlp_core/ui/test_slidecontroller.py @@ -1552,3 +1552,22 @@ def test_initial_preview_controller(registry): # WHEN: the default controller is built. # THEN: The controller should not be a live controller. assert preview_controller.is_live is False, 'The slide controller should be a Preview controller' + + +def test_close_displays(registry): + """ + Test that closing the displays calls the correct methods + """ + # GIVEN: A Live controller and a mocked display + mocked_display = MagicMock() + live_controller = LiveController(None) + live_controller.displays = [mocked_display] + + # WHEN: close_displays() is called + live_controller.close_displays() + + # THEN: The display is closed + mocked_display.deregister_display.assert_called_once() + mocked_display.setParent.assert_called_once_with(None) + mocked_display.close.assert_called_once() + assert live_controller.displays == []