From 23ddd918d1ff8c75dd42c69dc31632b0f404a4a9 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Mon, 27 Apr 2015 16:59:22 +0100 Subject: [PATCH 01/28] Open PowerPoint hidden so the main application window isn't visible. --- .../presentations/lib/powerpointcontroller.py | 38 ++++++------------- 1 file changed, 11 insertions(+), 27 deletions(-) diff --git a/openlp/plugins/presentations/lib/powerpointcontroller.py b/openlp/plugins/presentations/lib/powerpointcontroller.py index 2fb07f3ad..a319ce1d4 100644 --- a/openlp/plugins/presentations/lib/powerpointcontroller.py +++ b/openlp/plugins/presentations/lib/powerpointcontroller.py @@ -83,9 +83,9 @@ class PowerpointController(PresentationController): log.debug('start_process') if not self.process: self.process = Dispatch('PowerPoint.Application') - self.process.Visible = True + #self.process.Visible = True # ppWindowMinimized = 2 - self.process.WindowState = 2 + #self.process.WindowState = 2 def kill(self): """ @@ -132,21 +132,12 @@ class PowerpointDocument(PresentationDocument): """ log.debug('load_presentation') try: - if not self.controller.process or not self.controller.process.Visible: + if not self.controller.process: self.controller.start_process() - self.controller.process.Presentations.Open(self.file_path, False, False, True) + self.controller.process.Presentations.Open(os.path.normpath(self.file_path), False, False, False) self.presentation = self.controller.process.Presentations(self.controller.process.Presentations.Count) self.create_thumbnails() self.create_titles_and_notes() - # Powerpoint 2010 and 2013 pops up when loading a file, so we minimize it again - if float(self.presentation.Application.Version) >= 14.0: - try: - # ppWindowMinimized = 2 - self.presentation.Application.WindowState = 2 - except (AttributeError, pywintypes.com_error) as e: - log.exception('Failed to minimize main powerpoint window') - log.exception(e) - trace_error_handler(log) # Make sure powerpoint doesn't steal focus Registry().get('main_window').activateWindow() return True @@ -203,10 +194,6 @@ class PowerpointDocument(PresentationDocument): """ log.debug('is_loaded') try: - if not self.controller.process.Visible: - return False - if self.controller.process.Windows.Count == 0: - return False if self.controller.process.Presentations.Count == 0: return False except (AttributeError, pywintypes.com_error) as e: @@ -321,7 +308,13 @@ class PowerpointDocument(PresentationDocument): except win32ui.error: dpi = 96 size = ScreenList().current['size'] - ppt_window = self.presentation.SlideShowSettings.Run() + try: + ppt_window = self.presentation.SlideShowSettings.Run() + except (AttributeError, pywintypes.com_error) as e: + log.exception('Caught exception while in get_slide_number') + log.exception(e) + trace_error_handler(log) + self.show_error_msg() if not ppt_window: return try: @@ -332,15 +325,6 @@ class PowerpointDocument(PresentationDocument): except AttributeError as e: log.exception('AttributeError while in start_presentation') log.exception(e) - # Powerpoint 2010 and 2013 pops up when starting a file, so we minimize it again - if float(self.presentation.Application.Version) >= 14.0: - try: - # ppWindowMinimized = 2 - self.presentation.Application.WindowState = 2 - except (AttributeError, pywintypes.com_error) as e: - log.exception('Failed to minimize main powerpoint window') - log.exception(e) - trace_error_handler(log) # Make sure powerpoint doesn't steal focus Registry().get('main_window').activateWindow() From e21729c14ff8e0fbde2e2ecb5189356358d57620 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Mon, 27 Apr 2015 19:07:14 +0100 Subject: [PATCH 02/28] Fix wrong indentation --- openlp/plugins/presentations/lib/powerpointcontroller.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/openlp/plugins/presentations/lib/powerpointcontroller.py b/openlp/plugins/presentations/lib/powerpointcontroller.py index a319ce1d4..03db9e84f 100644 --- a/openlp/plugins/presentations/lib/powerpointcontroller.py +++ b/openlp/plugins/presentations/lib/powerpointcontroller.py @@ -83,9 +83,6 @@ class PowerpointController(PresentationController): log.debug('start_process') if not self.process: self.process = Dispatch('PowerPoint.Application') - #self.process.Visible = True - # ppWindowMinimized = 2 - #self.process.WindowState = 2 def kill(self): """ @@ -311,7 +308,7 @@ class PowerpointDocument(PresentationDocument): try: ppt_window = self.presentation.SlideShowSettings.Run() except (AttributeError, pywintypes.com_error) as e: - log.exception('Caught exception while in get_slide_number') + log.exception('Caught exception while in get_slide_number') log.exception(e) trace_error_handler(log) self.show_error_msg() From ed6d4541054adba40e09c2dcf072f26529b28d35 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Tue, 28 Apr 2015 11:55:40 +0200 Subject: [PATCH 03/28] Small fixes for powerpoint. --- .../plugins/presentations/lib/powerpointcontroller.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/openlp/plugins/presentations/lib/powerpointcontroller.py b/openlp/plugins/presentations/lib/powerpointcontroller.py index 03db9e84f..f1c4bb557 100644 --- a/openlp/plugins/presentations/lib/powerpointcontroller.py +++ b/openlp/plugins/presentations/lib/powerpointcontroller.py @@ -121,6 +121,8 @@ class PowerpointDocument(PresentationDocument): self.presentation = None self.index_map = {} self.slide_count = 0 + self.blank_slide = None + self.blank_click = None def load_presentation(self): """ @@ -230,10 +232,12 @@ class PowerpointDocument(PresentationDocument): self.presentation.SlideShowWindow.View.State = 1 self.presentation.SlideShowWindow.Activate() # Unblanking is broken in PowerPoint 2010 and 2013, need to redisplay - if float(self.presentation.Application.Version) >= 14.0: + if float(self.presentation.Application.Version) >= 14.0 and self.blank_slide: self.presentation.SlideShowWindow.View.GotoSlide(self.blank_slide, False) if self.blank_click: self.presentation.SlideShowWindow.View.GotoClick(self.blank_click) + self.blank_slide = None + self.blank_click = None except (AttributeError, pywintypes.com_error) as e: log.exception('Caught exception while in unblank_screen') log.exception(e) @@ -279,7 +283,7 @@ class PowerpointDocument(PresentationDocument): def stop_presentation(self): """ - Stops the current presentation and hides the output. + Stops the current presentation and hides the output. Used when blanking to desktop. """ log.debug('stop_presentation') try: @@ -305,10 +309,11 @@ class PowerpointDocument(PresentationDocument): except win32ui.error: dpi = 96 size = ScreenList().current['size'] + ppt_window = None try: ppt_window = self.presentation.SlideShowSettings.Run() except (AttributeError, pywintypes.com_error) as e: - log.exception('Caught exception while in get_slide_number') + log.exception('Caught exception while in start_presentation') log.exception(e) trace_error_handler(log) self.show_error_msg() From 9c0525b00c62a727e88176a00fb4f76de5e319c5 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Tue, 28 Apr 2015 14:36:43 +0200 Subject: [PATCH 04/28] Use return-to-pre-blank-slide fix for all powerpoint versions. --- .../plugins/presentations/lib/powerpointcontroller.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/openlp/plugins/presentations/lib/powerpointcontroller.py b/openlp/plugins/presentations/lib/powerpointcontroller.py index f1c4bb557..518f2040a 100644 --- a/openlp/plugins/presentations/lib/powerpointcontroller.py +++ b/openlp/plugins/presentations/lib/powerpointcontroller.py @@ -231,8 +231,8 @@ class PowerpointDocument(PresentationDocument): # ppSlideShowRunning = 1 self.presentation.SlideShowWindow.View.State = 1 self.presentation.SlideShowWindow.Activate() - # Unblanking is broken in PowerPoint 2010 and 2013, need to redisplay - if float(self.presentation.Application.Version) >= 14.0 and self.blank_slide: + # Unblanking is broken it seems, can't return to the right slide + if self.blank_slide: self.presentation.SlideShowWindow.View.GotoSlide(self.blank_slide, False) if self.blank_click: self.presentation.SlideShowWindow.View.GotoClick(self.blank_click) @@ -252,10 +252,9 @@ class PowerpointDocument(PresentationDocument): """ log.debug('blank_screen') try: - # Unblanking is broken in PowerPoint 2010 and 2013, need to save info for later - if float(self.presentation.Application.Version) >= 14.0: - self.blank_slide = self.get_slide_number() - self.blank_click = self.presentation.SlideShowWindow.View.GetClickIndex() + # Unblanking is broken it seems, can't return to the right slide, need to save info for later + self.blank_slide = self.get_slide_number() + self.blank_click = self.presentation.SlideShowWindow.View.GetClickIndex() # ppSlideShowBlackScreen = 3 self.presentation.SlideShowWindow.View.State = 3 except (AttributeError, pywintypes.com_error) as e: From 472baeb07927a77a08b261867aa8d3b08bc38e36 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Tue, 28 Apr 2015 22:24:01 +0100 Subject: [PATCH 05/28] Fix blanking --- openlp/plugins/presentations/lib/messagelistener.py | 4 ++-- .../presentations/lib/powerpointcontroller.py | 12 ------------ 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/openlp/plugins/presentations/lib/messagelistener.py b/openlp/plugins/presentations/lib/messagelistener.py index c420d5f3a..a599e6f87 100644 --- a/openlp/plugins/presentations/lib/messagelistener.py +++ b/openlp/plugins/presentations/lib/messagelistener.py @@ -243,6 +243,8 @@ class Controller(object): Instruct the controller to stop and hide the presentation. """ log.debug('Live = %s, stop' % self.is_live) + # Save the current slide number to be able to return to this slide if the presentation is activated again. + self.doc.slidenumber = self.doc.get_slide_number() self.hide_mode = HideMode.Screen if not self.doc: return @@ -266,8 +268,6 @@ class Controller(object): return if not self.activate(): return - if self.doc.slidenumber and self.doc.slidenumber != self.doc.get_slide_number(): - self.doc.goto_slide(self.doc.slidenumber) self.doc.unblank_screen() Registry().execute('live_display_hide', HideMode.Screen) diff --git a/openlp/plugins/presentations/lib/powerpointcontroller.py b/openlp/plugins/presentations/lib/powerpointcontroller.py index 518f2040a..ed90dda9a 100644 --- a/openlp/plugins/presentations/lib/powerpointcontroller.py +++ b/openlp/plugins/presentations/lib/powerpointcontroller.py @@ -121,8 +121,6 @@ class PowerpointDocument(PresentationDocument): self.presentation = None self.index_map = {} self.slide_count = 0 - self.blank_slide = None - self.blank_click = None def load_presentation(self): """ @@ -231,13 +229,6 @@ class PowerpointDocument(PresentationDocument): # ppSlideShowRunning = 1 self.presentation.SlideShowWindow.View.State = 1 self.presentation.SlideShowWindow.Activate() - # Unblanking is broken it seems, can't return to the right slide - if self.blank_slide: - self.presentation.SlideShowWindow.View.GotoSlide(self.blank_slide, False) - if self.blank_click: - self.presentation.SlideShowWindow.View.GotoClick(self.blank_click) - self.blank_slide = None - self.blank_click = None except (AttributeError, pywintypes.com_error) as e: log.exception('Caught exception while in unblank_screen') log.exception(e) @@ -252,9 +243,6 @@ class PowerpointDocument(PresentationDocument): """ log.debug('blank_screen') try: - # Unblanking is broken it seems, can't return to the right slide, need to save info for later - self.blank_slide = self.get_slide_number() - self.blank_click = self.presentation.SlideShowWindow.View.GetClickIndex() # ppSlideShowBlackScreen = 3 self.presentation.SlideShowWindow.View.State = 3 except (AttributeError, pywintypes.com_error) as e: From cc5aba2008ec2e89084c2701578f611cbffb7ea2 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Wed, 29 Apr 2015 09:13:01 +0200 Subject: [PATCH 06/28] Fix vlc test --- .../openlp_plugins/media/forms/test_mediaclipselectorform.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/interfaces/openlp_plugins/media/forms/test_mediaclipselectorform.py b/tests/interfaces/openlp_plugins/media/forms/test_mediaclipselectorform.py index 7f05eaa9b..0fc66d1cb 100644 --- a/tests/interfaces/openlp_plugins/media/forms/test_mediaclipselectorform.py +++ b/tests/interfaces/openlp_plugins/media/forms/test_mediaclipselectorform.py @@ -25,9 +25,9 @@ Module to test the MediaClipSelectorForm. import os from unittest import TestCase, SkipTest -from openlp.core.ui.media.vlcplayer import VLC_AVAILABLE +from openlp.core.ui.media.vlcplayer import get_vlc -if os.name == 'nt' and not VLC_AVAILABLE: +if os.name == 'nt' and not get_vlc(): raise SkipTest('Windows without VLC, skipping this test since it cannot run without vlc') from PyQt4 import QtGui, QtTest, QtCore From 335d8d2d17ee3bd8ee54022c6bafd96b1530e649 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Wed, 29 Apr 2015 09:20:25 +0200 Subject: [PATCH 07/28] pep8 fix --- tests/functional/openlp_core_ui_media/test_vlcplayer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/functional/openlp_core_ui_media/test_vlcplayer.py b/tests/functional/openlp_core_ui_media/test_vlcplayer.py index b3ef0484a..2415fae77 100644 --- a/tests/functional/openlp_core_ui_media/test_vlcplayer.py +++ b/tests/functional/openlp_core_ui_media/test_vlcplayer.py @@ -74,4 +74,4 @@ class TestVLCPlayer(TestCase): # THEN: The extra environment variable should NOT be there self.assertNotIn('VLC_PLUGIN_PATH', os.environ, - 'The plugin path should NOT be in the environment variables') \ No newline at end of file + 'The plugin path should NOT be in the environment variables') From 54fbaf3a4fc84e0994416c18c24d71847c039b8b Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Thu, 30 Apr 2015 14:37:13 +0200 Subject: [PATCH 08/28] When going from a theme-blanked item to item which doesn't support theme-blanking, switch to black-blank. --- openlp/core/ui/slidecontroller.py | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 22fd0f4b3..f36e37df5 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -826,8 +826,10 @@ class SlideController(DisplayController, RegistryProperties): old_item = self.service_item # take a copy not a link to the servicemanager copy. self.service_item = copy.copy(service_item) - if old_item and self.is_live and old_item.is_capable(ItemCapabilities.ProvidesOwnDisplay): - self._reset_blank() + # Reset blanking if needed + if old_item and self.is_live and (old_item.is_capable(ItemCapabilities.ProvidesOwnDisplay) or \ + self.service_item.is_capable(ItemCapabilities.ProvidesOwnDisplay)): + self._reset_blank(self.service_item.is_capable(ItemCapabilities.ProvidesOwnDisplay)) if service_item.is_command(): Registry().execute( '%s_start' % service_item.name.lower(), [self.service_item, self.is_live, self.hide_mode(), slide_no]) @@ -1347,7 +1349,11 @@ class SlideController(DisplayController, RegistryProperties): :param item: The service item to be processed """ - self.media_controller.video(self.controller_type, item, self.hide_mode()) + if self.is_live and self.hide_mode() == HideMode.Theme: + self.media_controller.video(self.controller_type, item, HideMode.Blank) + self.on_blank_display(True) + else: + self.media_controller.video(self.controller_type, item, self.hide_mode()) if not self.is_live: self.preview_display.show() self.slide_preview.hide() @@ -1360,16 +1366,22 @@ class SlideController(DisplayController, RegistryProperties): self.preview_display.hide() self.slide_preview.show() - def _reset_blank(self): + def _reset_blank(self, no_theme): """ Used by command items which provide their own displays to reset the screen hide attributes + + :param no_theme: Does the new item support theme-blanking. """ hide_mode = self.hide_mode() if hide_mode == HideMode.Blank: self.on_blank_display(True) elif hide_mode == HideMode.Theme: - self.on_theme_display(True) + # The new item-type doesn't support theme-blanking, so 'switch' to normal blanking. + if no_theme: + self.on_blank_display(True) + else: + self.on_theme_display(True) elif hide_mode == HideMode.Screen: self.on_hide_display(True) else: From 1333c2ff4369bbe219aca6bf5fcde7fad5a7be0e Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Thu, 30 Apr 2015 14:38:55 +0200 Subject: [PATCH 09/28] Implement workaround for unblanking bug in powerpoint 2010 --- .../presentations/lib/messagelistener.py | 3 ++- .../presentations/lib/powerpointcontroller.py | 24 +++++++++++++++---- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/openlp/plugins/presentations/lib/messagelistener.py b/openlp/plugins/presentations/lib/messagelistener.py index a599e6f87..69a23cc7f 100644 --- a/openlp/plugins/presentations/lib/messagelistener.py +++ b/openlp/plugins/presentations/lib/messagelistener.py @@ -244,7 +244,8 @@ class Controller(object): """ log.debug('Live = %s, stop' % self.is_live) # Save the current slide number to be able to return to this slide if the presentation is activated again. - self.doc.slidenumber = self.doc.get_slide_number() + if self.doc.is_active(): + self.doc.slidenumber = self.doc.get_slide_number() self.hide_mode = HideMode.Screen if not self.doc: return diff --git a/openlp/plugins/presentations/lib/powerpointcontroller.py b/openlp/plugins/presentations/lib/powerpointcontroller.py index ed90dda9a..4a0f5a0d3 100644 --- a/openlp/plugins/presentations/lib/powerpointcontroller.py +++ b/openlp/plugins/presentations/lib/powerpointcontroller.py @@ -37,6 +37,8 @@ if is_win(): import winreg import win32ui import pywintypes + import win32con + import win32api from openlp.core.lib import ScreenList from openlp.core.lib.ui import UiStrings, critical_error_message_box, translate @@ -225,10 +227,24 @@ class PowerpointDocument(PresentationDocument): """ log.debug('unblank_screen') try: - self.presentation.SlideShowSettings.Run() - # ppSlideShowRunning = 1 - self.presentation.SlideShowWindow.View.State = 1 - self.presentation.SlideShowWindow.Activate() + # Powerpoint 2010 (14.0) has a bug that prevents unblanking from working, + # so we have to works around it by sending a keystroke to Powerpoint. + # The keystroke 'U' should not have any bindings in Powerpoint so we use that + if float(self.presentation.Application.Version) == 14.0: + loops = 0 + while self.presentation.SlideShowWindow.View.State == 3: + if loops >= 10: + log.warning('Tried to unblank 10 times, break to avoid hang, leaving presentation blanked.') + break + log.debug('Unblanking by sending "U"') + self.presentation.SlideShowWindow.Activate() + win32api.keybd_event(ord('U'), 0, 0, 0) + time.sleep(0.01) + win32api.keybd_event(ord('U'), 0, win32con.KEYEVENTF_KEYUP, 0) + loops += 1 + else: + # ppSlideShowRunning = 1 + self.presentation.SlideShowWindow.View.State = 1 except (AttributeError, pywintypes.com_error) as e: log.exception('Caught exception while in unblank_screen') log.exception(e) From d04482148304c7a21a92c8e842b2e6db402ff607 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Thu, 30 Apr 2015 14:48:45 +0200 Subject: [PATCH 10/28] pep8 fixes --- openlp/core/ui/slidecontroller.py | 2 +- openlp/plugins/presentations/lib/powerpointcontroller.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index f36e37df5..7ce7317ba 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -827,7 +827,7 @@ class SlideController(DisplayController, RegistryProperties): # take a copy not a link to the servicemanager copy. self.service_item = copy.copy(service_item) # Reset blanking if needed - if old_item and self.is_live and (old_item.is_capable(ItemCapabilities.ProvidesOwnDisplay) or \ + if old_item and self.is_live and (old_item.is_capable(ItemCapabilities.ProvidesOwnDisplay) or self.service_item.is_capable(ItemCapabilities.ProvidesOwnDisplay)): self._reset_blank(self.service_item.is_capable(ItemCapabilities.ProvidesOwnDisplay)) if service_item.is_command(): diff --git a/openlp/plugins/presentations/lib/powerpointcontroller.py b/openlp/plugins/presentations/lib/powerpointcontroller.py index 4a0f5a0d3..31e65b2b1 100644 --- a/openlp/plugins/presentations/lib/powerpointcontroller.py +++ b/openlp/plugins/presentations/lib/powerpointcontroller.py @@ -227,7 +227,7 @@ class PowerpointDocument(PresentationDocument): """ log.debug('unblank_screen') try: - # Powerpoint 2010 (14.0) has a bug that prevents unblanking from working, + # Powerpoint 2010 (14.0) has a bug that prevents unblanking from working, # so we have to works around it by sending a keystroke to Powerpoint. # The keystroke 'U' should not have any bindings in Powerpoint so we use that if float(self.presentation.Application.Version) == 14.0: From cdb564c4f33f64b801b8e52f3876c08948d8e064 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Thu, 30 Apr 2015 16:57:26 +0200 Subject: [PATCH 11/28] Partly revert to old unblanking workaround for powerpoint 2010. --- .../presentations/lib/powerpointcontroller.py | 34 ++++++++----------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/openlp/plugins/presentations/lib/powerpointcontroller.py b/openlp/plugins/presentations/lib/powerpointcontroller.py index 31e65b2b1..a65f3dc2e 100644 --- a/openlp/plugins/presentations/lib/powerpointcontroller.py +++ b/openlp/plugins/presentations/lib/powerpointcontroller.py @@ -37,8 +37,7 @@ if is_win(): import winreg import win32ui import pywintypes - import win32con - import win32api + from openlp.core.lib import ScreenList from openlp.core.lib.ui import UiStrings, critical_error_message_box, translate @@ -123,6 +122,8 @@ class PowerpointDocument(PresentationDocument): self.presentation = None self.index_map = {} self.slide_count = 0 + self.blank_slide = 1 + self.blank_click = None def load_presentation(self): """ @@ -227,24 +228,13 @@ class PowerpointDocument(PresentationDocument): """ log.debug('unblank_screen') try: - # Powerpoint 2010 (14.0) has a bug that prevents unblanking from working, - # so we have to works around it by sending a keystroke to Powerpoint. - # The keystroke 'U' should not have any bindings in Powerpoint so we use that - if float(self.presentation.Application.Version) == 14.0: - loops = 0 - while self.presentation.SlideShowWindow.View.State == 3: - if loops >= 10: - log.warning('Tried to unblank 10 times, break to avoid hang, leaving presentation blanked.') - break - log.debug('Unblanking by sending "U"') - self.presentation.SlideShowWindow.Activate() - win32api.keybd_event(ord('U'), 0, 0, 0) - time.sleep(0.01) - win32api.keybd_event(ord('U'), 0, win32con.KEYEVENTF_KEYUP, 0) - loops += 1 - else: - # ppSlideShowRunning = 1 - self.presentation.SlideShowWindow.View.State = 1 + self.presentation.SlideShowWindow.Activate() + self.presentation.SlideShowWindow.View.State = 1 + # Unblanking is broken in PowerPoint 2010 (14.0), need to redisplay + if 15.0 > float(self.presentation.Application.Version) >= 14.0: + self.presentation.SlideShowWindow.View.GotoSlide(self.index_map[self.blank_slide], False) + if self.blank_click: + self.presentation.SlideShowWindow.View.GotoClick(self.blank_click) except (AttributeError, pywintypes.com_error) as e: log.exception('Caught exception while in unblank_screen') log.exception(e) @@ -259,6 +249,10 @@ class PowerpointDocument(PresentationDocument): """ log.debug('blank_screen') try: + # Unblanking is broken in PowerPoint 2010 (14.0), need to save info for later + if 15.0 > float(self.presentation.Application.Version) >= 14.0: + self.blank_slide = self.get_slide_number() + self.blank_click = self.presentation.SlideShowWindow.View.GetClickIndex() # ppSlideShowBlackScreen = 3 self.presentation.SlideShowWindow.View.State = 3 except (AttributeError, pywintypes.com_error) as e: From 73ae9a2643b430dd90b96e5c43cd5c12cdae61fb Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Fri, 1 May 2015 16:21:59 +0200 Subject: [PATCH 12/28] Make screenshots for main webview, even on single screen setup. Fixes bug 1449041. Fixes: https://launchpad.net/bugs/1449041 --- openlp/core/ui/slidecontroller.py | 3 +-- .../presentations/lib/powerpointcontroller.py | 20 +++++++++++-------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 7ce7317ba..b2956224a 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -1119,8 +1119,7 @@ class SlideController(DisplayController, RegistryProperties): This updates the preview frame, for example after changing a slide or using *Blank to Theme*. """ self.log_debug('update_preview %s ' % self.screens.current['primary']) - if not self.screens.current['primary'] and self.service_item and \ - self.service_item.is_capable(ItemCapabilities.ProvidesOwnDisplay): + if self.service_item and self.service_item.is_capable(ItemCapabilities.ProvidesOwnDisplay): # Grab now, but try again in a couple of seconds if slide change is slow QtCore.QTimer.singleShot(0.5, self.grab_maindisplay) QtCore.QTimer.singleShot(2.5, self.grab_maindisplay) diff --git a/openlp/plugins/presentations/lib/powerpointcontroller.py b/openlp/plugins/presentations/lib/powerpointcontroller.py index a65f3dc2e..516053cb7 100644 --- a/openlp/plugins/presentations/lib/powerpointcontroller.py +++ b/openlp/plugins/presentations/lib/powerpointcontroller.py @@ -138,8 +138,9 @@ class PowerpointDocument(PresentationDocument): self.presentation = self.controller.process.Presentations(self.controller.process.Presentations.Count) self.create_thumbnails() self.create_titles_and_notes() - # Make sure powerpoint doesn't steal focus - Registry().get('main_window').activateWindow() + # Make sure powerpoint doesn't steal focus, unless we're on a single screen setup + if len(ScreenList().screen_list) > 1: + Registry().get('main_window').activateWindow() return True except (AttributeError, pywintypes.com_error) as e: log.exception('Exception caught while loading Powerpoint presentation') @@ -185,8 +186,9 @@ class PowerpointDocument(PresentationDocument): trace_error_handler(log) self.presentation = None self.controller.remove_doc(self) - # Make sure powerpoint doesn't steal focus - Registry().get('main_window').activateWindow() + # Make sure powerpoint doesn't steal focus, unless we're on a single screen setup + if len(ScreenList().screen_list) > 1: + Registry().get('main_window').activateWindow() def is_loaded(self): """ @@ -240,8 +242,9 @@ class PowerpointDocument(PresentationDocument): log.exception(e) trace_error_handler(log) self.show_error_msg() - # Make sure powerpoint doesn't steal focus - Registry().get('main_window').activateWindow() + # Make sure powerpoint doesn't steal focus, unless we're on a single screen setup + if len(ScreenList().screen_list) > 1: + Registry().get('main_window').activateWindow() def blank_screen(self): """ @@ -324,8 +327,9 @@ class PowerpointDocument(PresentationDocument): except AttributeError as e: log.exception('AttributeError while in start_presentation') log.exception(e) - # Make sure powerpoint doesn't steal focus - Registry().get('main_window').activateWindow() + # Make sure powerpoint doesn't steal focus, unless we're on a single screen setup + if len(ScreenList().screen_list) > 1: + Registry().get('main_window').activateWindow() def get_slide_number(self): """ From a7a71237c0253361852f73f90e826b3baa76464a Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Fri, 1 May 2015 21:54:05 +0100 Subject: [PATCH 13/28] Added tests of powerpoint blanking. --- .../test_powerpointcontroller.py | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/tests/functional/openlp_plugins/presentations/test_powerpointcontroller.py b/tests/functional/openlp_plugins/presentations/test_powerpointcontroller.py index 52b3c1b08..f0f1f6d1f 100644 --- a/tests/functional/openlp_plugins/presentations/test_powerpointcontroller.py +++ b/tests/functional/openlp_plugins/presentations/test_powerpointcontroller.py @@ -253,3 +253,54 @@ class TestPowerpointDocument(TestCase, TestMixin): # THEN: next_step() should be call to try to advance to the next effect. self.assertTrue(doc.next_step.called, 'next_step() should have been called!') + + def blank_screen_test(self): + """ + Test that blank_screen works as expected + """ + # GIVEN: A Document with mocked controller, presentation, and mocked function get_slide_number + doc = PowerpointDocument(self.mock_controller, self.mock_presentation) + doc.presentation = MagicMock() + doc.presentation.SlideShowWindow.View.GetClickIndex.return_value = 3 + doc.presentation.Application.Version = 14.0 + doc.get_slide_number = MagicMock() + doc.get_slide_number.return_value = 2 + + # WHEN: Calling goto_slide + doc.blank_screen() + + # THEN: The view state, doc.blank_slide and doc.blank_click should have new values + self.assertEquals(doc.presentation.SlideShowWindow.View.State, 3, 'The View State should be 3') + self.assertEquals(doc.blank_slide, 2, 'doc.blank_slide should be 2 because of the PowerPoint version') + self.assertEquals(doc.blank_click, 3, 'doc.blank_click should be 3 because of the PowerPoint version') + + def unblank_screen_test(self): + """ + Test that unblank_screen works as expected + """ + # GIVEN: A Document with mocked controller, presentation, ScreenList, and mocked function get_slide_number + with patch('openlp.plugins.presentations.lib.powerpointcontroller.ScreenList') as mocked_screen_list: + mocked_screen_list_ret = MagicMock() + mocked_screen_list_ret.screen_list = [1] + mocked_screen_list.return_value = mocked_screen_list_ret + doc = PowerpointDocument(self.mock_controller, self.mock_presentation) + doc.presentation = MagicMock() + doc.presentation.SlideShowWindow.View.GetClickIndex.return_value = 3 + doc.presentation.Application.Version = 14.0 + doc.get_slide_number = MagicMock() + doc.get_slide_number.return_value = 2 + doc.index_map[1] = 1 + doc.blank_slide = 1 + doc.blank_click = 1 + + # WHEN: Calling goto_slide + doc.unblank_screen() + + # THEN: The view state have new value, and several function should have been called + self.assertEquals(doc.presentation.SlideShowWindow.View.State, 1, 'The View State should be 1') + self.assertEquals(doc.presentation.SlideShowWindow.Activate.called, True, + 'SlideShowWindow.Activate should have been called') + self.assertEquals(doc.presentation.SlideShowWindow.View.GotoSlide.called, True, + 'View.GotoSlide should have been called because of the PowerPoint version') + self.assertEquals(doc.presentation.SlideShowWindow.View.GotoClick.called, True, + 'View.GotoClick should have been called because of the PowerPoint version') From c9a8f07a37b8626a13a221099e1c315e439ca7a7 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Fri, 1 May 2015 22:17:59 +0100 Subject: [PATCH 14/28] Only use transitions if we are changing slide. Fixes bug 1449064. Fixes: https://launchpad.net/bugs/1449064 --- openlp/core/ui/slidecontroller.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index b2956224a..a21bd2026 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -1080,6 +1080,7 @@ class SlideController(DisplayController, RegistryProperties): % timeout) return row = self.preview_widget.current_slide_number() + old_selected_row = self.selected_row self.selected_row = 0 if -1 < row < self.preview_widget.slide_count(): if self.service_item.is_command(): @@ -1089,7 +1090,7 @@ class SlideController(DisplayController, RegistryProperties): else: to_display = self.service_item.get_rendered_frame(row) if self.service_item.is_text(): - self.display.text(to_display) + self.display.text(to_display, row != old_selected_row) else: if start: self.display.build_html(self.service_item, to_display) From af3eaf2b370f1211cd32a649f0f270630728110a Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Sun, 3 May 2015 19:25:00 +0100 Subject: [PATCH 15/28] Added an option for letting powerpoint control the size and position for the presentation window. Workaround for windows 8.1 scaling. --- .../presentations/lib/powerpointcontroller.py | 19 +++++++++---------- .../presentations/lib/presentationtab.py | 14 +++++++++++++- .../presentations/presentationplugin.py | 3 ++- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/openlp/plugins/presentations/lib/powerpointcontroller.py b/openlp/plugins/presentations/lib/powerpointcontroller.py index 516053cb7..a7eb753c3 100644 --- a/openlp/plugins/presentations/lib/powerpointcontroller.py +++ b/openlp/plugins/presentations/lib/powerpointcontroller.py @@ -317,16 +317,15 @@ class PowerpointDocument(PresentationDocument): log.exception(e) trace_error_handler(log) self.show_error_msg() - if not ppt_window: - return - try: - ppt_window.Top = size.y() * 72 / dpi - ppt_window.Height = size.height() * 72 / dpi - ppt_window.Left = size.x() * 72 / dpi - ppt_window.Width = size.width() * 72 / dpi - except AttributeError as e: - log.exception('AttributeError while in start_presentation') - log.exception(e) + if ppt_window and not Settings().value('presentations/powerpoint control window'): + try: + ppt_window.Top = size.y() * 72 / dpi + ppt_window.Height = size.height() * 72 / dpi + ppt_window.Left = size.x() * 72 / dpi + ppt_window.Width = size.width() * 72 / dpi + except AttributeError as e: + log.exception('AttributeError while in start_presentation') + log.exception(e) # Make sure powerpoint doesn't steal focus, unless we're on a single screen setup if len(ScreenList().screen_list) > 1: Registry().get('main_window').activateWindow() diff --git a/openlp/plugins/presentations/lib/presentationtab.py b/openlp/plugins/presentations/lib/presentationtab.py index 4075bc25b..e831c328a 100644 --- a/openlp/plugins/presentations/lib/presentationtab.py +++ b/openlp/plugins/presentations/lib/presentationtab.py @@ -74,8 +74,11 @@ class PresentationTab(SettingsTab): self.powerpoint_layout = QtGui.QVBoxLayout(self.powerpoint_group_box) self.powerpoint_layout.setObjectName('powerpoint_layout') self.ppt_slide_click_check_box = QtGui.QCheckBox(self.powerpoint_group_box) - self.powerpoint_group_box.setObjectName('ppt_slide_click_check_box') + self.ppt_slide_click_check_box.setObjectName('ppt_slide_click_check_box') self.powerpoint_layout.addWidget(self.ppt_slide_click_check_box) + self.ppt_window_check_box = QtGui.QCheckBox(self.powerpoint_group_box) + 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) # Pdf options self.pdf_group_box = QtGui.QGroupBox(self.left_column) @@ -123,6 +126,9 @@ class PresentationTab(SettingsTab): self.ppt_slide_click_check_box.setText( translate('PresentationPlugin.PresentationTab', 'Clicking on a selected slide in the slidecontroller advances to next effect.')) + self.ppt_window_check_box.setText( + translate('PresentationPlugin.PresentationTab', + 'Let PowerPoint control the size and position of the presentation window.')) self.pdf_program_check_box.setText( translate('PresentationPlugin.PresentationTab', 'Use given full path for mudraw or ghostscript binary:')) @@ -148,6 +154,8 @@ class PresentationTab(SettingsTab): self.ppt_slide_click_check_box.setChecked(Settings().value(self.settings_section + '/powerpoint slide click advance')) self.ppt_slide_click_check_box.setEnabled(powerpoint_available) + self.ppt_window_check_box.setChecked(Settings().value(self.settings_section +'/powerpoint control window')) + self.ppt_window_check_box.setEnabled(powerpoint_available) # load pdf-program settings enable_pdf_program = Settings().value(self.settings_section + '/enable_pdf_program') self.pdf_program_check_box.setChecked(enable_pdf_program) @@ -186,6 +194,10 @@ class PresentationTab(SettingsTab): if Settings().value(setting_key) != self.ppt_slide_click_check_box.checkState(): Settings().setValue(setting_key, self.ppt_slide_click_check_box.checkState()) changed = True + setting_key = self.settings_section + '/powerpoint control window' + if Settings().value(setting_key) != self.ppt_window_check_box.checkState(): + Settings().setValue(setting_key, self.ppt_window_check_box.checkState()) + changed = True # Save pdf-settings pdf_program = self.pdf_program_path.text() enable_pdf_program = self.pdf_program_check_box.checkState() diff --git a/openlp/plugins/presentations/presentationplugin.py b/openlp/plugins/presentations/presentationplugin.py index 589fb1ecf..361df514c 100644 --- a/openlp/plugins/presentations/presentationplugin.py +++ b/openlp/plugins/presentations/presentationplugin.py @@ -45,7 +45,8 @@ __default_settings__ = {'presentations/override app': QtCore.Qt.Unchecked, 'presentations/Pdf': QtCore.Qt.Checked, 'presentations/presentations files': [], 'presentations/thumbnail_scheme': '', - 'presentations/powerpoint slide click advance': QtCore.Qt.Unchecked + 'presentations/powerpoint slide click advance': QtCore.Qt.Unchecked, + 'presentations/powerpoint control window': QtCore.Qt.Unchecked } From cd6903be863b6f0bbdc132118e04fe41b12c4ee5 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Tue, 5 May 2015 10:53:31 +0200 Subject: [PATCH 16/28] Added support for Powerpoint events, which is used to update the slidecontroller if OpenLP is not in focus. --- .../presentations/lib/powerpointcontroller.py | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/openlp/plugins/presentations/lib/powerpointcontroller.py b/openlp/plugins/presentations/lib/powerpointcontroller.py index a7eb753c3..1b46a5e17 100644 --- a/openlp/plugins/presentations/lib/powerpointcontroller.py +++ b/openlp/plugins/presentations/lib/powerpointcontroller.py @@ -32,7 +32,7 @@ import time from openlp.core.common import is_win, Settings if is_win(): - from win32com.client import Dispatch + from win32com.client import DispatchWithEvents import win32com import winreg import win32ui @@ -81,9 +81,21 @@ class PowerpointController(PresentationController): """ Loads PowerPoint process. """ + class PowerPointEvents: + """ + Class to catch events from PowerPoint. + """ + def OnSlideShowNextClick(self, slideshow_window, effect): + """ + Occurs on the next click of the slide. If the main OpenLP is not in focus force update of the slidecontroller. + """ + if not Registry().get('main_window').isActiveWindow(): + log.debug('main window is not in focus - should update slidecontroller') + Registry().execute('slidecontroller_live_change', slideshow_window.View.CurrentShowPosition) + log.debug('start_process') if not self.process: - self.process = Dispatch('PowerPoint.Application') + self.process = DispatchWithEvents('PowerPoint.Application', PowerPointEvents) def kill(self): """ @@ -311,6 +323,7 @@ class PowerpointDocument(PresentationDocument): size = ScreenList().current['size'] ppt_window = None try: + self.presentation.SlideShowSettings.ShowWithAnimation = True ppt_window = self.presentation.SlideShowSettings.Run() except (AttributeError, pywintypes.com_error) as e: log.exception('Caught exception while in start_presentation') @@ -391,6 +404,7 @@ class PowerpointDocument(PresentationDocument): """ log.debug('next_step') try: + self.presentation.SlideShowWindow.Activate() self.presentation.SlideShowWindow.View.Next() except (AttributeError, pywintypes.com_error) as e: log.exception('Caught exception while in next_step') @@ -401,6 +415,9 @@ class PowerpointDocument(PresentationDocument): if self.get_slide_number() > self.get_slide_count(): log.debug('past end, stepping back to previous') self.previous_step() + # Make sure powerpoint doesn't steal focus, unless we're on a single screen setup + if len(ScreenList().screen_list) > 1: + Registry().get('main_window').activateWindow() def previous_step(self): """ From 47acc9dc89fd7a55a2c13787428630840a6b335e Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Tue, 5 May 2015 11:03:47 +0200 Subject: [PATCH 17/28] pep8 fixes --- openlp/plugins/presentations/lib/powerpointcontroller.py | 3 ++- openlp/plugins/presentations/lib/presentationtab.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/openlp/plugins/presentations/lib/powerpointcontroller.py b/openlp/plugins/presentations/lib/powerpointcontroller.py index 1b46a5e17..39dfc24e4 100644 --- a/openlp/plugins/presentations/lib/powerpointcontroller.py +++ b/openlp/plugins/presentations/lib/powerpointcontroller.py @@ -87,7 +87,8 @@ class PowerpointController(PresentationController): """ def OnSlideShowNextClick(self, slideshow_window, effect): """ - Occurs on the next click of the slide. If the main OpenLP is not in focus force update of the slidecontroller. + Occurs on the next click of the slide. + If the main OpenLP window is not in focus force update of the slidecontroller. """ if not Registry().get('main_window').isActiveWindow(): log.debug('main window is not in focus - should update slidecontroller') diff --git a/openlp/plugins/presentations/lib/presentationtab.py b/openlp/plugins/presentations/lib/presentationtab.py index e831c328a..a93ceb7b9 100644 --- a/openlp/plugins/presentations/lib/presentationtab.py +++ b/openlp/plugins/presentations/lib/presentationtab.py @@ -154,7 +154,7 @@ class PresentationTab(SettingsTab): self.ppt_slide_click_check_box.setChecked(Settings().value(self.settings_section + '/powerpoint slide click advance')) self.ppt_slide_click_check_box.setEnabled(powerpoint_available) - self.ppt_window_check_box.setChecked(Settings().value(self.settings_section +'/powerpoint control window')) + self.ppt_window_check_box.setChecked(Settings().value(self.settings_section + '/powerpoint control window')) self.ppt_window_check_box.setEnabled(powerpoint_available) # load pdf-program settings enable_pdf_program = Settings().value(self.settings_section + '/enable_pdf_program') From 51b37de551fb7a0d7323cc6ad61c3cb4628cebb9 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Tue, 5 May 2015 15:20:24 +0200 Subject: [PATCH 18/28] Fix a powerpoint test and make it run on all platforms. --- .../test_powerpointcontroller.py | 57 +++++++++---------- 1 file changed, 27 insertions(+), 30 deletions(-) diff --git a/tests/functional/openlp_plugins/presentations/test_powerpointcontroller.py b/tests/functional/openlp_plugins/presentations/test_powerpointcontroller.py index f0f1f6d1f..d905496be 100644 --- a/tests/functional/openlp_plugins/presentations/test_powerpointcontroller.py +++ b/tests/functional/openlp_plugins/presentations/test_powerpointcontroller.py @@ -164,45 +164,42 @@ class TestPowerpointDocument(TestCase, TestMixin): """ Test creating the titles from PowerPoint """ - if is_win() and self.real_controller.check_available(): - # GIVEN: mocked save_titles_and_notes, _get_text_from_shapes and two mocked slides - self.doc = PowerpointDocument(self.real_controller, self.file_name) - self.doc.save_titles_and_notes = MagicMock() - self.doc._PowerpointDocument__get_text_from_shapes = MagicMock() - slide = MagicMock() - slide.Shapes.Title.TextFrame.TextRange.Text = 'SlideText' - pres = MagicMock() - pres.Slides = [slide, slide] - self.doc.presentation = pres + # GIVEN: mocked save_titles_and_notes, _get_text_from_shapes and two mocked slides + self.doc = PowerpointDocument(self.mock_controller, self.file_name) + self.doc.get_slide_count = MagicMock() + self.doc.get_slide_count.return_value = 2 + self.doc.index_map = {1: 1, 2: 2} + self.doc.save_titles_and_notes = MagicMock() + self.doc._PowerpointDocument__get_text_from_shapes = MagicMock() + slide = MagicMock() + slide.Shapes.Title.TextFrame.TextRange.Text = 'SlideText' + pres = MagicMock() + pres.Slides = MagicMock(side_effect=[slide, slide]) + self.doc.presentation = pres - # WHEN reading the titles and notes - self.doc.create_titles_and_notes() + # WHEN reading the titles and notes + self.doc.create_titles_and_notes() - # THEN the save should have been called exactly once with 2 titles and 2 notes - self.doc.save_titles_and_notes.assert_called_once_with(['SlideText\n', 'SlideText\n'], [' ', ' ']) - else: - self.skipTest('Powerpoint not available, skipping test.') + # THEN the save should have been called exactly once with 2 titles and 2 notes + self.doc.save_titles_and_notes.assert_called_once_with(['SlideText\n', 'SlideText\n'], [' ', ' ']) def create_titles_and_notes_with_no_slides_test(self): """ Test creating the titles from PowerPoint when it returns no slides """ - if is_win() and self.real_controller.check_available(): - # GIVEN: mocked save_titles_and_notes, _get_text_from_shapes and two mocked slides - doc = PowerpointDocument(self.real_controller, self.file_name) - doc.save_titles_and_notes = MagicMock() - doc._PowerpointDocument__get_text_from_shapes = MagicMock() - pres = MagicMock() - pres.Slides = [] - doc.presentation = pres + # GIVEN: mocked save_titles_and_notes, _get_text_from_shapes and two mocked slides + doc = PowerpointDocument(self.mock_controller, self.file_name) + doc.save_titles_and_notes = MagicMock() + doc._PowerpointDocument__get_text_from_shapes = MagicMock() + pres = MagicMock() + pres.Slides = [] + doc.presentation = pres - # WHEN reading the titles and notes - doc.create_titles_and_notes() + # WHEN reading the titles and notes + doc.create_titles_and_notes() - # THEN the save should have been called exactly once with empty titles and notes - doc.save_titles_and_notes.assert_called_once_with([], []) - else: - self.skipTest('Powerpoint not available, skipping test.') + # THEN the save should have been called exactly once with empty titles and notes + doc.save_titles_and_notes.assert_called_once_with([], []) def get_text_from_shapes_test(self): """ From bf665a8549f880d590fb26e3425121b567798f91 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Thu, 7 May 2015 14:45:52 +0200 Subject: [PATCH 19/28] Remove unnecessary powerpoint presentation setting. --- openlp/plugins/presentations/lib/powerpointcontroller.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openlp/plugins/presentations/lib/powerpointcontroller.py b/openlp/plugins/presentations/lib/powerpointcontroller.py index 39dfc24e4..6d0f52872 100644 --- a/openlp/plugins/presentations/lib/powerpointcontroller.py +++ b/openlp/plugins/presentations/lib/powerpointcontroller.py @@ -324,7 +324,6 @@ class PowerpointDocument(PresentationDocument): size = ScreenList().current['size'] ppt_window = None try: - self.presentation.SlideShowSettings.ShowWithAnimation = True ppt_window = self.presentation.SlideShowSettings.Run() except (AttributeError, pywintypes.com_error) as e: log.exception('Caught exception while in start_presentation') From b52a4e640c90ec611f4f8207fdb266c0df8ceea1 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Fri, 8 May 2015 10:17:35 +0200 Subject: [PATCH 20/28] Hide the powerpoint presentation window from the taskbar - can be disabled from the settings. --- openlp/.version | 2 +- .../presentations/lib/powerpointcontroller.py | 18 ++++++++++++++++++ .../presentations/lib/presentationtab.py | 11 +++++++++++ .../presentations/presentationplugin.py | 3 ++- 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/openlp/.version b/openlp/.version index ac2cdeba0..7d2ed7c70 100644 --- a/openlp/.version +++ b/openlp/.version @@ -1 +1 @@ -2.1.3 +2.1.4 diff --git a/openlp/plugins/presentations/lib/powerpointcontroller.py b/openlp/plugins/presentations/lib/powerpointcontroller.py index 6d0f52872..ed86e6132 100644 --- a/openlp/plugins/presentations/lib/powerpointcontroller.py +++ b/openlp/plugins/presentations/lib/powerpointcontroller.py @@ -34,8 +34,10 @@ from openlp.core.common import is_win, Settings if is_win(): from win32com.client import DispatchWithEvents import win32com + import win32con import winreg import win32ui + import win32gui import pywintypes @@ -339,10 +341,26 @@ class PowerpointDocument(PresentationDocument): except AttributeError as e: log.exception('AttributeError while in start_presentation') log.exception(e) + if ppt_window and Settings().value('presentations/powerpoint hide in taskbar'): + win32gui.EnumWindows(self._window_enum_callback, size) # Make sure powerpoint doesn't steal focus, unless we're on a single screen setup if len(ScreenList().screen_list) > 1: Registry().get('main_window').activateWindow() + def _window_enum_callback(self, hwnd, size): + """ + Method for callback from win32gui.EnumWindows. + Used to hide the powerpoint presentation window from the taskbar. + """ + # Get the size of the current window and if it matches the size of our main display we assume + # it is the powerpoint presentation window and hides it from the taskbar. + (left, top, right, bottom) = win32gui.GetWindowRect(hwnd) + if size.y() == top and size.height() == (bottom - top) and size.x() == left and size.width() == (right - left): + win32gui.ShowWindow(hwnd, win32con.SW_HIDE) + win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, + win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE) | win32con.WS_EX_TOOLWINDOW) + win32gui.ShowWindow(hwnd, win32con.SW_SHOW) + def get_slide_number(self): """ Returns the current slide number. diff --git a/openlp/plugins/presentations/lib/presentationtab.py b/openlp/plugins/presentations/lib/presentationtab.py index a93ceb7b9..af6a5d4c8 100644 --- a/openlp/plugins/presentations/lib/presentationtab.py +++ b/openlp/plugins/presentations/lib/presentationtab.py @@ -79,6 +79,9 @@ class PresentationTab(SettingsTab): self.ppt_window_check_box = QtGui.QCheckBox(self.powerpoint_group_box) self.ppt_window_check_box.setObjectName('ppt_window_check_box') self.powerpoint_layout.addWidget(self.ppt_window_check_box) + self.ppt_hide_check_box = QtGui.QCheckBox(self.powerpoint_group_box) + self.ppt_hide_check_box.setObjectName('ppt_hide_check_box') + self.powerpoint_layout.addWidget(self.ppt_hide_check_box) self.left_layout.addWidget(self.powerpoint_group_box) # Pdf options self.pdf_group_box = QtGui.QGroupBox(self.left_column) @@ -129,6 +132,8 @@ class PresentationTab(SettingsTab): self.ppt_window_check_box.setText( translate('PresentationPlugin.PresentationTab', 'Let PowerPoint control the size and position of the presentation window.')) + self.ppt_hide_check_box.setText( + translate('PresentationPlugin.PresentationTab', 'Hide PowerPoint presentation windows from the taskbar')) self.pdf_program_check_box.setText( translate('PresentationPlugin.PresentationTab', 'Use given full path for mudraw or ghostscript binary:')) @@ -156,6 +161,8 @@ class PresentationTab(SettingsTab): self.ppt_slide_click_check_box.setEnabled(powerpoint_available) self.ppt_window_check_box.setChecked(Settings().value(self.settings_section + '/powerpoint control window')) self.ppt_window_check_box.setEnabled(powerpoint_available) + self.ppt_hide_check_box.setChecked(Settings().value(self.settings_section + '/powerpoint hide in taskbar')) + self.ppt_hide_check_box.setEnabled(powerpoint_available) # load pdf-program settings enable_pdf_program = Settings().value(self.settings_section + '/enable_pdf_program') self.pdf_program_check_box.setChecked(enable_pdf_program) @@ -198,6 +205,10 @@ class PresentationTab(SettingsTab): if Settings().value(setting_key) != self.ppt_window_check_box.checkState(): Settings().setValue(setting_key, self.ppt_window_check_box.checkState()) changed = True + setting_key = self.settings_section + '/powerpoint hide in taskbar' + if Settings().value(setting_key) != self.ppt_hide_check_box.checkState(): + Settings().setValue(setting_key, self.ppt_hide_check_box.checkState()) + changed = True # Save pdf-settings pdf_program = self.pdf_program_path.text() enable_pdf_program = self.pdf_program_check_box.checkState() diff --git a/openlp/plugins/presentations/presentationplugin.py b/openlp/plugins/presentations/presentationplugin.py index 361df514c..5065c6064 100644 --- a/openlp/plugins/presentations/presentationplugin.py +++ b/openlp/plugins/presentations/presentationplugin.py @@ -46,7 +46,8 @@ __default_settings__ = {'presentations/override app': QtCore.Qt.Unchecked, 'presentations/presentations files': [], 'presentations/thumbnail_scheme': '', 'presentations/powerpoint slide click advance': QtCore.Qt.Unchecked, - 'presentations/powerpoint control window': QtCore.Qt.Unchecked + 'presentations/powerpoint control window': QtCore.Qt.Unchecked, + 'presentations/powerpoint hide in taskbar': QtCore.Qt.Checked } From a07b8a8f4931fe4862d68dfee3aad730282cc423 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Fri, 8 May 2015 16:47:02 +0200 Subject: [PATCH 21/28] Added support for odp for powerpoint 2007 and newer. --- .../presentations/lib/powerpointcontroller.py | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/openlp/plugins/presentations/lib/powerpointcontroller.py b/openlp/plugins/presentations/lib/powerpointcontroller.py index ed86e6132..362803ab7 100644 --- a/openlp/plugins/presentations/lib/powerpointcontroller.py +++ b/openlp/plugins/presentations/lib/powerpointcontroller.py @@ -73,8 +73,18 @@ class PowerpointController(PresentationController): if is_win(): try: winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, 'PowerPoint.Application').Close() + try: + # Try to detect if the version is 12 (2007) or above, and if so add 'odp' as a support filetype + version_key = winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, 'PowerPoint.Application\\CurVer') + tmp1, app_version_string, tmp2 = winreg.EnumValue(version_key, 0) + version_key.Close() + app_version = int(app_version_string[-2:]) + if app_version >= 12: + self.also_supports = ['odp'] + except (OSError, ValueError): + log.warning('Detection of powerpoint version using registry failed.') return True - except WindowsError: + except OSError: pass return False @@ -511,8 +521,12 @@ def _get_text_from_shapes(shapes): :param shapes: A set of shapes to search for text. """ text = '' - for shape in shapes: - if shape.PlaceholderFormat.Type == 2: # 2 from is enum PpPlaceholderType.ppPlaceholderBody - if shape.HasTextFrame and shape.TextFrame.HasText: - text += shape.TextFrame.TextRange.Text + '\n' + try: + for shape in shapes: + if shape.PlaceholderFormat.Type == 2: # 2 from is enum PpPlaceholderType.ppPlaceholderBody + if shape.HasTextFrame and shape.TextFrame.HasText: + text += shape.TextFrame.TextRange.Text + '\n' + except pywintypes.com_error as e: + log.warning('Failed to extract text from powerpoint slide') + log.warning(e) return text From 4266d9cbdf7ce03ab300edd35833fce6f9950e1c Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Mon, 25 May 2015 12:11:04 +0100 Subject: [PATCH 22/28] For worshipassistant add a default verse-id for lyrics to use if none is given. Fixes bug 1458056. Fixes: https://launchpad.net/bugs/1458056 --- .../songs/lib/importers/worshipassistant.py | 1 + .../songs/test_worshipassistantimport.py | 2 + .../lift_up_your_heads.csv | 40 +++++++++++++++++++ .../lift_up_your_heads.json | 13 ++++++ 4 files changed, 56 insertions(+) create mode 100644 tests/resources/worshipassistantsongs/lift_up_your_heads.csv create mode 100644 tests/resources/worshipassistantsongs/lift_up_your_heads.json diff --git a/openlp/plugins/songs/lib/importers/worshipassistant.py b/openlp/plugins/songs/lib/importers/worshipassistant.py index f5254be5b..9d59a2e81 100644 --- a/openlp/plugins/songs/lib/importers/worshipassistant.py +++ b/openlp/plugins/songs/lib/importers/worshipassistant.py @@ -131,6 +131,7 @@ class WorshipAssistantImport(SongImport): return verse = '' used_verses = [] + verse_id = VerseType.tags[VerseType.Verse] + '1' for line in lyrics.splitlines(): if line.startswith('['): # verse marker # Add previous verse diff --git a/tests/functional/openlp_plugins/songs/test_worshipassistantimport.py b/tests/functional/openlp_plugins/songs/test_worshipassistantimport.py index c84ce8342..42c3a87bc 100644 --- a/tests/functional/openlp_plugins/songs/test_worshipassistantimport.py +++ b/tests/functional/openlp_plugins/songs/test_worshipassistantimport.py @@ -49,3 +49,5 @@ class TestWorshipAssistantFileImport(SongImportTestHelper): self.load_external_result_data(os.path.join(TEST_PATH, 'would_you_be_free.json'))) self.file_import(os.path.join(TEST_PATH, 'would_you_be_free2.csv'), self.load_external_result_data(os.path.join(TEST_PATH, 'would_you_be_free.json'))) + self.file_import(os.path.join(TEST_PATH, 'lift_up_your_heads.csv'), + self.load_external_result_data(os.path.join(TEST_PATH, 'lift_up_your_heads.json'))) diff --git a/tests/resources/worshipassistantsongs/lift_up_your_heads.csv b/tests/resources/worshipassistantsongs/lift_up_your_heads.csv new file mode 100644 index 000000000..18be3110b --- /dev/null +++ b/tests/resources/worshipassistantsongs/lift_up_your_heads.csv @@ -0,0 +1,40 @@ +"SongID","SongNr","Title","Author","Copyright","FirstLine","PriKey","AltKey","Tempo","Focus","Theme","Scripture","Active","Songbook","TimeSig","Introduced","LastUsed","TimesUsed","CCLINr","User1","User2","User3","User4","User5","Roadmap","Overmap","FileLink1","FileLink2","Updated","Lyrics","Info","Lyrics2","Background" +"000013ab-0000-0000-0000-000000000000","0","Lift Up Your Heads"," Bryan Mierau","Public Domain","Lift up your heads and the doors","Em","NULL","NULL","NULL","NULL","NULL","1","1","NULL","NULL","NULL","0","NULL","NULL","NULL","NULL","NULL","NULL","NULL","NULL","NULL","NULL","2004-04-07 06:36:18.952",".Em D C D + Lift up your heads and the doors of your heart +. Am B7 Em + And the King of glory will come in +(Repeat) + +.G Am D + Who is this King of Glory? +. B7 Em + The Lord strong and mighty! +.G Am D + Who is this King of Glory? +. B7 + The Lord, mighty in battle! + +.G Am D + Who is this King of Glory? +.B7 Em + Jesus our Messiah! +.G Am D + Who is this King of Glory? +.B7 Em + Jesus, Lord of Lords! + +","NULL","Lift up your heads and the doors of your heart +And the King of glory will come in +(Repeat) + +Who is this King of Glory? +The Lord strong and mighty! +Who is this King of Glory? +The Lord, mighty in battle! + +Who is this King of Glory? +Jesus our Messiah! +Who is this King of Glory? +Jesus, Lord of Lords! + +","NULL" diff --git a/tests/resources/worshipassistantsongs/lift_up_your_heads.json b/tests/resources/worshipassistantsongs/lift_up_your_heads.json new file mode 100644 index 000000000..d3ef07f44 --- /dev/null +++ b/tests/resources/worshipassistantsongs/lift_up_your_heads.json @@ -0,0 +1,13 @@ +{ + "authors": [ + "Bryan Mierau" + ], + "title": "Lift Up Your Heads", + "verse_order_list": [], + "verses": [ + [ + "Lift up your heads and the doors of your heart\nAnd the King of glory will come in\n(Repeat)\n\nWho is this King of Glory?\nThe Lord strong and mighty!\nWho is this King of Glory?\nThe Lord, mighty in battle!\n\nWho is this King of Glory?\nJesus our Messiah!\nWho is this King of Glory?\nJesus, Lord of Lords!\n", + "v1" + ] + ] +} From dce6031a9f234b1b9d6102d46e16dd644b2e381f Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Mon, 25 May 2015 12:12:54 +0100 Subject: [PATCH 23/28] Only try to hide powerpoint presentation window for powerpoint 2007 and newer. --- openlp/plugins/presentations/lib/powerpointcontroller.py | 4 +++- openlp/plugins/presentations/lib/presentationtab.py | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/openlp/plugins/presentations/lib/powerpointcontroller.py b/openlp/plugins/presentations/lib/powerpointcontroller.py index 362803ab7..5c82695e3 100644 --- a/openlp/plugins/presentations/lib/powerpointcontroller.py +++ b/openlp/plugins/presentations/lib/powerpointcontroller.py @@ -351,7 +351,9 @@ class PowerpointDocument(PresentationDocument): except AttributeError as e: log.exception('AttributeError while in start_presentation') log.exception(e) - if ppt_window and Settings().value('presentations/powerpoint hide in taskbar'): + # Hide the presentation windows icon from the taskbar, if enabled and if powerpoint 2007 or newer + if ppt_window and Settings().value('presentations/powerpoint hide in taskbar') and \ + float(self.presentation.Application.Version) >= 12.0: win32gui.EnumWindows(self._window_enum_callback, size) # Make sure powerpoint doesn't steal focus, unless we're on a single screen setup if len(ScreenList().screen_list) > 1: diff --git a/openlp/plugins/presentations/lib/presentationtab.py b/openlp/plugins/presentations/lib/presentationtab.py index af6a5d4c8..e157b5012 100644 --- a/openlp/plugins/presentations/lib/presentationtab.py +++ b/openlp/plugins/presentations/lib/presentationtab.py @@ -133,7 +133,8 @@ class PresentationTab(SettingsTab): translate('PresentationPlugin.PresentationTab', 'Let PowerPoint control the size and position of the presentation window.')) self.ppt_hide_check_box.setText( - translate('PresentationPlugin.PresentationTab', 'Hide PowerPoint presentation windows from the taskbar')) + translate('PresentationPlugin.PresentationTab', + 'Hide PowerPoint presentation windows from the taskbar (PowerPoint 2007 and newer)')) self.pdf_program_check_box.setText( translate('PresentationPlugin.PresentationTab', 'Use given full path for mudraw or ghostscript binary:')) From aef340b6310ffc4f8e3eaf381040e15ddb65dbf4 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Mon, 25 May 2015 13:08:26 +0100 Subject: [PATCH 24/28] Added some logging --- .../presentations/lib/powerpointcontroller.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/openlp/plugins/presentations/lib/powerpointcontroller.py b/openlp/plugins/presentations/lib/powerpointcontroller.py index 5c82695e3..cf846e5df 100644 --- a/openlp/plugins/presentations/lib/powerpointcontroller.py +++ b/openlp/plugins/presentations/lib/powerpointcontroller.py @@ -39,6 +39,8 @@ if is_win(): import win32ui import win32gui import pywintypes + import win32process + import win32api from openlp.core.lib import ScreenList @@ -354,6 +356,7 @@ class PowerpointDocument(PresentationDocument): # Hide the presentation windows icon from the taskbar, if enabled and if powerpoint 2007 or newer if ppt_window and Settings().value('presentations/powerpoint hide in taskbar') and \ float(self.presentation.Application.Version) >= 12.0: + log.debug('main display size: y=%d, height=%d, x=%d, width=%d' % (size.y(), size.height(), size.x(), size.width())) win32gui.EnumWindows(self._window_enum_callback, size) # Make sure powerpoint doesn't steal focus, unless we're on a single screen setup if len(ScreenList().screen_list) > 1: @@ -367,6 +370,16 @@ class PowerpointDocument(PresentationDocument): # Get the size of the current window and if it matches the size of our main display we assume # it is the powerpoint presentation window and hides it from the taskbar. (left, top, right, bottom) = win32gui.GetWindowRect(hwnd) + log.debug('window size: left=%d, top=%d, right=%d, width=%d' % (left, top, right, bottom)) + log.debug('compare size: %d and %d, %d and %d, %d and %d, %d and %d' % (size.y(), top, size.height(), (bottom - top), size.x(), left, size.width(), (right - left))) + log.debug('window title: %s' % win32gui.GetWindowText(hwnd)) + try: + t,p = win32process.GetWindowThreadProcessId(hwnd) + handle = win32api.OpenProcess(0x0410, False, p) + nama = win32process.GetModuleFileNameEx(handle, 0) + log.debug('module name: %s' % nama) + except Exception: + log.debug('could not get window module name') if size.y() == top and size.height() == (bottom - top) and size.x() == left and size.width() == (right - left): win32gui.ShowWindow(hwnd, win32con.SW_HIDE) win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, From ff5be436aeedbb220a36457c7333ad58a568fb50 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Mon, 25 May 2015 21:37:29 +0100 Subject: [PATCH 25/28] Make translation of 'Advanced' specific to the bible plugin. --- openlp/plugins/bibles/lib/mediaitem.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index 0d3a40008..5bdec5bd2 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -193,7 +193,7 @@ class BibleMediaItem(MediaManagerItem): self.add_search_fields('quick', translate('BiblesPlugin.MediaItem', 'Quick')) self.quickTab.setVisible(True) # Add the Advanced Search tab. - self.add_search_tab('advanced', UiStrings().Advanced) + self.add_search_tab('advanced', translate('BiblesPlugin.MediaItem', 'Advanced')) self.advanced_book_label = QtGui.QLabel(self.advancedTab) self.advanced_book_label.setObjectName('advanced_book_label') self.advancedLayout.addWidget(self.advanced_book_label, 0, 0, QtCore.Qt.AlignRight) From c3e567969b6b74fb40a6276980aeab6386e4d61f Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Mon, 25 May 2015 21:43:37 +0100 Subject: [PATCH 26/28] Don't import setting keys that does not exists. Fixes bug 1458672. Fixes: https://launchpad.net/bugs/1458672 --- openlp/core/ui/mainwindow.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 34cbad495..3b6a4b2c7 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -900,7 +900,10 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow, RegistryProperties): for section_key in import_keys: if 'eneral' in section_key: section_key = section_key.lower() - value = import_settings.value(section_key) + try: + value = import_settings.value(section_key) + except KeyError: + log.warning('The key "%s" does not exist (anymore), so it will be skipped.' % section_key) if value is not None: settings.setValue('%s' % (section_key), value) now = datetime.now() From 6cd270481434d475ffd44d6a115bcc1ffd544d10 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Tue, 26 May 2015 22:26:59 +0100 Subject: [PATCH 27/28] Revert attempt to try to hide powerpoint presentation window. Instead try to minimized the flashing in the taskbar. --- .../presentations/lib/powerpointcontroller.py | 44 ++++++++++++------- .../presentations/lib/presentationtab.py | 12 ----- .../presentations/presentationplugin.py | 3 +- 3 files changed, 29 insertions(+), 30 deletions(-) diff --git a/openlp/plugins/presentations/lib/powerpointcontroller.py b/openlp/plugins/presentations/lib/powerpointcontroller.py index cf846e5df..f20ef57ac 100644 --- a/openlp/plugins/presentations/lib/powerpointcontroller.py +++ b/openlp/plugins/presentations/lib/powerpointcontroller.py @@ -151,6 +151,7 @@ class PowerpointDocument(PresentationDocument): self.slide_count = 0 self.blank_slide = 1 self.blank_click = None + self.presentation_hwnd = None def load_presentation(self): """ @@ -269,6 +270,9 @@ class PowerpointDocument(PresentationDocument): log.exception(e) trace_error_handler(log) self.show_error_msg() + # Stop powerpoint from flashing in the taskbar + if self.presentation_hwnd: + win32gui.FlashWindowEx(self.presentation_hwnd, win32con.FLASHW_STOP, 0, 0) # Make sure powerpoint doesn't steal focus, unless we're on a single screen setup if len(ScreenList().screen_list) > 1: Registry().get('main_window').activateWindow() @@ -353,10 +357,11 @@ class PowerpointDocument(PresentationDocument): except AttributeError as e: log.exception('AttributeError while in start_presentation') log.exception(e) - # Hide the presentation windows icon from the taskbar, if enabled and if powerpoint 2007 or newer - if ppt_window and Settings().value('presentations/powerpoint hide in taskbar') and \ - float(self.presentation.Application.Version) >= 12.0: - log.debug('main display size: y=%d, height=%d, x=%d, width=%d' % (size.y(), size.height(), size.x(), size.width())) + # Find the presentation window and save the handle for later + self.presentation_hwnd = None + if ppt_window: + log.debug('main display size: y=%d, height=%d, x=%d, width=%d' + % (size.y(), size.height(), size.x(), size.width())) win32gui.EnumWindows(self._window_enum_callback, size) # Make sure powerpoint doesn't steal focus, unless we're on a single screen setup if len(ScreenList().screen_list) > 1: @@ -365,26 +370,30 @@ class PowerpointDocument(PresentationDocument): def _window_enum_callback(self, hwnd, size): """ Method for callback from win32gui.EnumWindows. - Used to hide the powerpoint presentation window from the taskbar. + Used to find the powerpoint presentation window and stop it flashing in the taskbar. """ # Get the size of the current window and if it matches the size of our main display we assume - # it is the powerpoint presentation window and hides it from the taskbar. + # it is the powerpoint presentation window. (left, top, right, bottom) = win32gui.GetWindowRect(hwnd) log.debug('window size: left=%d, top=%d, right=%d, width=%d' % (left, top, right, bottom)) - log.debug('compare size: %d and %d, %d and %d, %d and %d, %d and %d' % (size.y(), top, size.height(), (bottom - top), size.x(), left, size.width(), (right - left))) + log.debug('compare size: %d and %d, %d and %d, %d and %d, %d and %d' + % (size.y(), top, size.height(), (bottom - top), size.x(), left, size.width(), (right - left))) log.debug('window title: %s' % win32gui.GetWindowText(hwnd)) + module_name = '' try: - t,p = win32process.GetWindowThreadProcessId(hwnd) - handle = win32api.OpenProcess(0x0410, False, p) - nama = win32process.GetModuleFileNameEx(handle, 0) - log.debug('module name: %s' % nama) + thread_ud, process_id = win32process.GetWindowThreadProcessId(hwnd) + handle = win32api.OpenProcess((win32con.PROCESS_VM_READ | win32con.PROCESS_QUERY_INFORMATION), + False, process_id) + module_name = win32process.GetModuleFileNameEx(handle, 0) + log.debug('module name: %s' % module_name) except Exception: log.debug('could not get window module name') - if size.y() == top and size.height() == (bottom - top) and size.x() == left and size.width() == (right - left): - win32gui.ShowWindow(hwnd, win32con.SW_HIDE) - win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, - win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE) | win32con.WS_EX_TOOLWINDOW) - win32gui.ShowWindow(hwnd, win32con.SW_SHOW) + if size.y() == top and size.height() == (bottom - top) and size.x() == left and \ + size.width() == (right - left) and 'POWERPNT.EXE' in module_name: + log.debug('Found a match and will save the handle') + self.presentation_hwnd = hwnd + # Stop powerpoint from flashing in the taskbar + win32gui.FlashWindowEx(self.presentation_hwnd, win32con.FLASHW_STOP, 0, 0) def get_slide_number(self): """ @@ -458,6 +467,9 @@ class PowerpointDocument(PresentationDocument): if self.get_slide_number() > self.get_slide_count(): log.debug('past end, stepping back to previous') self.previous_step() + # Stop powerpoint from flashing in the taskbar + if self.presentation_hwnd: + win32gui.FlashWindowEx(self.presentation_hwnd, win32con.FLASHW_STOP, 0, 0) # Make sure powerpoint doesn't steal focus, unless we're on a single screen setup if len(ScreenList().screen_list) > 1: Registry().get('main_window').activateWindow() diff --git a/openlp/plugins/presentations/lib/presentationtab.py b/openlp/plugins/presentations/lib/presentationtab.py index e157b5012..a93ceb7b9 100644 --- a/openlp/plugins/presentations/lib/presentationtab.py +++ b/openlp/plugins/presentations/lib/presentationtab.py @@ -79,9 +79,6 @@ class PresentationTab(SettingsTab): self.ppt_window_check_box = QtGui.QCheckBox(self.powerpoint_group_box) self.ppt_window_check_box.setObjectName('ppt_window_check_box') self.powerpoint_layout.addWidget(self.ppt_window_check_box) - self.ppt_hide_check_box = QtGui.QCheckBox(self.powerpoint_group_box) - self.ppt_hide_check_box.setObjectName('ppt_hide_check_box') - self.powerpoint_layout.addWidget(self.ppt_hide_check_box) self.left_layout.addWidget(self.powerpoint_group_box) # Pdf options self.pdf_group_box = QtGui.QGroupBox(self.left_column) @@ -132,9 +129,6 @@ class PresentationTab(SettingsTab): self.ppt_window_check_box.setText( translate('PresentationPlugin.PresentationTab', 'Let PowerPoint control the size and position of the presentation window.')) - self.ppt_hide_check_box.setText( - translate('PresentationPlugin.PresentationTab', - 'Hide PowerPoint presentation windows from the taskbar (PowerPoint 2007 and newer)')) self.pdf_program_check_box.setText( translate('PresentationPlugin.PresentationTab', 'Use given full path for mudraw or ghostscript binary:')) @@ -162,8 +156,6 @@ class PresentationTab(SettingsTab): self.ppt_slide_click_check_box.setEnabled(powerpoint_available) self.ppt_window_check_box.setChecked(Settings().value(self.settings_section + '/powerpoint control window')) self.ppt_window_check_box.setEnabled(powerpoint_available) - self.ppt_hide_check_box.setChecked(Settings().value(self.settings_section + '/powerpoint hide in taskbar')) - self.ppt_hide_check_box.setEnabled(powerpoint_available) # load pdf-program settings enable_pdf_program = Settings().value(self.settings_section + '/enable_pdf_program') self.pdf_program_check_box.setChecked(enable_pdf_program) @@ -206,10 +198,6 @@ class PresentationTab(SettingsTab): if Settings().value(setting_key) != self.ppt_window_check_box.checkState(): Settings().setValue(setting_key, self.ppt_window_check_box.checkState()) changed = True - setting_key = self.settings_section + '/powerpoint hide in taskbar' - if Settings().value(setting_key) != self.ppt_hide_check_box.checkState(): - Settings().setValue(setting_key, self.ppt_hide_check_box.checkState()) - changed = True # Save pdf-settings pdf_program = self.pdf_program_path.text() enable_pdf_program = self.pdf_program_check_box.checkState() diff --git a/openlp/plugins/presentations/presentationplugin.py b/openlp/plugins/presentations/presentationplugin.py index 5065c6064..361df514c 100644 --- a/openlp/plugins/presentations/presentationplugin.py +++ b/openlp/plugins/presentations/presentationplugin.py @@ -46,8 +46,7 @@ __default_settings__ = {'presentations/override app': QtCore.Qt.Unchecked, 'presentations/presentations files': [], 'presentations/thumbnail_scheme': '', 'presentations/powerpoint slide click advance': QtCore.Qt.Unchecked, - 'presentations/powerpoint control window': QtCore.Qt.Unchecked, - 'presentations/powerpoint hide in taskbar': QtCore.Qt.Checked + 'presentations/powerpoint control window': QtCore.Qt.Unchecked } From 9b0ebabc92cbb4f2e4dd5322f18e0b8684d430e8 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Wed, 27 May 2015 10:45:52 +0200 Subject: [PATCH 28/28] Last minute fixes... Don't query window process, instead look at window title for presentation filename. --- .../presentations/lib/powerpointcontroller.py | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/openlp/plugins/presentations/lib/powerpointcontroller.py b/openlp/plugins/presentations/lib/powerpointcontroller.py index f20ef57ac..107ebe4cd 100644 --- a/openlp/plugins/presentations/lib/powerpointcontroller.py +++ b/openlp/plugins/presentations/lib/powerpointcontroller.py @@ -39,8 +39,6 @@ if is_win(): import win32ui import win32gui import pywintypes - import win32process - import win32api from openlp.core.lib import ScreenList @@ -375,21 +373,13 @@ class PowerpointDocument(PresentationDocument): # Get the size of the current window and if it matches the size of our main display we assume # it is the powerpoint presentation window. (left, top, right, bottom) = win32gui.GetWindowRect(hwnd) + window_title = win32gui.GetWindowText(hwnd) log.debug('window size: left=%d, top=%d, right=%d, width=%d' % (left, top, right, bottom)) log.debug('compare size: %d and %d, %d and %d, %d and %d, %d and %d' % (size.y(), top, size.height(), (bottom - top), size.x(), left, size.width(), (right - left))) - log.debug('window title: %s' % win32gui.GetWindowText(hwnd)) - module_name = '' - try: - thread_ud, process_id = win32process.GetWindowThreadProcessId(hwnd) - handle = win32api.OpenProcess((win32con.PROCESS_VM_READ | win32con.PROCESS_QUERY_INFORMATION), - False, process_id) - module_name = win32process.GetModuleFileNameEx(handle, 0) - log.debug('module name: %s' % module_name) - except Exception: - log.debug('could not get window module name') + log.debug('window title: %s' % window_title) if size.y() == top and size.height() == (bottom - top) and size.x() == left and \ - size.width() == (right - left) and 'POWERPNT.EXE' in module_name: + size.width() == (right - left) and os.path.basename(self.file_path) in window_title: log.debug('Found a match and will save the handle') self.presentation_hwnd = hwnd # Stop powerpoint from flashing in the taskbar @@ -435,7 +425,7 @@ class PowerpointDocument(PresentationDocument): log.debug('goto_slide') try: if Settings().value('presentations/powerpoint slide click advance') \ - and self.get_slide_number() == self.index_map[slide_no]: + and self.get_slide_number() == slide_no: click_index = self.presentation.SlideShowWindow.View.GetClickIndex() click_count = self.presentation.SlideShowWindow.View.GetClickCount() log.debug('We are already on this slide - go to next effect if any left, idx: %d, count: %d'