diff --git a/openlp/core/display/screens.py b/openlp/core/display/screens.py index ef9af023c..2d8992b6f 100644 --- a/openlp/core/display/screens.py +++ b/openlp/core/display/screens.py @@ -41,18 +41,19 @@ class Screen(object): """ A Python representation of a screen """ - def __init__(self, number=None, geometry=None, is_primary=False, is_display=False): + def __init__(self, number=None, geometry=None, custom_geometry=None, is_primary=False, is_display=False): """ Set up the screen object :param int number: The Qt number of this screen :param QRect geometry: The geometry of this screen as a QRect object + :param QRect custom_geometry: The custom geometry of this screen as a QRect object :param bool is_primary: Whether or not this screen is the primary screen :param bool is_display: Whether or not this screen should be used to display lyrics """ self.number = int(number) self.geometry = geometry - self.custom_geometry = None + self.custom_geometry = custom_geometry self.is_primary = is_primary self.is_display = is_display @@ -131,16 +132,17 @@ class Screen(object): :param dict screen_dict: The dictionary which we want to apply to the screen """ - self.number = int(screen_dict['number']) - self.is_display = screen_dict['is_display'] - self.is_primary = screen_dict['is_primary'] - try: - self.geometry = QtCore.QRect(screen_dict['geometry']['x'], screen_dict['geometry']['y'], - screen_dict['geometry']['width'], screen_dict['geometry']['height']) - except KeyError: - # Preserve the current values as this has come from the settings update which does not have - # the geometry information - pass + 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: + try: + self.geometry = QtCore.QRect(screen_dict['geometry']['x'], screen_dict['geometry']['y'], + screen_dict['geometry']['width'], screen_dict['geometry']['height']) + except KeyError: + # Preserve the current values as this has come from the settings update which does not have + # the geometry information + pass if 'custom_geometry' in screen_dict: self.custom_geometry = QtCore.QRect(screen_dict['custom_geometry']['x'], screen_dict['custom_geometry']['y'], @@ -322,7 +324,7 @@ class ScreenList(metaclass=Singleton): os_screens.sort(key=cmp_to_key(_screen_compare)) for number, screen in enumerate(os_screens): self.screens.append( - Screen(number, screen.geometry(), self.desktop.primaryScreen() == number)) + Screen(number, screen.geometry(), is_primary=self.desktop.primaryScreen() == number)) def on_screen_resolution_changed(self, number): """ diff --git a/tests/functional/openlp_core/display/test_screens.py b/tests/functional/openlp_core/display/test_screens.py index 01724c40d..49806f23e 100644 --- a/tests/functional/openlp_core/display/test_screens.py +++ b/tests/functional/openlp_core/display/test_screens.py @@ -126,3 +126,134 @@ class TestScreenList(TestCase): 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 + + +def test_screen_from_dict(): + """Test that all the correct attributes are set when creating a screen from a dictionary""" + # GIVEN: A dictionary of values + screen_dict = { + 'number': 1, + 'geometry': {'x': 0, 'y': 0, 'width': 1920, 'height': 1080}, + 'custom_geometry': {'x': 10, 'y': 10, 'width': 1900, 'height': 1060}, + 'is_primary': True, + 'is_display': False + } + + # WHEN: A screen object is created from a dictionary + screen = Screen.from_dict(screen_dict) + + # THEN: A screen object with the correct attributes is created + assert screen.number == 1 + assert screen.is_primary is True + assert screen.is_display is False + assert screen.geometry == QtCore.QRect(0, 0, 1920, 1080) + assert screen.custom_geometry == QtCore.QRect(10, 10, 1900, 1060) + + +def test_screen_to_dict(): + """Test that the correct dictionary is generated""" + # GIVEN: A screen object + screen = Screen(1, QtCore.QRect(0, 0, 1920, 1080), QtCore.QRect(10, 10, 1900, 1060), True, False) + + # WHEN: A dictionary is generated + screen_dict = screen.to_dict() + + # THEN: The dictionary should be correct + expected_screen = { + 'number': 1, + 'geometry': {'x': 0, 'y': 0, 'width': 1920, 'height': 1080}, + 'custom_geometry': {'x': 10, 'y': 10, 'width': 1900, 'height': 1060}, + 'is_primary': True, + 'is_display': False + } + assert screen_dict == expected_screen + + +def test_screen_update(): + """Test that updating a screen object from a dictionary results in the correct attributes""" + # GIVEN: A screen object and a dictionary with updated values + screen = Screen(1, QtCore.QRect(0, 0, 1920, 1080), is_primary=True, is_display=False) + updated_screen = { + 'geometry': {'x': 0, 'y': 0, 'width': 3840, 'height': 2160}, + 'custom_geometry': {'x': 10, 'y': 10, 'width': 1900, 'height': 1060}, + 'is_primary': False, + 'is_display': True + } + + # WHEN: screen.update() is called + screen.update(updated_screen) + + # Then the screen attributes should be correct + assert screen.is_primary is False + assert screen.is_display is True + assert screen.geometry == QtCore.QRect(0, 0, 3840, 2160) + assert screen.custom_geometry == QtCore.QRect(10, 10, 1900, 1060) + + +def test_screen_update_bad_geometry(): + """Test that updating a screen object from a dictionary results in the correct attributes""" + # GIVEN: A screen object and a dictionary with updated values + screen = Screen(1, QtCore.QRect(0, 0, 1920, 1080), is_primary=True, is_display=False) + updated_screen = { + 'geometry': {'x': 0, 'y': 0, 'x2': 3840, 'y2': 2160}, + 'custom_geometry': {'x': 10, 'y': 10, 'width': 1900, 'height': 1060}, + 'is_primary': False, + 'is_display': True + } + + # WHEN: screen.update() is called + screen.update(updated_screen) + + # Then the screen attributes should be correct + assert screen.is_primary is False + assert screen.is_display is True + assert screen.geometry == QtCore.QRect(0, 0, 1920, 1080) + assert screen.custom_geometry == QtCore.QRect(10, 10, 1900, 1060) + + +def test_screen_to_str(): + """Test that the correct string is generated""" + # GIVEN: A screen object + screen = Screen(1, QtCore.QRect(0, 0, 1920, 1080), QtCore.QRect(10, 10, 1900, 1060), True, False) + + # WHEN: A string is generated + screen_str = str(screen) + + # THEN: The string should be correct (screens are 0-based) + assert screen_str == 'Screen 2 (primary)' + + +def test_screen_display_geometry(): + """Test that the display_geometry property returns the geometry when no custom geometry exists""" + # GIVEN: A screen object + screen = Screen(1, QtCore.QRect(0, 0, 1920, 1080), is_primary=True, is_display=False) + + # WHEN: The display_geometry property is accessed + display_geometry = screen.display_geometry + + # THEN: The display geometry is correct + assert display_geometry == QtCore.QRect(0, 0, 1920, 1080) + + +def test_screen_display_geometry_custom(): + """Test that the display_geometry property returns the custom geometry when it exists""" + # GIVEN: A screen object + screen = Screen(1, QtCore.QRect(0, 0, 1920, 1080), QtCore.QRect(10, 10, 1900, 1060), True, False) + + # WHEN: The display_geometry property is accessed + display_geometry = screen.display_geometry + + # THEN: The display geometry is correct + assert display_geometry == QtCore.QRect(10, 10, 1900, 1060) + + +def test_screen_repr(): + """Test that the correct screen representation is generated""" + # GIVEN: A screen object + screen = Screen(1, QtCore.QRect(0, 0, 1920, 1080), QtCore.QRect(10, 10, 1900, 1060), True, False) + + # WHEN: A string is generated + screen_str = screen.__repr__() + + # THEN: The string should be correct (screens are 0-based) + assert screen_str == ''