diff --git a/openlp/core/display/screens.py b/openlp/core/display/screens.py index 30f1c24fe..692c94c49 100644 --- a/openlp/core/display/screens.py +++ b/openlp/core/display/screens.py @@ -142,7 +142,6 @@ class Screen(object): :param dict screen_dict: The dictionary which we want to apply to the screen """ - self.number = int(screen_dict['number']) if 'number' in screen_dict else self.number self.is_display = screen_dict.get('is_display', self.is_display) self.is_primary = screen_dict.get('is_primary', self.is_primary) if 'geometry' in screen_dict: @@ -257,13 +256,12 @@ class ScreenList(metaclass=Singleton): screen_settings = self.settings.value('core/screens') if screen_settings: need_new_display_screen = False - for number, screen_dict in screen_settings.items(): - # Sometimes this loads as a string instead of an int - number = int(number) + for screen_dict in screen_settings.values(): # Compare geometry, primary of screen from settings with available screens - if self.has_screen(screen_dict): + screen_number = self.get_screen_number(screen_dict) + if screen_number is not None: # If match was found, we're all happy, update with custom geometry, display info, if available - self[number].update(screen_dict) + self[screen_number].update(screen_dict) else: # If no match, ignore this screen, also need to find new display screen if the discarded screen was # marked as such. @@ -333,17 +331,19 @@ class ScreenList(metaclass=Singleton): if can_save: self.save_screen_settings() - def has_screen(self, screen_dict): + def get_screen_number(self, screen_dict): """ - Confirms a screen is known. + Tries to match a screen with the passed-in screen_dict attributes + If a match is found then the number of the screen is returned. + If not then None is returned. - :param screen_dict: The dict descrebing the screen. + :param screen_dict: The dict describing the screen to match. """ for screen in self.screens: if screen.to_dict()['geometry'] == screen_dict['geometry'] \ and screen.is_primary == screen_dict['is_primary']: - return True - return False + return screen.number + return None def update_screens(self): """ diff --git a/tests/openlp_core/display/test_screens.py b/tests/openlp_core/display/test_screens.py index 9537851e0..585380ded 100644 --- a/tests/openlp_core/display/test_screens.py +++ b/tests/openlp_core/display/test_screens.py @@ -93,6 +93,146 @@ def test_create_screen_list(mocked_screens, settings): assert screen_list.screens[1].is_primary is False +@patch('openlp.core.display.screens.QtWidgets.QApplication.screens') +def test_create_screen_list_with_settings_matching(mocked_screens, settings): + """ + Create the screen list and match with saved settings + """ + # GIVEN: Mocked application and saved screen settings + mocked_application = MagicMock() + settings.setValue('core/screens', {'0': {'number': 0, 'geometry': {'x': 0, 'y': 0, 'width': 1024, 'height': 768}, + 'is_primary': True, 'is_display': False, + 'custom_geometry': {'x': 50, 'y': 50, 'width': 924, 'height': 668}}, + '1': {'number': 0, 'geometry': {'x': 1024, 'y': 0, 'width': 1024, 'height': 768}, + 'is_primary': False, 'is_display': True, + 'custom_geometry': {'x': 50, 'y': 50, 'width': 924, 'height': 568}}}) + mocked_screen1 = MagicMock(**{'geometry.return_value': QtCore.QRect(0, 0, 1024, 768)}) + mocked_screen2 = MagicMock(**{'geometry.return_value': QtCore.QRect(1024, 0, 1024, 768)}) + mocked_application.screens.return_value = [mocked_screen1, mocked_screen2] + mocked_application.primaryScreen.return_value = mocked_screen1 + + # WHEN: create() is called + screen_list = ScreenList.create(mocked_application) + + # THEN: The correct screens have been set up, matching the saved settings + assert screen_list.screens[0].number == 0 + assert screen_list.screens[0].geometry == QtCore.QRect(0, 0, 1024, 768) + assert screen_list.screens[0].is_primary is True + assert screen_list.screens[0].is_display is False + assert screen_list.screens[0].custom_geometry == QtCore.QRect(50, 50, 924, 668) + assert screen_list.screens[1].number == 1 + assert screen_list.screens[1].geometry == QtCore.QRect(1024, 0, 1024, 768) + assert screen_list.screens[1].is_primary is False + assert screen_list.screens[1].is_display is True + assert screen_list.screens[1].custom_geometry == QtCore.QRect(50, 50, 924, 568) + + +@patch('openlp.core.display.screens.QtWidgets.QApplication.screens') +@patch('openlp.core.display.screens.QtWidgets.QMessageBox.warning') +def test_create_screen_list_with_screen_unplugged(screen_warning, mocked_screens, settings): + """ + Create the screen list where saved screens > os screens (ie display unplugged) + """ + # GIVEN: Mocked application and saved screen settings + mocked_application = MagicMock() + settings.setValue('core/screens', {'0': {'number': 0, + 'geometry': {'x': -1024, 'y': 0, 'width': 1024, 'height': 768}, + 'is_primary': False, + 'is_display': True, + 'custom_geometry': {'x': 50, 'y': 50, 'width': 924, 'height': 668}}, + '1': {'number': 0, + 'geometry': {'x': 0, 'y': 0, 'width': 1024, 'height': 768}, + 'is_primary': True, + 'is_display': False, + 'custom_geometry': {'x': 50, 'y': 50, 'width': 924, 'height': 568}}}) + # set up mocked_screen to match the 2nd screen in the settings + mocked_screen1 = MagicMock(**{'geometry.return_value': QtCore.QRect(0, 0, 1024, 768)}) + mocked_application.screens.return_value = [mocked_screen1] + mocked_application.primaryScreen.return_value = mocked_screen1 + + # WHEN: create() is called + screen_list = ScreenList.create(mocked_application) + + # THEN: The correct screens have been set up + assert len(screen_list.screens) == 1 + assert screen_list.screens[0].number == 0 + assert screen_list.screens[0].geometry == QtCore.QRect(0, 0, 1024, 768) + assert screen_list.screens[0].is_primary is True + # find_new_display_screen() sets this screen's is_display to True + assert screen_list.screens[0].is_display is True + assert screen_list.screens[0].custom_geometry == QtCore.QRect(50, 50, 924, 568) + + +@patch('openlp.core.display.screens.QtWidgets.QApplication.screens') +def test_create_screen_list_with_screen_replugged_1(mocked_screens, settings): + """ + Create the screen list where saved screens < os screens (ie display plugged in again) + with saved screen matching the first screen + """ + # GIVEN: Mocked application and saved screen settings + mocked_application = MagicMock() + settings.setValue('core/screens', {'0': {'number': 0, + 'geometry': {'x': 0, 'y': 0, 'width': 1024, 'height': 768}, + 'is_primary': True, + 'is_display': True, + 'custom_geometry': {'x': 50, 'y': 50, 'width': 924, 'height': 668}}}) + # set up mocked_screen so that mocked_screen1 matches saved screen + mocked_screen1 = MagicMock(**{'geometry.return_value': QtCore.QRect(0, 0, 1024, 768)}) + mocked_screen2 = MagicMock(**{'geometry.return_value': QtCore.QRect(1024, 0, 1024, 768)}) + mocked_application.screens.return_value = [mocked_screen1, mocked_screen2] + mocked_application.primaryScreen.return_value = mocked_screen1 + + # WHEN: create() is called + screen_list = ScreenList.create(mocked_application) + + # THEN: The correct screens have been set up + assert screen_list.screens[0].number == 0 + assert screen_list.screens[0].geometry == QtCore.QRect(0, 0, 1024, 768) + assert screen_list.screens[0].is_primary is True + assert screen_list.screens[0].is_display is True + assert screen_list.screens[0].custom_geometry == QtCore.QRect(50, 50, 924, 668) + assert screen_list.screens[1].number == 1 + assert screen_list.screens[1].geometry == QtCore.QRect(1024, 0, 1024, 768) + assert screen_list.screens[1].is_primary is False + assert screen_list.screens[1].is_display is False + assert screen_list.screens[1].custom_geometry is None + + +@patch('openlp.core.display.screens.QtWidgets.QApplication.screens') +def test_create_screen_list_with_screen_replugged_2(mocked_screens, settings): + """ + Create the screen list where saved screens < os screens (ie display plugged in again) + with saved screen matching the second screen + """ + # GIVEN: Mocked application and saved screen settings + mocked_application = MagicMock() + settings.setValue('core/screens', {'0': {'number': 0, + 'geometry': {'x': 0, 'y': 0, 'width': 1024, 'height': 768}, + 'is_primary': True, + 'is_display': True, + 'custom_geometry': {'x': 50, 'y': 50, 'width': 924, 'height': 668}}}) + # set up mocked_screen so that mocked_screen2 matches saved screen + mocked_screen1 = MagicMock(**{'geometry.return_value': QtCore.QRect(-1024, 0, 1024, 768)}) + mocked_screen2 = MagicMock(**{'geometry.return_value': QtCore.QRect(0, 0, 1024, 768)}) + mocked_application.screens.return_value = [mocked_screen1, mocked_screen2] + mocked_application.primaryScreen.return_value = mocked_screen2 + + # WHEN: create() is called + screen_list = ScreenList.create(mocked_application) + + # THEN: The correct screens have been set up + assert screen_list.screens[0].number == 0 + assert screen_list.screens[0].geometry == QtCore.QRect(-1024, 0, 1024, 768) + assert screen_list.screens[0].is_primary is False + assert screen_list.screens[0].is_display is False + assert screen_list.screens[0].custom_geometry is None + assert screen_list.screens[1].number == 1 + assert screen_list.screens[1].geometry == QtCore.QRect(0, 0, 1024, 768) + assert screen_list.screens[1].is_primary is True + assert screen_list.screens[1].is_display is True + assert screen_list.screens[1].custom_geometry == QtCore.QRect(50, 50, 924, 668) + + @patch('openlp.core.display.screens.QtWidgets.QApplication.screens') def test_screen_list_on_primary_changed(mocked_screens, settings, registry): """Test that the screen is correctly updated when a primary screen is changed"""