diff --git a/openlp/core/lib/projector/pjlink1.py b/openlp/core/lib/projector/pjlink1.py index 5feda33f4..c5c765d62 100644 --- a/openlp/core/lib/projector/pjlink1.py +++ b/openlp/core/lib/projector/pjlink1.py @@ -515,7 +515,7 @@ class PJLink1(QTcpSocket): self.socket_timer.start() try: self.projectorNetwork.emit(S_NETWORK_SENDING) - sent = self.write(out) + sent = self.write(out.encode('ascii')) self.waitForBytesWritten(2000) # 2 seconds should be enough if sent == -1: # Network error? @@ -665,7 +665,15 @@ class PJLink1(QTcpSocket): :param data: Class that projector supports. """ - self.pjlink_class = data + # bug 1550891: Projector returns non-standard class response: + # : Expected: %1CLSS=1 + # : Received: %1CLSS=Class 1 + if len(data) > 1: + # Split non-standard information from response + clss = data.split()[-1] + else: + clss = data + self.pjlink_class = clss log.debug('(%s) Setting pjlink_class for this projector to "%s"' % (self.ip, self.pjlink_class)) return diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index a4bfa4bc5..d9a9a6468 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -408,10 +408,7 @@ class MainDisplay(OpenLPMixin, Display, RegistryProperties): self.application.process_events() # Workaround for bug #1531319, should not be needed with PyQt 5.6. if is_win(): - # Workaround for bug #1531319, should not be needed with PyQt 5.6. fade_shake_timer.stop() - elif is_win(): - self.shake_web_view() # Wait for the webview to update before getting the preview. # Important otherwise first preview will miss the background ! while not self.web_loaded: @@ -429,6 +426,9 @@ class MainDisplay(OpenLPMixin, Display, RegistryProperties): self.setVisible(True) else: self.setVisible(True) + # Workaround for bug #1531319, should not be needed with PyQt 5.6. + if is_win(): + self.shake_web_view() return self.grab() def build_html(self, service_item, image_path=''): diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 2579580df..d2e2fe4ae 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -601,13 +601,21 @@ class SlideController(DisplayController, RegistryProperties): def __add_actions_to_widget(self, widget): """ Add actions to the widget specified by `widget` + This defines the controls available when Live display has stolen focus. + Examples of this happening: Clicking anything in the live window or certain single screen mode scenarios. + Needles to say, blank to modes should not be removed from here. + For some reason this required a test. It may be found in test_slidecontroller.py as + "live_stolen_focus_shortcuts_test. If you want to modify things here, you must also modify them there. (Duh) :param widget: The UI widget for the actions """ widget.addActions([ self.previous_item, self.next_item, self.previous_service, self.next_service, - self.escape_item]) + self.escape_item, + self.desktop_screen, + self.theme_screen, + self.blank_screen]) def preview_size_changed(self): """ diff --git a/tests/functional/openlp_core_lib/test_projector_pjlink1.py b/tests/functional/openlp_core_lib/test_projector_pjlink1.py index 92ce02acd..067818957 100644 --- a/tests/functional/openlp_core_lib/test_projector_pjlink1.py +++ b/tests/functional/openlp_core_lib/test_projector_pjlink1.py @@ -60,3 +60,17 @@ class TestPJLink(TestCase): "Connection request should have been called with TEST_SALT")) self.assertTrue(mock_qmd5_hash.called_with(TEST_PIN, "Connection request should have been called with TEST_PIN")) + + def non_standard_class_reply_test(self): + """ + bugfix 1550891 - CLSS request returns non-standard 'Class N' reply + """ + # GIVEN: Test object + pjlink = pjlink_test + + # WHEN: Process non-standard reply + pjlink.process_clss('Class 1') + + # THEN: Projector class should be set with proper value + self.assertEquals(pjlink.pjlink_class, '1', + 'Non-standard class reply should have set proper class') diff --git a/tests/functional/openlp_core_ui/test_slidecontroller.py b/tests/functional/openlp_core_ui/test_slidecontroller.py index 7f071a835..20e48cbe0 100644 --- a/tests/functional/openlp_core_ui/test_slidecontroller.py +++ b/tests/functional/openlp_core_ui/test_slidecontroller.py @@ -685,6 +685,34 @@ class TestSlideController(TestCase): self.assertEqual('mocked_presentation_item_stop', mocked_execute.call_args_list[1][0][0], 'The presentation should have been stopped.') + def live_stolen_focus_shortcuts_test(self): + """ + Test that all the needed shortcuts are available in scenarios where Live has stolen focus. + These are found under def __add_actions_to_widget(self, widget): in slidecontroller.py + """ + # GIVEN: A slide controller, actions needed + slide_controller = SlideController(None) + mocked_widget = MagicMock() + slide_controller.previous_item = MagicMock() + slide_controller.next_item = MagicMock() + slide_controller.previous_service = MagicMock() + slide_controller.next_service = MagicMock() + slide_controller.escape_item = MagicMock() + slide_controller.desktop_screen = MagicMock() + slide_controller.blank_screen = MagicMock() + slide_controller.theme_screen = MagicMock() + + # WHEN: __add_actions_to_widget is called + slide_controller._SlideController__add_actions_to_widget(mocked_widget) + + # THEN: The call to addActions should be correct + mocked_widget.addActions.assert_called_with([ + slide_controller.previous_item, slide_controller.next_item, + slide_controller.previous_service, slide_controller.next_service, + slide_controller.escape_item, slide_controller.desktop_screen, + slide_controller.theme_screen, slide_controller.blank_screen + ]) + class TestInfoLabel(TestCase): diff --git a/tests/functional/openlp_plugins/songusage/test_songusage.py b/tests/functional/openlp_plugins/songusage/test_songusage.py index 6b103c9f1..61d8a22bb 100644 --- a/tests/functional/openlp_plugins/songusage/test_songusage.py +++ b/tests/functional/openlp_plugins/songusage/test_songusage.py @@ -81,3 +81,19 @@ class TestSongUsage(TestCase): # THEN: It should return True self.assertTrue(ret) + + @patch('openlp.plugins.songusage.songusageplugin.Manager') + def toggle_song_usage_state_test(self, MockedManager): + """ + Test that toggle_song_usage_state does toggle song_usage_state + """ + # GIVEN: A SongUsagePlugin + song_usage = SongUsagePlugin() + song_usage.set_button_state = MagicMock() + song_usage.song_usage_active = True + + # WHEN: calling toggle_song_usage_state + song_usage.toggle_song_usage_state() + + # THEN: song_usage_state should have been toogled + self.assertFalse(song_usage.song_usage_active)