Merge branch 'sept-2020' into 'master'

Fixes Sept 2020

Closes #633

See merge request openlp/openlp!231
This commit is contained in:
Tim Bentley 2020-09-23 08:37:57 +00:00
commit ac161d79ed
5 changed files with 144 additions and 30 deletions

View File

@ -29,6 +29,7 @@ from threading import Lock
from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5 import QtCore, QtGui, QtWidgets
from openlp.core.state import State
from openlp.core.common import SlideLimits from openlp.core.common import SlideLimits
from openlp.core.common.actions import ActionList, CategoryOrder from openlp.core.common.actions import ActionList, CategoryOrder
from openlp.core.common.i18n import UiStrings, translate from openlp.core.common.i18n import UiStrings, translate
@ -1469,24 +1470,26 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
def on_media_start(self, item): def on_media_start(self, item):
""" """
Respond to the arrival of a media service item Respond to the arrival of a media service item but only run if we have media
:param item: The service item to be processed :param item: The service item to be processed
""" """
if self.is_live and self.get_hide_mode() == HideMode.Theme: if State().check_preconditions('media'):
self.media_controller.load_video(self.controller_type, item, HideMode.Blank) if self.is_live and self.get_hide_mode() == HideMode.Theme:
self.set_hide_mode(HideMode.Blank) self.media_controller.load_video(self.controller_type, item, HideMode.Blank)
elif self.is_live or item.is_media(): self.set_hide_mode(HideMode.Blank)
# avoid loading the video if this is preview and the media is background elif self.is_live or item.is_media():
self.media_controller.load_video(self.controller_type, item, self.get_hide_mode()) # avoid loading the video if this is preview and the media is background
if not self.is_live: self.media_controller.load_video(self.controller_type, item, self.get_hide_mode())
self.preview_display.show() if not self.is_live:
self.preview_display.show()
def on_media_close(self): def on_media_close(self):
""" """
Respond to a request to close the Video Respond to a request to close the Video if we have media
""" """
self.media_controller.media_reset(self) if State().check_preconditions('media'):
self.media_controller.media_reset(self)
def _reset_blank(self, no_theme): def _reset_blank(self, no_theme):
""" """

View File

@ -23,7 +23,12 @@ This module is a base to be used for Mac OS X presentation modules using applesc
to control presentation application, such as keynote and powerpoint for mac to control presentation application, such as keynote and powerpoint for mac
""" """
import logging import logging
import applescript try:
import applescript
APPLESCRIPT_AVAILABLE = True
except ImportError:
APPLESCRIPT_AVAILABLE = False
from openlp.core.common import is_macosx from openlp.core.common import is_macosx
from openlp.core.display.screens import ScreenList from openlp.core.display.screens import ScreenList
@ -55,7 +60,8 @@ class AppleScriptBaseController(PresentationController):
""" """
super(AppleScriptBaseController, self).__init__(plugin, name, doc) super(AppleScriptBaseController, self).__init__(plugin, name, doc)
# Script expected to be overwritten by subclasses # Script expected to be overwritten by subclasses
self.applescript = applescript.AppleScript(DEFAULT_APPLESCRIPT) if APPLESCRIPT_AVAILABLE:
self.applescript = applescript.AppleScript(DEFAULT_APPLESCRIPT)
def check_available(self): def check_available(self):
""" """

View File

@ -23,7 +23,11 @@ This module is for controlling keynote.
""" """
import logging import logging
import shutil import shutil
import applescript try:
import applescript
APPLESCRIPT_AVAILABLE = True
except ImportError:
APPLESCRIPT_AVAILABLE = False
from openlp.plugins.presentations.lib.applescriptbasecontroller import AppleScriptBaseController,\ from openlp.plugins.presentations.lib.applescriptbasecontroller import AppleScriptBaseController,\
AppleScriptBaseDocument AppleScriptBaseDocument
@ -236,13 +240,14 @@ class KeynoteController(AppleScriptBaseController):
""" """
log.debug('Initialising') log.debug('Initialising')
super(KeynoteController, self).__init__(plugin, 'Keynote', KeynoteDocument) super(KeynoteController, self).__init__(plugin, 'Keynote', KeynoteDocument)
# Compiled script expected to be set by subclasses if APPLESCRIPT_AVAILABLE:
try: # Compiled script expected to be set by subclasses
self.applescript = applescript.AppleScript(KEYNOTE_APPLESCRIPT) try:
except applescript.ScriptError: self.applescript = applescript.AppleScript(KEYNOTE_APPLESCRIPT)
log.exception('Compilation of Keynote applescript failed') except applescript.ScriptError:
self.supports = ['key'] log.exception('Compilation of Keynote applescript failed')
self.also_supports = ['ppt', 'pps', 'pptx', 'ppsx', 'pptm'] self.supports = ['key']
self.also_supports = ['ppt', 'pps', 'pptx', 'ppsx', 'pptm']
def check_available(self): def check_available(self):
""" """

View File

@ -22,7 +22,11 @@
This module is for controlling keynote. This module is for controlling keynote.
""" """
import logging import logging
import applescript try:
import applescript
APPLESCRIPT_AVAILABLE = True
except ImportError:
APPLESCRIPT_AVAILABLE = False
try: try:
import fitz import fitz
@ -277,13 +281,14 @@ class PowerPointMacController(AppleScriptBaseController):
""" """
log.debug('Initialising') log.debug('Initialising')
super(PowerPointMacController, self).__init__(plugin, 'PowerPointMac', PowerPointMacDocument) super(PowerPointMacController, self).__init__(plugin, 'PowerPointMac', PowerPointMacDocument)
# Compiled script expected to be set by subclasses if APPLESCRIPT_AVAILABLE:
try: # Compiled script expected to be set by subclasses
self.applescript = applescript.AppleScript(POWERPOINT_MAC_APPLESCRIPT) try:
except applescript.ScriptError: self.applescript = applescript.AppleScript(POWERPOINT_MAC_APPLESCRIPT)
log.exception('Compilation of Powerpoint applescript failed') except applescript.ScriptError:
self.supports = ['ppt', 'pps', 'pptx', 'ppsx', 'pptm'] log.exception('Compilation of Powerpoint applescript failed')
self.also_supports = ['odp'] self.supports = ['ppt', 'pps', 'pptx', 'ppsx', 'pptm']
self.also_supports = ['odp']
def check_available(self): def check_available(self):
""" """

View File

@ -25,6 +25,7 @@ from unittest.mock import MagicMock, patch, sentinel
from PyQt5 import QtCore, QtGui from PyQt5 import QtCore, QtGui
from openlp.core.state import State
from openlp.core.common.registry import Registry from openlp.core.common.registry import Registry
from openlp.core.lib import ServiceItemAction from openlp.core.lib import ServiceItemAction
from openlp.core.ui import HideMode from openlp.core.ui import HideMode
@ -771,7 +772,7 @@ def test_reload_theme(mock_settings):
@patch.object(Registry, 'execute') @patch.object(Registry, 'execute')
def test_process_item(mocked_execute, registry): def test_process_item(mocked_execute, registry, state_media):
""" """
Test that presentation service-items is closed when followed by a media service-item Test that presentation service-items is closed when followed by a media service-item
""" """
@ -818,6 +819,100 @@ def test_process_item(mocked_execute, registry):
'The presentation should have been stopped.' 'The presentation should have been stopped.'
@patch.object(Registry, 'execute')
def test_process_item_song_vlc(mocked_execute, registry, state_media):
"""
Test that media is started if VLC is present.
"""
# GIVEN: A mocked presentation service item, a mocked media service item, a mocked Registry.execute
# and a slide controller with many mocks.
mocked_pres_item = MagicMock()
mocked_pres_item.name = 'mocked_song_item'
mocked_pres_item.is_command.return_value = False
mocked_pres_item.is_media.return_value = True
mocked_pres_item.is_image.return_value = False
mocked_pres_item.from_service = False
mocked_pres_item.get_frames.return_value = []
mocked_media_item = MagicMock()
mocked_media_item.name = 'mocked_media_item'
mocked_media_item.is_command.return_value = True
mocked_media_item.is_media.return_value = True
mocked_media_item.is_image.return_value = False
mocked_media_item.from_service = False
mocked_media_item.get_frames.return_value = []
mocked_main_window = MagicMock()
Registry().register('main_window', mocked_main_window)
Registry().register('media_controller', MagicMock())
Registry().register('application', MagicMock())
slide_controller = SlideController(None)
slide_controller.service_item = mocked_pres_item
slide_controller.is_live = False
slide_controller.preview_widget = MagicMock()
slide_controller.preview_display = MagicMock()
slide_controller.enable_tool_bar = MagicMock()
slide_controller.slide_selected = MagicMock()
slide_controller.on_stop_loop = MagicMock()
slide_controller.info_label = MagicMock()
slide_controller.displays = [MagicMock()]
slide_controller.split = 0
slide_controller.type_prefix = 'test'
# WHEN: _process_item is called
slide_controller._process_item(mocked_media_item, 0)
# THEN: Registry.execute should have been called to stop the presentation
assert 1 == slide_controller.media_controller.load_video.call_count, ' Load_video should have been called 1 times'
assert 2 == slide_controller.preview_display.load_verses.call_count, 'Execute should have been called 2 times'
@patch.object(Registry, 'execute')
def test_process_item_song_no_vlc(mocked_execute, registry, state_media):
"""
Test that media is started if VLC is present.
"""
# GIVEN: A mocked presentation service item, a mocked media service item, a mocked Registry.execute
# and a slide controller with many mocks.
State().update_pre_conditions("media", False)
State().flush_preconditions()
mocked_pres_item = MagicMock()
mocked_pres_item.name = 'mocked_song_item'
mocked_pres_item.is_command.return_value = False
mocked_pres_item.is_media.return_value = True
mocked_pres_item.is_image.return_value = False
mocked_pres_item.from_service = False
mocked_pres_item.get_frames.return_value = []
mocked_media_item = MagicMock()
mocked_media_item.name = 'mocked_media_item'
mocked_media_item.is_command.return_value = True
mocked_media_item.is_media.return_value = True
mocked_media_item.is_image.return_value = False
mocked_media_item.from_service = False
mocked_media_item.get_frames.return_value = []
mocked_main_window = MagicMock()
Registry().register('main_window', mocked_main_window)
Registry().register('media_controller', MagicMock())
Registry().register('application', MagicMock())
slide_controller = SlideController(None)
slide_controller.service_item = mocked_pres_item
slide_controller.is_live = False
slide_controller.preview_widget = MagicMock()
slide_controller.preview_display = MagicMock()
slide_controller.enable_tool_bar = MagicMock()
slide_controller.slide_selected = MagicMock()
slide_controller.on_stop_loop = MagicMock()
slide_controller.info_label = MagicMock()
slide_controller.displays = [MagicMock()]
slide_controller.split = 0
slide_controller.type_prefix = 'test'
# WHEN: _process_item is called
slide_controller._process_item(mocked_media_item, 0)
# THEN: Registry.execute should have been called to stop the presentation
assert 0 == slide_controller.media_controller.load_video.call_count, ' Load_video should have been called 0 times'
assert 2 == slide_controller.preview_display.load_verses.call_count, 'Execute should have been called 2 times'
def test_live_stolen_focus_shortcuts(settings): def test_live_stolen_focus_shortcuts(settings):
""" """
Test that all the needed shortcuts are available in scenarios where Live has stolen focus. Test that all the needed shortcuts are available in scenarios where Live has stolen focus.