- Noticed this had a conflict, fixed it, improved comments

This commit is contained in:
suutari-olli 2016-05-15 22:41:13 +03:00
commit 334d16d81c
20 changed files with 282 additions and 77 deletions

View File

@ -222,10 +222,11 @@ class OpenLP(OpenLPMixin, QtWidgets.QApplication):
QtWidgets.QMessageBox.warning(None, translate('OpenLP', 'Backup'), QtWidgets.QMessageBox.warning(None, translate('OpenLP', 'Backup'),
translate('OpenLP', 'Backup of the data folder failed!')) translate('OpenLP', 'Backup of the data folder failed!'))
return return
QtWidgets.QMessageBox.information(None, translate('OpenLP', 'Backup'), message = translate('OpenLP',
translate('OpenLP', 'A backup of the data folder has been created'
'A backup of the data folder has been created at %s') 'at {text}').format(text=data_folder_backup_path)
% data_folder_backup_path) QtWidgets.QMessageBox.information(None, translate('OpenLP', 'Backup'), message)
# Update the version in the settings # Update the version in the settings
Settings().setValue('core/application version', openlp_version) Settings().setValue('core/application version', openlp_version)
@ -257,7 +258,7 @@ class OpenLP(OpenLPMixin, QtWidgets.QApplication):
""" """
if event.type() == QtCore.QEvent.FileOpen: if event.type() == QtCore.QEvent.FileOpen:
file_name = event.file() file_name = event.file()
log.debug('Got open file event for %s!', file_name) log.debug('Got open file event for {name}!'.format(name=file_name))
self.args.insert(0, file_name) self.args.insert(0, file_name)
return True return True
# Mac OS X should restore app window when user clicked on the OpenLP icon # Mac OS X should restore app window when user clicked on the OpenLP icon
@ -311,7 +312,7 @@ def set_up_logging(log_path):
logfile.setFormatter(logging.Formatter('%(asctime)s %(name)-55s %(levelname)-8s %(message)s')) logfile.setFormatter(logging.Formatter('%(asctime)s %(name)-55s %(levelname)-8s %(message)s'))
log.addHandler(logfile) log.addHandler(logfile)
if log.isEnabledFor(logging.DEBUG): if log.isEnabledFor(logging.DEBUG):
print('Logging to: %s' % filename) print('Logging to: {name}'.format(name=filename))
def main(args=None): def main(args=None):
@ -351,12 +352,12 @@ def main(args=None):
log.info('Running portable') log.info('Running portable')
portable_settings_file = os.path.abspath(os.path.join(application_path, '..', '..', 'Data', 'OpenLP.ini')) portable_settings_file = os.path.abspath(os.path.join(application_path, '..', '..', 'Data', 'OpenLP.ini'))
# Make this our settings file # Make this our settings file
log.info('INI file: %s', portable_settings_file) log.info('INI file: {name}'.format(name=portable_settings_file))
Settings.set_filename(portable_settings_file) Settings.set_filename(portable_settings_file)
portable_settings = Settings() portable_settings = Settings()
# Set our data path # Set our data path
data_path = os.path.abspath(os.path.join(application_path, '..', '..', 'Data',)) data_path = os.path.abspath(os.path.join(application_path, '..', '..', 'Data',))
log.info('Data path: %s', data_path) log.info('Data path: {name}'.format(name=data_path))
# Point to our data path # Point to our data path
portable_settings.setValue('advanced/data path', data_path) portable_settings.setValue('advanced/data path', data_path)
portable_settings.setValue('advanced/is portable', True) portable_settings.setValue('advanced/is portable', True)

View File

@ -55,7 +55,9 @@ def trace_error_handler(logger):
""" """
log_string = "OpenLP Error trace" log_string = "OpenLP Error trace"
for tb in traceback.extract_stack(): for tb in traceback.extract_stack():
log_string = '%s\n File %s at line %d \n\t called %s' % (log_string, tb[0], tb[1], tb[3]) log_string += '\n File {file} at line {line} \n\t called {data}'.format(file=tb[0],
line=tb[1],
data=tb[3])
logger.error(log_string) logger.error(log_string)
@ -67,7 +69,7 @@ def check_directory_exists(directory, do_not_log=False):
:param do_not_log: To not log anything. This is need for the start up, when the log isn't ready. :param do_not_log: To not log anything. This is need for the start up, when the log isn't ready.
""" """
if not do_not_log: if not do_not_log:
log.debug('check_directory_exists %s' % directory) log.debug('check_directory_exists {text}'.format(text=directory))
try: try:
if not os.path.exists(directory): if not os.path.exists(directory):
os.makedirs(directory) os.makedirs(directory)
@ -202,13 +204,13 @@ def md5_hash(salt, data=None):
:param data: OPTIONAL Data to hash :param data: OPTIONAL Data to hash
:returns: str :returns: str
""" """
log.debug('md5_hash(salt="%s")' % salt) log.debug('md5_hash(salt="{text}")'.format(text=salt))
hash_obj = hashlib.new('md5') hash_obj = hashlib.new('md5')
hash_obj.update(salt) hash_obj.update(salt)
if data: if data:
hash_obj.update(data) hash_obj.update(data)
hash_value = hash_obj.hexdigest() hash_value = hash_obj.hexdigest()
log.debug('md5_hash() returning "%s"' % hash_value) log.debug('md5_hash() returning "{text}"'.format(text=hash_value))
return hash_value return hash_value
@ -221,12 +223,12 @@ def qmd5_hash(salt, data=None):
:param data: OPTIONAL Data to hash :param data: OPTIONAL Data to hash
:returns: str :returns: str
""" """
log.debug('qmd5_hash(salt="%s"' % salt) log.debug('qmd5_hash(salt="{text}"'.format(text=salt))
hash_obj = QHash(QHash.Md5) hash_obj = QHash(QHash.Md5)
hash_obj.addData(salt) hash_obj.addData(salt)
hash_obj.addData(data) hash_obj.addData(data)
hash_value = hash_obj.result().toHex() hash_value = hash_obj.result().toHex()
log.debug('qmd5_hash() returning "%s"' % hash_value) log.debug('qmd5_hash() returning "{text}"'.format(text=hash_value))
return hash_value.data() return hash_value.data()
@ -283,7 +285,7 @@ def get_uno_command(connection_type='pipe'):
CONNECTION = '"--accept=pipe,name=openlp_pipe;urp;"' CONNECTION = '"--accept=pipe,name=openlp_pipe;urp;"'
else: else:
CONNECTION = '"--accept=socket,host=localhost,port=2002;urp;"' CONNECTION = '"--accept=socket,host=localhost,port=2002;urp;"'
return '%s %s %s' % (command, OPTIONS, CONNECTION) return '{cmd} {opt} {conn}'.format(cmd=command, opt=OPTIONS, conn=CONNECTION)
def get_uno_instance(resolver, connection_type='pipe'): def get_uno_instance(resolver, connection_type='pipe'):
@ -333,7 +335,7 @@ def delete_file(file_path_name):
os.remove(file_path_name) os.remove(file_path_name)
return True return True
except (IOError, OSError): except (IOError, OSError):
log.exception("Unable to delete file %s" % file_path_name) log.exception("Unable to delete file {text}".format(text=file_path_name))
return False return False
@ -345,9 +347,11 @@ def get_images_filter():
if not IMAGES_FILTER: if not IMAGES_FILTER:
log.debug('Generating images filter.') log.debug('Generating images filter.')
formats = list(map(bytes.decode, list(map(bytes, QtGui.QImageReader.supportedImageFormats())))) formats = list(map(bytes.decode, list(map(bytes, QtGui.QImageReader.supportedImageFormats()))))
visible_formats = '(*.%s)' % '; *.'.join(formats) visible_formats = '(*.{text})'.format(text='; *.'.join(formats))
actual_formats = '(*.%s)' % ' *.'.join(formats) actual_formats = '(*.{text})'.format(text=' *.'.join(formats))
IMAGES_FILTER = '%s %s %s' % (translate('OpenLP', 'Image Files'), visible_formats, actual_formats) IMAGES_FILTER = '{text} {visible} {actual}'.format(text=translate('OpenLP', 'Image Files'),
visible=visible_formats,
actual=actual_formats)
return IMAGES_FILTER return IMAGES_FILTER
@ -385,7 +389,7 @@ def check_binary_exists(program_path):
:param program_path:The full path to the binary to check. :param program_path:The full path to the binary to check.
:return: program output to be parsed :return: program output to be parsed
""" """
log.debug('testing program_path: %s', program_path) log.debug('testing program_path: {text}'.format(text=program_path))
try: try:
# Setup startupinfo options for check_output to avoid console popping up on windows # Setup startupinfo options for check_output to avoid console popping up on windows
if is_win(): if is_win():
@ -399,5 +403,5 @@ def check_binary_exists(program_path):
except Exception: except Exception:
trace_error_handler(log) trace_error_handler(log)
runlog = '' runlog = ''
log.debug('check_output returned: %s' % runlog) log.debug('check_output returned: {text}'.format(text=runlog))
return runlog return runlog

View File

@ -153,6 +153,7 @@ class UiStrings(object):
self.Version = translate('OpenLP.Ui', 'Version') self.Version = translate('OpenLP.Ui', 'Version')
self.View = translate('OpenLP.Ui', 'View') self.View = translate('OpenLP.Ui', 'View')
self.ViewMode = translate('OpenLP.Ui', 'View Mode') self.ViewMode = translate('OpenLP.Ui', 'View Mode')
self.Video = translate('OpenLP.Ui', 'Video')
self.BibleShortSearchTitle = translate('OpenLP.Ui', 'Search is Empty or too Short') self.BibleShortSearchTitle = translate('OpenLP.Ui', 'Search is Empty or too Short')
self.BibleShortSearch = translate('OpenLP.Ui', '<strong>The search you have entered is empty or shorter ' self.BibleShortSearch = translate('OpenLP.Ui', '<strong>The search you have entered is empty or shorter '
'than 3 characters long.<br>Please try again with ' 'than 3 characters long.<br>Please try again with '
@ -182,3 +183,4 @@ class UiStrings(object):
itertools.chain.from_iterable(itertools.repeat(strings, 1) if isinstance(strings, str) itertools.chain.from_iterable(itertools.repeat(strings, 1) if isinstance(strings, str)
else strings for strings in bible_scripture_items) else strings for strings in bible_scripture_items)
self.BibleScriptureError = ''.join(str(joined) for joined in bible_scripture_items) self.BibleScriptureError = ''.join(str(joined) for joined in bible_scripture_items)

View File

@ -97,7 +97,7 @@ def get_text_file_string(text_file):
file_handle.seek(0) file_handle.seek(0)
content = file_handle.read() content = file_handle.read()
except (IOError, UnicodeError): except (IOError, UnicodeError):
log.exception('Failed to open text file %s' % text_file) log.exception('Failed to open text file {text}'.format(text=text_file))
finally: finally:
if file_handle: if file_handle:
file_handle.close() file_handle.close()
@ -300,6 +300,8 @@ def create_separated_list(string_list):
return '' return ''
elif len(string_list) == 1: elif len(string_list) == 1:
return string_list[0] return string_list[0]
# TODO:
# Cannot convert these strings to python3 yet until I can figure out how to mock translate() with the new format
elif len(string_list) == 2: elif len(string_list) == 2:
return translate('OpenLP.core.lib', '%s and %s', return translate('OpenLP.core.lib', '%s and %s',
'Locale list separator: 2 items') % (string_list[0], string_list[1]) 'Locale list separator: 2 items') % (string_list[0], string_list[1])

View File

@ -297,7 +297,11 @@ PJLINK_ERST_STATUS = {'0': ERROR_STRING[E_OK],
PJLINK_POWR_STATUS = {'0': S_STANDBY, PJLINK_POWR_STATUS = {'0': S_STANDBY,
'1': S_ON, '1': S_ON,
'2': S_COOLDOWN, '2': S_COOLDOWN,
'3': S_WARMUP} '3': S_WARMUP,
S_STANDBY: '0',
S_ON: '1',
S_COOLDOWN: '2',
S_WARMUP: '3'}
PJLINK_DEFAULT_SOURCES = {'1': translate('OpenLP.DB', 'RGB'), PJLINK_DEFAULT_SOURCES = {'1': translate('OpenLP.DB', 'RGB'),
'2': translate('OpenLP.DB', 'Video'), '2': translate('OpenLP.DB', 'Video'),

View File

@ -44,6 +44,7 @@ class BackgroundType(object):
Gradient = 1 Gradient = 1
Image = 2 Image = 2
Transparent = 3 Transparent = 3
Video = 4
@staticmethod @staticmethod
def to_string(background_type): def to_string(background_type):
@ -58,6 +59,8 @@ class BackgroundType(object):
return 'image' return 'image'
elif background_type == BackgroundType.Transparent: elif background_type == BackgroundType.Transparent:
return 'transparent' return 'transparent'
elif background_type == BackgroundType.Video:
return 'video'
@staticmethod @staticmethod
def from_string(type_string): def from_string(type_string):
@ -72,6 +75,8 @@ class BackgroundType(object):
return BackgroundType.Image return BackgroundType.Image
elif type_string == 'transparent': elif type_string == 'transparent':
return BackgroundType.Transparent return BackgroundType.Transparent
elif type_string == 'video':
return BackgroundType.Video
class BackgroundGradientType(object): class BackgroundGradientType(object):
@ -184,7 +189,7 @@ class ThemeXML(object):
:param path: The path name to be added. :param path: The path name to be added.
""" """
if self.background_type == 'image': if self.background_type == 'image' or self.background_type == 'video':
if self.background_filename and path: if self.background_filename and path:
self.theme_name = self.theme_name.strip() self.theme_name = self.theme_name.strip()
self.background_filename = self.background_filename.strip() self.background_filename = self.background_filename.strip()
@ -255,6 +260,21 @@ class ThemeXML(object):
# Create endColor element # Create endColor element
self.child_element(background, 'borderColor', str(border_color)) self.child_element(background, 'borderColor', str(border_color))
def add_background_video(self, filename, border_color):
"""
Add a video background.
:param filename: The file name of the video.
:param border_color:
"""
background = self.theme_xml.createElement('background')
background.setAttribute('type', 'video')
self.theme.appendChild(background)
# Create Filename element
self.child_element(background, 'filename', filename)
# Create endColor element
self.child_element(background, 'borderColor', str(border_color))
def add_font(self, name, color, size, override, fonttype='main', bold='False', italics='False', def add_font(self, name, color, size, override, fonttype='main', bold='False', italics='False',
line_adjustment=0, xpos=0, ypos=0, width=0, height=0, outline='False', outline_color='#ffffff', line_adjustment=0, xpos=0, ypos=0, width=0, height=0, outline='False', outline_color='#ffffff',
outline_pixel=2, shadow='False', shadow_color='#ffffff', shadow_pixel=5): outline_pixel=2, shadow='False', shadow_color='#ffffff', shadow_pixel=5):
@ -512,6 +532,9 @@ class ThemeXML(object):
elif self.background_type == BackgroundType.to_string(BackgroundType.Image): elif self.background_type == BackgroundType.to_string(BackgroundType.Image):
filename = os.path.split(self.background_filename)[1] filename = os.path.split(self.background_filename)[1]
self.add_background_image(filename, self.background_border_color) self.add_background_image(filename, self.background_border_color)
elif self.background_type == BackgroundType.to_string(BackgroundType.Video):
filename = os.path.split(self.background_filename)[1]
self.add_background_video(filename, self.background_border_color)
elif self.background_type == BackgroundType.to_string(BackgroundType.Transparent): elif self.background_type == BackgroundType.to_string(BackgroundType.Transparent):
self.add_background_transparent() self.add_background_transparent()
self.add_font( self.add_font(

View File

@ -31,13 +31,15 @@ Some of the code for this form is based on the examples at:
import html import html
import logging import logging
import os
from PyQt5 import QtCore, QtWidgets, QtWebKit, QtWebKitWidgets, QtOpenGL, QtGui, QtMultimedia from PyQt5 import QtCore, QtWidgets, QtWebKit, QtWebKitWidgets, QtOpenGL, QtGui, QtMultimedia
from openlp.core.common import Registry, RegistryProperties, OpenLPMixin, Settings, translate, is_macosx, is_win from openlp.core.common import AppLocation, Registry, RegistryProperties, OpenLPMixin, Settings, translate,\
is_macosx, is_win
from openlp.core.lib import ServiceItem, ImageSource, ScreenList, build_html, expand_tags, image_to_byte from openlp.core.lib import ServiceItem, ImageSource, ScreenList, build_html, expand_tags, image_to_byte
from openlp.core.lib.theme import BackgroundType from openlp.core.lib.theme import BackgroundType
from openlp.core.ui import HideMode, AlertLocation from openlp.core.ui import HideMode, AlertLocation, DisplayControllerType
if is_macosx(): if is_macosx():
from ctypes import pythonapi, c_void_p, c_char_p, py_object from ctypes import pythonapi, c_void_p, c_char_p, py_object
@ -459,13 +461,13 @@ class MainDisplay(OpenLPMixin, Display, RegistryProperties):
background = self.image_manager.get_image_bytes(self.override['image'], ImageSource.ImagePlugin) background = self.image_manager.get_image_bytes(self.override['image'], ImageSource.ImagePlugin)
self.set_transparency(self.service_item.theme_data.background_type == self.set_transparency(self.service_item.theme_data.background_type ==
BackgroundType.to_string(BackgroundType.Transparent)) BackgroundType.to_string(BackgroundType.Transparent))
image_bytes = None
if self.service_item.theme_data.background_type == 'image':
if self.service_item.theme_data.background_filename: if self.service_item.theme_data.background_filename:
self.service_item.bg_image_bytes = self.image_manager.get_image_bytes( self.service_item.bg_image_bytes = self.image_manager.get_image_bytes(
self.service_item.theme_data.background_filename, ImageSource.Theme) self.service_item.theme_data.background_filename, ImageSource.Theme)
if image_path: if image_path:
image_bytes = self.image_manager.get_image_bytes(image_path, ImageSource.ImagePlugin) image_bytes = self.image_manager.get_image_bytes(image_path, ImageSource.ImagePlugin)
else:
image_bytes = None
html = build_html(self.service_item, self.screen, self.is_live, background, image_bytes, html = build_html(self.service_item, self.screen, self.is_live, background, image_bytes,
plugins=self.plugin_manager.plugins) plugins=self.plugin_manager.plugins)
self.web_view.setHtml(html) self.web_view.setHtml(html)
@ -477,6 +479,17 @@ class MainDisplay(OpenLPMixin, Display, RegistryProperties):
Registry().execute('slidecontroller_live_unblank') Registry().execute('slidecontroller_live_unblank')
else: else:
self.hide_display(self.hide_mode) self.hide_display(self.hide_mode)
if self.service_item.theme_data.background_type == 'video' and self.is_live:
if self.service_item.theme_data.background_filename:
service_item = ServiceItem()
service_item.title = 'webkit'
service_item.processor = 'webkit'
path = os.path.join(AppLocation.get_section_data_path('themes'),
self.service_item.theme_data.theme_name)
service_item.add_from_command(path,
self.service_item.theme_data.background_filename,
':/media/slidecontroller_multimedia.png')
self.media_controller.video(DisplayControllerType.Live, service_item, video_behind_text=True)
self._hide_mouse() self._hide_mouse()
def footer(self, text): def footer(self, text):

View File

@ -83,7 +83,7 @@ def get_media_players():
reg_ex = QtCore.QRegExp(".*\[(.*)\].*") reg_ex = QtCore.QRegExp(".*\[(.*)\].*")
if Settings().value('media/override player') == QtCore.Qt.Checked: if Settings().value('media/override player') == QtCore.Qt.Checked:
if reg_ex.exactMatch(saved_players): if reg_ex.exactMatch(saved_players):
overridden_player = '%s' % reg_ex.cap(1) overridden_player = '{text}'.format(text=reg_ex.cap(1))
else: else:
overridden_player = 'auto' overridden_player = 'auto'
else: else:
@ -102,7 +102,7 @@ def set_media_players(players_list, overridden_player='auto'):
log.debug('set_media_players') log.debug('set_media_players')
players = ','.join(players_list) players = ','.join(players_list)
if Settings().value('media/override player') == QtCore.Qt.Checked and overridden_player != 'auto': if Settings().value('media/override player') == QtCore.Qt.Checked and overridden_player != 'auto':
players = players.replace(overridden_player, '[%s]' % overridden_player) players = players.replace(overridden_player, '[{text}]'.format(text=overridden_player))
Settings().setValue('media/players', players) Settings().setValue('media/players', players)
@ -113,7 +113,7 @@ def parse_optical_path(input_string):
:param input_string: The string to parse :param input_string: The string to parse
:return: The elements extracted from the string: filename, title, audio_track, subtitle_track, start, end :return: The elements extracted from the string: filename, title, audio_track, subtitle_track, start, end
""" """
log.debug('parse_optical_path, about to parse: "%s"' % input_string) log.debug('parse_optical_path, about to parse: "{text}"'.format(text=input_string))
clip_info = input_string.split(sep=':') clip_info = input_string.split(sep=':')
title = int(clip_info[1]) title = int(clip_info[1])
audio_track = int(clip_info[2]) audio_track = int(clip_info[2])
@ -137,7 +137,10 @@ def format_milliseconds(milliseconds):
seconds, millis = divmod(milliseconds, 1000) seconds, millis = divmod(milliseconds, 1000)
minutes, seconds = divmod(seconds, 60) minutes, seconds = divmod(seconds, 60)
hours, minutes = divmod(minutes, 60) hours, minutes = divmod(minutes, 60)
return "%02d:%02d:%02d,%03d" % (hours, minutes, seconds, millis) return "{hours:02d}:{minutes:02d}:{seconds:02d},{millis:03d}".format(hours=hours,
minutes=minutes,
seconds=seconds,
millis=millis)
from .mediacontroller import MediaController from .mediacontroller import MediaController
from .playertab import PlayerTab from .playertab import PlayerTab

View File

@ -45,7 +45,7 @@ VIDEO_CSS = """
""" """
VIDEO_JS = """ VIDEO_JS = """
function show_video(state, path, volume, loop, variable_value){ function show_video(state, path, volume, variable_value){
// Sometimes video.currentTime stops slightly short of video.duration and video.ended is intermittent! // Sometimes video.currentTime stops slightly short of video.duration and video.ended is intermittent!
var video = document.getElementById('video'); var video = document.getElementById('video');
@ -55,9 +55,6 @@ VIDEO_JS = """
switch(state){ switch(state){
case 'load': case 'load':
video.src = 'file:///' + path; video.src = 'file:///' + path;
if(loop == true) {
video.loop = true;
}
video.load(); video.load();
break; break;
case 'play': case 'play':
@ -180,12 +177,8 @@ class WebkitPlayer(MediaPlayer):
else: else:
vol = 0 vol = 0
path = controller.media_info.file_info.absoluteFilePath() path = controller.media_info.file_info.absoluteFilePath()
if controller.media_info.is_background:
loop = 'true'
else:
loop = 'false'
display.web_view.setVisible(True) display.web_view.setVisible(True)
js = 'show_video("load", "%s", %s, %s);' % (path.replace('\\', '\\\\'), str(vol), loop) js = 'show_video("load", "{path}", {vol});'.format(path=path.replace('\\', '\\\\'), vol=str(vol))
display.frame.evaluateJavaScript(js) display.frame.evaluateJavaScript(js)
return True return True

View File

@ -1323,7 +1323,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtWidgets.QWidget, Ui_ServiceMa
""" """
The theme may have changed in the settings dialog so make sure the theme combo box is in the correct state. The theme may have changed in the settings dialog so make sure the theme combo box is in the correct state.
""" """
visible = self.renderer.theme_level == ThemeLevel.Global visible = not self.renderer.theme_level == ThemeLevel.Global
self.theme_label.setVisible(visible) self.theme_label.setVisible(visible)
self.theme_combo_box.setVisible(visible) self.theme_combo_box.setVisible(visible)

View File

@ -31,7 +31,7 @@ from openlp.core.common import Registry, RegistryProperties, UiStrings, translat
from openlp.core.lib.theme import BackgroundType, BackgroundGradientType from openlp.core.lib.theme import BackgroundType, BackgroundGradientType
from openlp.core.lib.ui import critical_error_message_box from openlp.core.lib.ui import critical_error_message_box
from openlp.core.ui import ThemeLayoutForm from openlp.core.ui import ThemeLayoutForm
from openlp.core.ui.lib.colorbutton import ColorButton from openlp.core.ui.media.webkitplayer import VIDEO_EXT
from .themewizard import Ui_ThemeWizard from .themewizard import Ui_ThemeWizard
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -66,10 +66,13 @@ class ThemeForm(QtWidgets.QWizard, Ui_ThemeWizard, RegistryProperties):
self.gradient_combo_box.currentIndexChanged.connect(self.on_gradient_combo_box_current_index_changed) self.gradient_combo_box.currentIndexChanged.connect(self.on_gradient_combo_box_current_index_changed)
self.color_button.colorChanged.connect(self.on_color_changed) self.color_button.colorChanged.connect(self.on_color_changed)
self.image_color_button.colorChanged.connect(self.on_image_color_changed) self.image_color_button.colorChanged.connect(self.on_image_color_changed)
self.video_color_button.colorChanged.connect(self.on_video_color_changed)
self.gradient_start_button.colorChanged.connect(self.on_gradient_start_color_changed) self.gradient_start_button.colorChanged.connect(self.on_gradient_start_color_changed)
self.gradient_end_button.colorChanged.connect(self.on_gradient_end_color_changed) self.gradient_end_button.colorChanged.connect(self.on_gradient_end_color_changed)
self.image_browse_button.clicked.connect(self.on_image_browse_button_clicked) self.image_browse_button.clicked.connect(self.on_image_browse_button_clicked)
self.image_file_edit.editingFinished.connect(self.on_image_file_edit_editing_finished) self.image_file_edit.editingFinished.connect(self.on_image_file_edit_editing_finished)
self.video_browse_button.clicked.connect(self.on_video_browse_button_clicked)
self.video_file_edit.editingFinished.connect(self.on_video_file_edit_editing_finished)
self.main_color_button.colorChanged.connect(self.on_main_color_changed) self.main_color_button.colorChanged.connect(self.on_main_color_changed)
self.outline_color_button.colorChanged.connect(self.on_outline_color_changed) self.outline_color_button.colorChanged.connect(self.on_outline_color_changed)
self.shadow_color_button.colorChanged.connect(self.on_shadow_color_changed) self.shadow_color_button.colorChanged.connect(self.on_shadow_color_changed)
@ -307,6 +310,10 @@ class ThemeForm(QtWidgets.QWizard, Ui_ThemeWizard, RegistryProperties):
self.image_color_button.color = self.theme.background_border_color self.image_color_button.color = self.theme.background_border_color
self.image_file_edit.setText(self.theme.background_filename) self.image_file_edit.setText(self.theme.background_filename)
self.setField('background_type', 2) self.setField('background_type', 2)
elif self.theme.background_type == BackgroundType.to_string(BackgroundType.Video):
self.video_color_button.color = self.theme.background_border_color
self.video_file_edit.setText(self.theme.background_filename)
self.setField('background_type', 4)
elif self.theme.background_type == BackgroundType.to_string(BackgroundType.Transparent): elif self.theme.background_type == BackgroundType.to_string(BackgroundType.Transparent):
self.setField('background_type', 3) self.setField('background_type', 3)
if self.theme.background_direction == BackgroundGradientType.to_string(BackgroundGradientType.Horizontal): if self.theme.background_direction == BackgroundGradientType.to_string(BackgroundGradientType.Horizontal):
@ -384,10 +391,12 @@ class ThemeForm(QtWidgets.QWizard, Ui_ThemeWizard, RegistryProperties):
if self.update_theme_allowed: if self.update_theme_allowed:
self.theme.background_type = BackgroundType.to_string(index) self.theme.background_type = BackgroundType.to_string(index)
if self.theme.background_type != BackgroundType.to_string(BackgroundType.Image) and \ if self.theme.background_type != BackgroundType.to_string(BackgroundType.Image) and \
self.theme.background_type != BackgroundType.to_string(BackgroundType.Video) and \
self.temp_background_filename == '': self.temp_background_filename == '':
self.temp_background_filename = self.theme.background_filename self.temp_background_filename = self.theme.background_filename
self.theme.background_filename = '' self.theme.background_filename = ''
if self.theme.background_type == BackgroundType.to_string(BackgroundType.Image) and \ if (self.theme.background_type == BackgroundType.to_string(BackgroundType.Image) or
self.theme.background_type != BackgroundType.to_string(BackgroundType.Video)) and \
self.temp_background_filename != '': self.temp_background_filename != '':
self.theme.background_filename = self.temp_background_filename self.theme.background_filename = self.temp_background_filename
self.temp_background_filename = '' self.temp_background_filename = ''
@ -413,6 +422,12 @@ class ThemeForm(QtWidgets.QWizard, Ui_ThemeWizard, RegistryProperties):
""" """
self.theme.background_border_color = color self.theme.background_border_color = color
def on_video_color_changed(self, color):
"""
Background / Gradient 1 _color button pushed.
"""
self.theme.background_border_color = color
def on_gradient_start_color_changed(self, color): def on_gradient_start_color_changed(self, color):
""" """
Gradient 2 _color button pushed. Gradient 2 _color button pushed.
@ -444,6 +459,28 @@ class ThemeForm(QtWidgets.QWizard, Ui_ThemeWizard, RegistryProperties):
""" """
self.theme.background_filename = str(self.image_file_edit.text()) self.theme.background_filename = str(self.image_file_edit.text())
def on_video_browse_button_clicked(self):
"""
Background video button pushed.
"""
visible_formats = '(%s)' % '; '.join(VIDEO_EXT)
actual_formats = '(%s)' % ' '.join(VIDEO_EXT)
video_filter = '{trans} {visible} {actual}'.format(trans=translate('OpenLP', 'Video Files'),
visible=visible_formats, actual=actual_formats)
video_filter = '{video};;{ui} (*.*)'.format(video=video_filter, ui=UiStrings().AllFiles)
filename, filter_used = QtWidgets.QFileDialog.getOpenFileName(
self, translate('OpenLP.ThemeWizard', 'Select Video'),
self.video_file_edit.text(), video_filter)
if filename:
self.theme.background_filename = filename
self.set_background_page_values()
def on_video_file_edit_editing_finished(self):
"""
Background video path edited
"""
self.theme.background_filename = str(self.image_file_edit.text())
def on_main_color_changed(self, color): def on_main_color_changed(self, color):
""" """
Set the main colour value Set the main colour value
@ -519,7 +556,8 @@ class ThemeForm(QtWidgets.QWizard, Ui_ThemeWizard, RegistryProperties):
return return
save_from = None save_from = None
save_to = None save_to = None
if self.theme.background_type == BackgroundType.to_string(BackgroundType.Image): if self.theme.background_type == BackgroundType.to_string(BackgroundType.Image) or \
self.theme.background_type == BackgroundType.to_string(BackgroundType.Video):
filename = os.path.split(str(self.theme.background_filename))[1] filename = os.path.split(str(self.theme.background_filename))[1]
save_to = os.path.join(self.path, self.theme.theme_name, filename) save_to = os.path.join(self.path, self.theme.theme_name, filename)
save_from = self.theme.background_filename save_from = self.theme.background_filename

View File

@ -300,7 +300,7 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtWidgets.QWidget, Ui_ThemeManage
""" """
save_to = None save_to = None
save_from = None save_from = None
if theme_data.background_type == 'image': if theme_data.background_type == 'image' or theme_data.background_type == 'video':
save_to = os.path.join(self.path, new_theme_name, os.path.split(str(theme_data.background_filename))[1]) save_to = os.path.join(self.path, new_theme_name, os.path.split(str(theme_data.background_filename))[1])
save_from = theme_data.background_filename save_from = theme_data.background_filename
theme_data.theme_name = new_theme_name theme_data.theme_name = new_theme_name
@ -318,7 +318,7 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtWidgets.QWidget, Ui_ThemeManage
translate('OpenLP.ThemeManager', 'You must select a theme to edit.')): translate('OpenLP.ThemeManager', 'You must select a theme to edit.')):
item = self.theme_list_widget.currentItem() item = self.theme_list_widget.currentItem()
theme = self.get_theme_data(item.data(QtCore.Qt.UserRole)) theme = self.get_theme_data(item.data(QtCore.Qt.UserRole))
if theme.background_type == 'image': if theme.background_type == 'image' or theme.background_type == 'video':
self.old_background_image = theme.background_filename self.old_background_image = theme.background_filename
self.theme_form.theme = theme self.theme_form.theme = theme
self.theme_form.exec(True) self.theme_form.exec(True)

View File

@ -62,7 +62,7 @@ class Ui_ThemeWizard(object):
self.background_label = QtWidgets.QLabel(self.background_page) self.background_label = QtWidgets.QLabel(self.background_page)
self.background_label.setObjectName('background_label') self.background_label.setObjectName('background_label')
self.background_combo_box = QtWidgets.QComboBox(self.background_page) self.background_combo_box = QtWidgets.QComboBox(self.background_page)
self.background_combo_box.addItems(['', '', '', '']) self.background_combo_box.addItems(['', '', '', '', ''])
self.background_combo_box.setObjectName('background_combo_box') self.background_combo_box.setObjectName('background_combo_box')
self.background_type_layout.addRow(self.background_label, self.background_combo_box) self.background_type_layout.addRow(self.background_label, self.background_combo_box)
self.background_type_layout.setItem(1, QtWidgets.QFormLayout.LabelRole, self.spacer) self.background_type_layout.setItem(1, QtWidgets.QFormLayout.LabelRole, self.spacer)
@ -135,6 +135,30 @@ class Ui_ThemeWizard(object):
self.transparent_layout.setObjectName('Transparent_layout') self.transparent_layout.setObjectName('Transparent_layout')
self.background_stack.addWidget(self.transparent_widget) self.background_stack.addWidget(self.transparent_widget)
self.background_layout.addLayout(self.background_stack) self.background_layout.addLayout(self.background_stack)
self.video_widget = QtWidgets.QWidget(self.background_page)
self.video_widget.setObjectName('video_widget')
self.video_layout = QtWidgets.QFormLayout(self.video_widget)
self.video_layout.setContentsMargins(0, 0, 0, 0)
self.video_layout.setObjectName('video_layout')
self.video_color_label = QtWidgets.QLabel(self.color_widget)
self.video_color_label.setObjectName('video_color_label')
self.video_color_button = ColorButton(self.color_widget)
self.video_color_button.setObjectName('video_color_button')
self.video_layout.addRow(self.video_color_label, self.video_color_button)
self.video_label = QtWidgets.QLabel(self.video_widget)
self.video_label.setObjectName('video_label')
self.video_file_layout = QtWidgets.QHBoxLayout()
self.video_file_layout.setObjectName('video_file_layout')
self.video_file_edit = QtWidgets.QLineEdit(self.video_widget)
self.video_file_edit.setObjectName('video_file_edit')
self.video_file_layout.addWidget(self.video_file_edit)
self.video_browse_button = QtWidgets.QToolButton(self.video_widget)
self.video_browse_button.setObjectName('video_browse_button')
self.video_browse_button.setIcon(build_icon(':/general/general_open.png'))
self.video_file_layout.addWidget(self.video_browse_button)
self.video_layout.addRow(self.video_label, self.video_file_layout)
self.video_layout.setItem(2, QtWidgets.QFormLayout.LabelRole, self.spacer)
self.background_stack.addWidget(self.video_widget)
theme_wizard.addPage(self.background_page) theme_wizard.addPage(self.background_page)
# Main Area Page # Main Area Page
self.main_area_page = QtWidgets.QWizardPage() self.main_area_page = QtWidgets.QWizardPage()
@ -390,11 +414,10 @@ class Ui_ThemeWizard(object):
self.background_page.setSubTitle(translate('OpenLP.ThemeWizard', 'Set up your theme\'s background ' self.background_page.setSubTitle(translate('OpenLP.ThemeWizard', 'Set up your theme\'s background '
'according to the parameters below.')) 'according to the parameters below.'))
self.background_label.setText(translate('OpenLP.ThemeWizard', 'Background type:')) self.background_label.setText(translate('OpenLP.ThemeWizard', 'Background type:'))
self.background_combo_box.setItemText(BackgroundType.Solid, self.background_combo_box.setItemText(BackgroundType.Solid, translate('OpenLP.ThemeWizard', 'Solid color'))
translate('OpenLP.ThemeWizard', 'Solid color')) self.background_combo_box.setItemText(BackgroundType.Gradient, translate('OpenLP.ThemeWizard', 'Gradient'))
self.background_combo_box.setItemText(BackgroundType.Gradient,
translate('OpenLP.ThemeWizard', 'Gradient'))
self.background_combo_box.setItemText(BackgroundType.Image, UiStrings().Image) self.background_combo_box.setItemText(BackgroundType.Image, UiStrings().Image)
self.background_combo_box.setItemText(BackgroundType.Video, UiStrings().Video)
self.background_combo_box.setItemText(BackgroundType.Transparent, self.background_combo_box.setItemText(BackgroundType.Transparent,
translate('OpenLP.ThemeWizard', 'Transparent')) translate('OpenLP.ThemeWizard', 'Transparent'))
self.color_label.setText(translate('OpenLP.ThemeWizard', 'color:')) self.color_label.setText(translate('OpenLP.ThemeWizard', 'color:'))
@ -413,6 +436,8 @@ class Ui_ThemeWizard(object):
translate('OpenLP.ThemeWizard', 'Bottom Left - Top Right')) translate('OpenLP.ThemeWizard', 'Bottom Left - Top Right'))
self.image_color_label.setText(translate('OpenLP.ThemeWizard', 'Background color:')) self.image_color_label.setText(translate('OpenLP.ThemeWizard', 'Background color:'))
self.image_label.setText('%s:' % UiStrings().Image) self.image_label.setText('%s:' % UiStrings().Image)
self.video_color_label.setText(translate('OpenLP.ThemeWizard', 'Background color:'))
self.video_label.setText('%s:' % UiStrings().Video)
self.main_area_page.setTitle(translate('OpenLP.ThemeWizard', 'Main Area Font Details')) self.main_area_page.setTitle(translate('OpenLP.ThemeWizard', 'Main Area Font Details'))
self.main_area_page.setSubTitle(translate('OpenLP.ThemeWizard', 'Define the font and display ' self.main_area_page.setSubTitle(translate('OpenLP.ThemeWizard', 'Define the font and display '
'characteristics for the Display text')) 'characteristics for the Display text'))

View File

@ -211,19 +211,21 @@ def update_reference_separators():
while '||' in source_string: while '||' in source_string:
source_string = source_string.replace('||', '|') source_string = source_string.replace('||', '|')
if role != 'e': if role != 'e':
REFERENCE_SEPARATORS['sep_%s_display' % role] = source_string.split('|')[0] REFERENCE_SEPARATORS['sep_{role}_display'.format(role=role)] = source_string.split('|')[0]
# escape reserved characters # escape reserved characters
for character in '\\.^$*+?{}[]()': for character in '\\.^$*+?{}[]()':
source_string = source_string.replace(character, '\\' + character) source_string = source_string.replace(character, '\\' + character)
# add various unicode alternatives # add various unicode alternatives
source_string = source_string.replace('-', '(?:[-\u00AD\u2010\u2011\u2012\u2014\u2014\u2212\uFE63\uFF0D])') source_string = source_string.replace('-', '(?:[-\u00AD\u2010\u2011\u2012\u2014\u2014\u2212\uFE63\uFF0D])')
source_string = source_string.replace(',', '(?:[,\u201A])') source_string = source_string.replace(',', '(?:[,\u201A])')
REFERENCE_SEPARATORS['sep_%s' % role] = '\s*(?:%s)\s*' % source_string REFERENCE_SEPARATORS['sep_{role}'.format(role=role)] = '\s*(?:{source})\s*'.format(source=source_string)
REFERENCE_SEPARATORS['sep_%s_default' % role] = default_separators[index] REFERENCE_SEPARATORS['sep_{role}_default'.format(role=role)] = default_separators[index]
# verse range match: (<chapter>:)?<verse>(-((<chapter>:)?<verse>|end)?)? # verse range match: (<chapter>:)?<verse>(-((<chapter>:)?<verse>|end)?)?
# TODO: Check before converting this string
range_regex = '(?:(?P<from_chapter>[0-9]+)%(sep_v)s)?' \ range_regex = '(?:(?P<from_chapter>[0-9]+)%(sep_v)s)?' \
'(?P<from_verse>[0-9]+)(?P<range_to>%(sep_r)s(?:(?:(?P<to_chapter>' \ '(?P<from_verse>[0-9]+)(?P<range_to>%(sep_r)s(?:(?:(?P<to_chapter>' \
'[0-9]+)%(sep_v)s)?(?P<to_verse>[0-9]+)|%(sep_e)s)?)?' % REFERENCE_SEPARATORS '[0-9]+)%(sep_v)s)?(?P<to_verse>[0-9]+)|%(sep_e)s)?)?' % REFERENCE_SEPARATORS
# TODO: Test before converting re.compile strings
REFERENCE_MATCHES['range'] = re.compile('^\s*%s\s*$' % range_regex, re.UNICODE) REFERENCE_MATCHES['range'] = re.compile('^\s*%s\s*$' % range_regex, re.UNICODE)
REFERENCE_MATCHES['range_separator'] = re.compile(REFERENCE_SEPARATORS['sep_l'], re.UNICODE) REFERENCE_MATCHES['range_separator'] = re.compile(REFERENCE_SEPARATORS['sep_l'], re.UNICODE)
# full reference match: <book>(<range>(,(?!$)|(?=$)))+ # full reference match: <book>(<range>(,(?!$)|(?=$)))+
@ -331,10 +333,10 @@ def parse_reference(reference, bible, language_selection, book_ref_id=False):
separator. separator.
""" """
log.debug('parse_reference("%s")', reference) log.debug('parse_reference("{text}")'.format(text=reference))
match = get_reference_match('full').match(reference) match = get_reference_match('full').match(reference)
if match: if match:
log.debug('Matched reference %s' % reference) log.debug('Matched reference {text}'.format(text=reference))
book = match.group('book') book = match.group('book')
if not book_ref_id: if not book_ref_id:
book_ref_id = bible.get_book_ref_id_by_localised_name(book, language_selection) book_ref_id = bible.get_book_ref_id_by_localised_name(book, language_selection)
@ -400,7 +402,7 @@ def parse_reference(reference, bible, language_selection, book_ref_id=False):
ref_list.append((book_ref_id, from_chapter, 1, -1)) ref_list.append((book_ref_id, from_chapter, 1, -1))
return ref_list return ref_list
else: else:
log.debug('Invalid reference: %s' % reference) log.debug('Invalid reference: {text}'.format(text=reference))
return None return None

View File

@ -669,6 +669,8 @@ class BibleMediaItem(MediaManagerItem):
second_bible = self.quickSecondComboBox.currentText() second_bible = self.quickSecondComboBox.currentText()
# Get input from field and replace 'A-Z + . ' with '' # Get input from field and replace 'A-Z + . ' with ''
# This will check if field has any '.' after A-Z and removes them. Eg. Gen. 1 = Gen 1 = Genesis 1 # This will check if field has any '.' after A-Z and removes them. Eg. Gen. 1 = Gen 1 = Genesis 1
# If Book name has '.' after number. eg. 1. Genesis, the search fails without the dot, and vice versa.
# A better solution would be to make '.' optional in the search results. Current solution was easier to code.
text = self.quick_search_edit.text() text = self.quick_search_edit.text()
text = re.sub('\D[.]\s', ' ', text) text = re.sub('\D[.]\s', ' ', text)
# This is triggered on reference search, use the search from manager.py # This is triggered on reference search, use the search from manager.py
@ -730,6 +732,7 @@ class BibleMediaItem(MediaManagerItem):
""" """
log.debug('Quick Search Button clicked') log.debug('Quick Search Button clicked')
# If we are performing "Search while typing", this setting is set to True, here it's reset to "False" # If we are performing "Search while typing", this setting is set to True, here it's reset to "False"
if Settings().Value('bibles/hide web bible error if searching while typing'):
Settings().setValue('bibles/hide web bible error if searching while typing', False) Settings().setValue('bibles/hide web bible error if searching while typing', False)
self.quickSearchButton.setEnabled(False) self.quickSearchButton.setEnabled(False)
self.application.process_events() self.application.process_events()
@ -811,6 +814,7 @@ class BibleMediaItem(MediaManagerItem):
""" """
This function is called when "Search as you type" is enabled for Bibles. This function is called when "Search as you type" is enabled for Bibles.
It is basically the same thing as "on_quick_search_search" but all the error messages are removed. It is basically the same thing as "on_quick_search_search" but all the error messages are removed.
This also has increased min len for text search for performance reasons.
For commented version, please visit def on_quick_search_button. For commented version, please visit def on_quick_search_button.
""" """
bible = self.quickVersionComboBox.currentText() bible = self.quickVersionComboBox.currentText()
@ -858,14 +862,14 @@ class BibleMediaItem(MediaManagerItem):
This would result in seeing the same message multiple times. This would result in seeing the same message multiple times.
This message is located in lib\manager.py, so the setting is required. This message is located in lib\manager.py, so the setting is required.
""" """
if Settings().value('bibles/is search while typing enabled'):
Settings().setValue('bibles/hide web bible error if searching while typing', True) Settings().setValue('bibles/hide web bible error if searching while typing', True)
# Regex for finding space + any non whitemark character. (Prevents search from starting on 1 word searches) # Regex for finding space + any non whitemark character. (Prevents search from starting on 1 word searches)
space_and_any = re.compile(' \S') space_and_any = re.compile(' \S')
# Turn this into a format that may be used in if statement. # Turn this into a format that may be used in if statement.
count_space_any = space_and_any.findall(text) count_space_any = space_and_any.findall(text)
# Start searching if this behaviour is not disabled in settings and conditions are met. # Start searching if this behaviour is not disabled in settings and conditions are met.
if Settings().value('bibles/is search while typing enabled'): # If text does not have 'count_space_any' and results are not locked, clear the results.
# If text length is less than the mininum and results are not locked, clear the results.
if len(count_space_any) == 0: if len(count_space_any) == 0:
if not self.quickLockButton.isChecked(): if not self.quickLockButton.isChecked():
self.list_view.clear() self.list_view.clear()

View File

@ -60,7 +60,7 @@ import webbrowser
from PyQt5 import QtCore from PyQt5 import QtCore
from lxml import etree, objectify from lxml import etree, objectify
SERVER_URL = 'http://www.transifex.net/api/2/project/openlp/resource/openlp-24x/' SERVER_URL = 'http://www.transifex.com/api/2/project/openlp/resource/openlp-26x/'
IGNORED_PATHS = ['scripts'] IGNORED_PATHS = ['scripts']
IGNORED_FILES = ['setup.py'] IGNORED_FILES = ['setup.py']
@ -270,7 +270,7 @@ def update_translations():
return return
else: else:
os.chdir(os.path.abspath('..')) os.chdir(os.path.abspath('..'))
run('pylupdate4 -verbose -noobsolete openlp.pro') run('pylupdate5 -verbose -noobsolete openlp.pro')
os.chdir(os.path.abspath('scripts')) os.chdir(os.path.abspath('scripts'))

View File

@ -26,7 +26,8 @@ Package to test the openlp.core.lib.projector.pjlink1 package.
from unittest import TestCase from unittest import TestCase
from openlp.core.lib.projector.pjlink1 import PJLink1 from openlp.core.lib.projector.pjlink1 import PJLink1
from openlp.core.lib.projector.constants import E_PARAMETER, ERROR_STRING from openlp.core.lib.projector.constants import E_PARAMETER, ERROR_STRING, S_OFF, S_STANDBY, S_WARMUP, S_ON, \
S_COOLDOWN, PJLINK_POWR_STATUS
from tests.functional import patch from tests.functional import patch
from tests.resources.projector.data import TEST_PIN, TEST_SALT, TEST_CONNECT_AUTHENTICATE from tests.resources.projector.data import TEST_PIN, TEST_SALT, TEST_CONNECT_AUTHENTICATE
@ -151,3 +152,33 @@ class TestPJLink(TestCase):
'Lamp 3 power status should have been set to TRUE') 'Lamp 3 power status should have been set to TRUE')
self.assertEquals(pjlink.lamp[2]['Hours'], 33333, self.assertEquals(pjlink.lamp[2]['Hours'], 33333,
'Lamp 3 hours should have been set to 33333') 'Lamp 3 hours should have been set to 33333')
@patch.object(pjlink_test, 'projectorReceivedData')
def projector_process_power_on_test(self, mock_projectorReceivedData):
"""
Test setting power to ON
"""
# GIVEN: Test object and preset
pjlink = pjlink_test
pjlink.power = S_STANDBY
# WHEN: Call process_command with turn power on command
pjlink.process_command('POWR', PJLINK_POWR_STATUS[S_ON])
# THEN: Power should be set to ON
self.assertEquals(pjlink.power, S_ON, 'Power should have been set to ON')
@patch.object(pjlink_test, 'projectorReceivedData')
def projector_process_power_off_test(self, mock_projectorReceivedData):
"""
Test setting power to STANDBY
"""
# GIVEN: Test object and preset
pjlink = pjlink_test
pjlink.power = S_ON
# WHEN: Call process_command with turn power on command
pjlink.process_command('POWR', PJLINK_POWR_STATUS[S_STANDBY])
# THEN: Power should be set to STANDBY
self.assertEquals(pjlink.power, S_STANDBY, 'Power should have been set to STANDBY')

View File

@ -27,8 +27,9 @@ from unittest import TestCase, skipUnless
from PyQt5 import QtCore from PyQt5 import QtCore
from openlp.core.common import Registry, is_macosx, Settings from openlp.core.common import Registry, is_macosx, Settings
from openlp.core.lib import ScreenList from openlp.core.lib import ScreenList, PluginManager
from openlp.core.ui import MainDisplay from openlp.core.ui import MainDisplay
from openlp.core.ui.media import MediaController
from openlp.core.ui.maindisplay import TRANSPARENT_STYLESHEET, OPAQUE_STYLESHEET from openlp.core.ui.maindisplay import TRANSPARENT_STYLESHEET, OPAQUE_STYLESHEET
from tests.helpers.testmixin import TestMixin from tests.helpers.testmixin import TestMixin
@ -223,3 +224,61 @@ class TestMainDisplay(TestCase, TestMixin):
# THEN: setVisible should had not been called # THEN: setVisible should had not been called
main_display.setVisible.assert_not_called() main_display.setVisible.assert_not_called()
@patch(u'openlp.core.ui.maindisplay.Settings')
@patch(u'openlp.core.ui.maindisplay.build_html')
def build_html_no_video_test(self, MockedSettings, Mocked_build_html):
# GIVEN: Mocked display
display = MagicMock()
mocked_media_controller = MagicMock()
Registry.create()
Registry().register('media_controller', mocked_media_controller)
main_display = MainDisplay(display)
main_display.frame = MagicMock()
mocked_settings = MagicMock()
mocked_settings.value.return_value = False
MockedSettings.return_value = mocked_settings
main_display.shake_web_view = MagicMock()
service_item = MagicMock()
mocked_plugin = MagicMock()
display.plugin_manager = PluginManager()
display.plugin_manager.plugins = [mocked_plugin]
main_display.web_view = MagicMock()
# WHEN: build_html is called with a normal service item and a non video theme.
main_display.build_html(service_item)
# THEN: the following should had not been called
self.assertEquals(main_display.web_view.setHtml.call_count, 1, 'setHTML should be called once')
self.assertEquals(main_display.media_controller.video.call_count, 0,
'Media Controller video should not have been called')
@patch(u'openlp.core.ui.maindisplay.Settings')
@patch(u'openlp.core.ui.maindisplay.build_html')
def build_html_video_test(self, MockedSettings, Mocked_build_html):
# GIVEN: Mocked display
display = MagicMock()
mocked_media_controller = MagicMock()
Registry.create()
Registry().register('media_controller', mocked_media_controller)
main_display = MainDisplay(display)
main_display.frame = MagicMock()
mocked_settings = MagicMock()
mocked_settings.value.return_value = False
MockedSettings.return_value = mocked_settings
main_display.shake_web_view = MagicMock()
service_item = MagicMock()
service_item.theme_data = MagicMock()
service_item.theme_data.background_type = 'video'
mocked_plugin = MagicMock()
display.plugin_manager = PluginManager()
display.plugin_manager.plugins = [mocked_plugin]
main_display.web_view = MagicMock()
# WHEN: build_html is called with a normal service item and a video theme.
main_display.build_html(service_item)
# THEN: the following should had not been called
self.assertEquals(main_display.web_view.setHtml.call_count, 1, 'setHTML should be called once')
self.assertEquals(main_display.media_controller.video.call_count, 1,
'Media Controller video should have been called once')

View File

@ -22,7 +22,7 @@
""" """
Package to test the openlp.plugin.bible.lib.https package. Package to test the openlp.plugin.bible.lib.https package.
""" """
from unittest import TestCase from unittest import TestCase, skip
from openlp.core.common import Registry from openlp.core.common import Registry
from openlp.plugins.bibles.lib.http import BGExtract, CWExtract, BSExtract from openlp.plugins.bibles.lib.http import BGExtract, CWExtract, BSExtract
@ -146,6 +146,7 @@ class TestBibleHTTP(TestCase):
self.assertIsNotNone(bibles) self.assertIsNotNone(bibles)
self.assertIn(('Holman Christian Standard Bible', 'HCSB', 'en'), bibles) self.assertIn(('Holman Christian Standard Bible', 'HCSB', 'en'), bibles)
@skip("Waiting for Crosswalk to fix their server")
def crosswalk_get_bibles_test(self): def crosswalk_get_bibles_test(self):
""" """
Test getting list of bibles from Crosswalk.com Test getting list of bibles from Crosswalk.com

View File

@ -26,7 +26,7 @@ import json
def assert_length(expected, iterable, msg=None): def assert_length(expected, iterable, msg=None):
if len(iterable) != expected: if len(iterable) != expected:
if not msg: if not msg:
msg = 'Expected length %s, got %s' % (expected, len(iterable)) msg = 'Expected length {expected}, got {got}'.format(expected=expected, got=len(iterable))
raise AssertionError(msg) raise AssertionError(msg)