diff --git a/openlp/core/common/settings.py b/openlp/core/common/settings.py index 0539f2de6..a3804c1c0 100644 --- a/openlp/core/common/settings.py +++ b/openlp/core/common/settings.py @@ -291,6 +291,7 @@ class Settings(QtCore.QSettings): 'presentations/thumbnail_scheme': '', 'presentations/powerpoint slide click advance': QtCore.Qt.Unchecked, 'presentations/powerpoint control window': QtCore.Qt.Unchecked, + 'presentations/impress use display setting': QtCore.Qt.Unchecked, 'presentations/last directory': None, 'servicemanager/last directory': None, 'servicemanager/last file': None, diff --git a/openlp/plugins/presentations/lib/impresscontroller.py b/openlp/plugins/presentations/lib/impresscontroller.py index be8b53b6d..8dc84969d 100644 --- a/openlp/plugins/presentations/lib/impresscontroller.py +++ b/openlp/plugins/presentations/lib/impresscontroller.py @@ -37,6 +37,7 @@ from PyQt5 import QtCore from openlp.core.common import delete_file, get_uno_command, get_uno_instance, is_win, trace_error_handler from openlp.core.common.registry import Registry +from openlp.core.common.settings import Settings from openlp.core.display.screens import ScreenList from openlp.plugins.presentations.lib.presentationcontroller import PresentationController, PresentationDocument, \ TextType @@ -312,7 +313,17 @@ class ImpressDocument(PresentationDocument): log.warning('Presentation {url} could not be loaded'.format(url=url)) return False self.presentation = self.document.getPresentation() - self.presentation.Display = ScreenList().current.number + 1 + # OpenOffice uses a screen numbering scheme where the primary display is 1 and the external monitor 2 + # but OpenLP sets screen numbers based on screen coordinates (geometry) + # so we work out what OpenOffice display to use based on which of the openlp screens is primary + # unless the user has defined in Settings to use the impress Slide Show setting for presentation display + if not Settings().value('presentations/impress use display setting'): + public_display_screen_number = ScreenList().current.number + screens = list(ScreenList()) + if screens[public_display_screen_number].is_primary: + self.presentation.Display = 1 + else: + self.presentation.Display = 2 self.control = None self.create_thumbnails() self.create_titles_and_notes() diff --git a/openlp/plugins/presentations/lib/presentationtab.py b/openlp/plugins/presentations/lib/presentationtab.py index 5aa186688..5856d7b8b 100644 --- a/openlp/plugins/presentations/lib/presentationtab.py +++ b/openlp/plugins/presentations/lib/presentationtab.py @@ -76,6 +76,15 @@ class PresentationTab(SettingsTab): self.ppt_window_check_box.setObjectName('ppt_window_check_box') self.powerpoint_layout.addWidget(self.ppt_window_check_box) self.left_layout.addWidget(self.powerpoint_group_box) + # Impress + self.impress_group_box = QtWidgets.QGroupBox(self.left_column) + self.impress_group_box.setObjectName('impress_group_box') + self.impress_layout = QtWidgets.QVBoxLayout(self.impress_group_box) + self.impress_layout.setObjectName('impress_layout') + self.odp_display_check_box = QtWidgets.QCheckBox(self.impress_group_box) + self.odp_display_check_box.setObjectName('odp_display_check_box') + self.impress_layout.addWidget(self.odp_display_check_box) + self.left_layout.addWidget(self.impress_group_box) # setup layout self.left_layout.addStretch() self.right_column.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred) @@ -101,6 +110,10 @@ class PresentationTab(SettingsTab): translate('PresentationPlugin.PresentationTab', 'Let PowerPoint control the size and monitor of the presentations\n' '(This may fix PowerPoint scaling issues in Windows 8 and 10)')) + self.impress_group_box.setTitle(translate('PresentationPlugin.PresentationTab', 'Impress options')) + self.odp_display_check_box.setText( + translate('PresentationPlugin.PresentationTab', + 'Use Impress Slide Show Settings / Presentation Display setting')) def set_controller_text(self, checkbox, controller): if checkbox.isEnabled(): @@ -114,18 +127,24 @@ class PresentationTab(SettingsTab): Load the settings. """ powerpoint_available = False + impress_available = False for key in self.controllers: controller = self.controllers[key] checkbox = self.presenter_check_boxes[controller.name] checkbox.setChecked(self.settings.value('presentations/' + controller.name)) if controller.name == 'Powerpoint' and controller.is_available(): powerpoint_available = True + if controller.name == 'Impress' and controller.is_available(): + impress_available = True self.override_app_check_box.setChecked(self.settings.value('presentations/override app')) # Load PowerPoint settings self.ppt_slide_click_check_box.setChecked(self.settings.value('presentations/powerpoint slide click advance')) self.ppt_slide_click_check_box.setEnabled(powerpoint_available) self.ppt_window_check_box.setChecked(self.settings.value('presentations/powerpoint control window')) self.ppt_window_check_box.setEnabled(powerpoint_available) + # Load Impress settings + self.odp_display_check_box.setChecked(self.settings.value('presentations/impress use display setting')) + self.odp_display_check_box.setEnabled(impress_available) def save(self): """ @@ -160,6 +179,11 @@ class PresentationTab(SettingsTab): if self.settings.value(setting_key) != self.ppt_window_check_box.checkState(): self.settings.setValue(setting_key, self.ppt_window_check_box.checkState()) changed = True + # Save impress setting + setting_key = 'presentations/impress use display setting' + if self.settings.value(setting_key) != self.odp_display_check_box.checkState(): + self.settings.setValue(setting_key, self.odp_display_check_box.checkState()) + changed = True if changed: self.settings_form.register_post_process('mediaitem_suffix_reset') self.settings_form.register_post_process('mediaitem_presentation_rebuild') diff --git a/tests/functional/openlp_plugins/presentations/test_presentationtab.py b/tests/functional/openlp_plugins/presentations/test_presentationtab.py new file mode 100644 index 000000000..9d2ede56a --- /dev/null +++ b/tests/functional/openlp_plugins/presentations/test_presentationtab.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- + +########################################################################## +# OpenLP - Open Source Lyrics Projection # +# ---------------------------------------------------------------------- # +# Copyright (c) 2008-2021 OpenLP Developers # +# ---------------------------------------------------------------------- # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +########################################################################## +""" +This module contains tests for the settings tab for the Presentations plugin. +""" +from unittest.mock import MagicMock + +from PyQt5 import QtCore, QtTest + +from openlp.core.common.registry import Registry +from openlp.plugins.presentations.lib.presentationtab import PresentationTab + +__default_settings__ = { + 'presentations/powerpoint slide click advance': QtCore.Qt.Unchecked, + 'presentations/powerpoint control window': QtCore.Qt.Unchecked, + 'presentations/impress use display setting': QtCore.Qt.Unchecked +} + + +def Mocked_Controllers(impress_available, powerpoint_available): + impress_controller = MagicMock() + impress_controller.name = 'Impress' + impress_controller.display_name = 'Impress' + impress_controller.is_available.return_value = impress_available + powerpoint_controller = MagicMock() + powerpoint_controller.name = 'Powerpoint' + powerpoint_controller.display_name = 'Powerpoint' + powerpoint_controller.is_available.return_value = powerpoint_available + return {'Impress': impress_controller, 'Powerpoint': powerpoint_controller} + + +def test_check_boxes(settings): + """ + Test check box options are correctly saved + """ + # GIVEN: A presentations tab fixture + Registry().register('settings_form', MagicMock()) + Registry().get('settings').extend_default_settings(__default_settings__) + form = PresentationTab(None, 'Presentations', None, Mocked_Controllers(True, True), None) + + # WHEN: The presentations tab checkboxes are checked and the form saved + QtTest.QTest.mouseClick(form.ppt_slide_click_check_box, QtCore.Qt.LeftButton) + QtTest.QTest.mouseClick(form.ppt_window_check_box, QtCore.Qt.LeftButton) + QtTest.QTest.mouseClick(form.odp_display_check_box, QtCore.Qt.LeftButton) + form.activated = True + form.save() + # THEN: The updated values should be stored in the settings + assert form.settings.value('presentations/powerpoint slide click advance') == QtCore.Qt.Checked + assert form.settings.value('presentations/powerpoint control window') == QtCore.Qt.Checked + assert form.settings.value('presentations/impress use display setting') == QtCore.Qt.Checked + + +def test_check_boxes_when_controllers_unavailable(settings): + """ + Test settings related check box options are unchanged when controllers aren't available + """ + # GIVEN: A presentations tab fixture + Registry().register('settings_form', MagicMock()) + Registry().get('settings').extend_default_settings(__default_settings__) + form = PresentationTab(None, 'Presentations', None, Mocked_Controllers(False, False), None) + + # WHEN: The presentations tab checkboxes are checked and the form saved + QtTest.QTest.mouseClick(form.ppt_slide_click_check_box, QtCore.Qt.LeftButton) + QtTest.QTest.mouseClick(form.ppt_window_check_box, QtCore.Qt.LeftButton) + QtTest.QTest.mouseClick(form.odp_display_check_box, QtCore.Qt.LeftButton) + form.activated = True + form.save() + # THEN: The updated values should be unchanged + assert form.settings.value('presentations/powerpoint slide click advance') == QtCore.Qt.Unchecked + assert form.settings.value('presentations/powerpoint control window') == QtCore.Qt.Unchecked + assert form.settings.value('presentations/impress use display setting') == QtCore.Qt.Unchecked