forked from openlp/openlp
Add a webengine view for previewing themes. Made VLC loading more robust. A few minor fixes.
bzr-revno: 2877
This commit is contained in:
commit
17893737b5
@ -24,6 +24,7 @@ The :mod:`~openlp.display.render` module contains functions for rendering.
|
||||
"""
|
||||
import html
|
||||
import logging
|
||||
import mako
|
||||
import math
|
||||
import os
|
||||
import re
|
||||
@ -32,8 +33,10 @@ import time
|
||||
from PyQt5 import QtWidgets, QtGui
|
||||
|
||||
from openlp.core.common import ThemeLevel
|
||||
from openlp.core.common.i18n import translate
|
||||
from openlp.core.common.mixins import LogMixin, RegistryProperties
|
||||
from openlp.core.common.registry import Registry, RegistryBase
|
||||
from openlp.core.common.settings import Settings
|
||||
from openlp.core.display.screens import ScreenList
|
||||
from openlp.core.display.window import DisplayWindow
|
||||
from openlp.core.lib import ItemCapabilities
|
||||
@ -58,8 +61,10 @@ VERSE = 'The Lord said to {r}Noah{/r}: \n' \
|
||||
'{r}C{/r}{b}h{/b}{bl}i{/bl}{y}l{/y}{g}d{/g}{pk}' \
|
||||
'r{/pk}{o}e{/o}{pp}n{/pp} of the Lord\n'
|
||||
VERSE_FOR_LINE_COUNT = '\n'.join(map(str, range(100)))
|
||||
TITLE = 'Arky Arky (Unknown)'
|
||||
FOOTER = ['Public Domain', 'CCLI 123456']
|
||||
TITLE = 'Arky Arky'
|
||||
AUTHOR = 'John Doe'
|
||||
FOOTER_COPYRIGHT = 'Public Domain'
|
||||
CCLI_NO = '123456'
|
||||
|
||||
|
||||
def remove_tags(text, can_remove_chords=False):
|
||||
@ -425,7 +430,7 @@ def get_start_tags(raw_text):
|
||||
return raw_text + ''.join(end_tags), ''.join(start_tags), ''.join(html_tags)
|
||||
|
||||
|
||||
class Renderer(RegistryBase, LogMixin, RegistryProperties, DisplayWindow):
|
||||
class ThemePreviewRenderer(LogMixin, DisplayWindow):
|
||||
"""
|
||||
A virtual display used for rendering thumbnails and other offscreen tasks
|
||||
"""
|
||||
@ -435,24 +440,6 @@ class Renderer(RegistryBase, LogMixin, RegistryProperties, DisplayWindow):
|
||||
"""
|
||||
super().__init__(*args, **kwargs)
|
||||
self.force_page = False
|
||||
for screen in ScreenList():
|
||||
if screen.is_display:
|
||||
self.setGeometry(screen.display_geometry.x(), screen.display_geometry.y(),
|
||||
screen.display_geometry.width(), screen.display_geometry.height())
|
||||
break
|
||||
# If the display is not show'ed and hidden like this webegine will not render
|
||||
self.show()
|
||||
self.hide()
|
||||
self.theme_height = 0
|
||||
self.theme_level = ThemeLevel.Global
|
||||
|
||||
def set_theme_level(self, theme_level):
|
||||
"""
|
||||
Sets the theme level.
|
||||
|
||||
:param theme_level: The theme level to be used.
|
||||
"""
|
||||
self.theme_level = theme_level
|
||||
|
||||
def calculate_line_count(self):
|
||||
"""
|
||||
@ -466,7 +453,30 @@ class Renderer(RegistryBase, LogMixin, RegistryProperties, DisplayWindow):
|
||||
"""
|
||||
return self.run_javascript('Display.clearSlides();')
|
||||
|
||||
def generate_preview(self, theme_data, force_page=False):
|
||||
def generate_footer(self):
|
||||
"""
|
||||
"""
|
||||
footer_template = Settings().value('songs/footer template')
|
||||
# Keep this in sync with the list in songstab.py
|
||||
vars = {
|
||||
'title': TITLE,
|
||||
'authors_none_label': translate('OpenLP.Ui', 'Written by'),
|
||||
'authors_words_label': translate('SongsPlugin.AuthorType', 'Words',
|
||||
'Author who wrote the lyrics of a song'),
|
||||
'authors_words': [AUTHOR],
|
||||
'copyright': FOOTER_COPYRIGHT,
|
||||
'ccli_license': Settings().value('core/ccli number'),
|
||||
'ccli_license_label': translate('SongsPlugin.MediaItem', 'CCLI License'),
|
||||
'ccli_number': CCLI_NO,
|
||||
}
|
||||
try:
|
||||
footer_html = mako.template.Template(footer_template).render_unicode(**vars).replace('\n', '')
|
||||
except mako.exceptions.SyntaxException:
|
||||
log.error('Failed to render Song footer html:\n' + mako.exceptions.text_error_template().render())
|
||||
footer_html = 'Dummy footer text'
|
||||
return footer_html
|
||||
|
||||
def generate_preview(self, theme_data, force_page=False, generate_screenshot=True):
|
||||
"""
|
||||
Generate a preview of a theme.
|
||||
|
||||
@ -479,14 +489,16 @@ class Renderer(RegistryBase, LogMixin, RegistryProperties, DisplayWindow):
|
||||
if not self.force_page:
|
||||
self.set_theme(theme_data)
|
||||
self.theme_height = theme_data.font_main_height
|
||||
slides = self.format_slide(render_tags(VERSE), None)
|
||||
slides = self.format_slide(VERSE, None)
|
||||
verses = dict()
|
||||
verses['title'] = TITLE
|
||||
verses['text'] = slides[0]
|
||||
verses['text'] = render_tags(slides[0])
|
||||
verses['verse'] = 'V1'
|
||||
verses['footer'] = self.generate_footer()
|
||||
self.load_verses([verses])
|
||||
self.force_page = False
|
||||
return self.save_screenshot()
|
||||
if generate_screenshot:
|
||||
return self.save_screenshot()
|
||||
self.force_page = False
|
||||
return None
|
||||
|
||||
@ -515,7 +527,7 @@ class Renderer(RegistryBase, LogMixin, RegistryProperties, DisplayWindow):
|
||||
if item and item.is_capable(ItemCapabilities.CanWordSplit):
|
||||
pages = self._paginate_slide_words(text.split('\n'), line_end)
|
||||
# Songs and Custom
|
||||
elif item is None or item.is_capable(ItemCapabilities.CanSoftBreak):
|
||||
elif item is None or (item and item.is_capable(ItemCapabilities.CanSoftBreak)):
|
||||
pages = []
|
||||
if '[---]' in text:
|
||||
# Remove Overflow split if at start of the text
|
||||
@ -722,7 +734,8 @@ class Renderer(RegistryBase, LogMixin, RegistryProperties, DisplayWindow):
|
||||
:param text: The text to check. It may contain HTML tags.
|
||||
"""
|
||||
self.clear_slides()
|
||||
self.run_javascript('Display.addTextSlide("v1", "{text}", "Dummy Footer");'.format(text=text), is_sync=True)
|
||||
self.run_javascript('Display.addTextSlide("v1", "{text}", "Dummy Footer");'
|
||||
.format(text=text.replace('"', '\\"')), is_sync=True)
|
||||
does_text_fits = self.run_javascript('Display.doesContentFit();', is_sync=True)
|
||||
return does_text_fits
|
||||
|
||||
@ -745,3 +758,33 @@ class Renderer(RegistryBase, LogMixin, RegistryProperties, DisplayWindow):
|
||||
pixmap.save(fname, ext)
|
||||
else:
|
||||
return pixmap
|
||||
|
||||
|
||||
class Renderer(RegistryBase, RegistryProperties, ThemePreviewRenderer):
|
||||
"""
|
||||
A virtual display used for rendering thumbnails and other offscreen tasks
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
super().__init__(*args, **kwargs)
|
||||
self.force_page = False
|
||||
for screen in ScreenList():
|
||||
if screen.is_display:
|
||||
self.setGeometry(screen.display_geometry.x(), screen.display_geometry.y(),
|
||||
screen.display_geometry.width(), screen.display_geometry.height())
|
||||
break
|
||||
# If the display is not show'ed and hidden like this webegine will not render
|
||||
self.show()
|
||||
self.hide()
|
||||
self.theme_height = 0
|
||||
self.theme_level = ThemeLevel.Global
|
||||
|
||||
def set_theme_level(self, theme_level):
|
||||
"""
|
||||
Sets the theme level.
|
||||
|
||||
:param theme_level: The theme level to be used.
|
||||
"""
|
||||
self.theme_level = theme_level
|
||||
|
@ -28,7 +28,6 @@ import os
|
||||
import sys
|
||||
import threading
|
||||
from datetime import datetime
|
||||
import vlc
|
||||
|
||||
from PyQt5 import QtWidgets
|
||||
|
||||
@ -62,25 +61,27 @@ def get_vlc():
|
||||
|
||||
:return: The "vlc" module, or None
|
||||
"""
|
||||
if 'vlc' in sys.modules:
|
||||
# If VLC has already been imported, no need to do all the stuff below again
|
||||
is_vlc_available = False
|
||||
# Import the VLC module if not already done
|
||||
if 'vlc' not in sys.modules:
|
||||
try:
|
||||
is_vlc_available = bool(sys.modules['vlc'].get_default_instance())
|
||||
except Exception:
|
||||
pass
|
||||
if is_vlc_available:
|
||||
return sys.modules['vlc']
|
||||
else:
|
||||
import vlc # noqa module is not used directly, but is used via sys.modules['vlc']
|
||||
except ImportError:
|
||||
return None
|
||||
else:
|
||||
return vlc
|
||||
# Verify that VLC is also loadable
|
||||
is_vlc_available = False
|
||||
try:
|
||||
is_vlc_available = bool(sys.modules['vlc'].get_default_instance())
|
||||
except Exception:
|
||||
pass
|
||||
if is_vlc_available:
|
||||
return sys.modules['vlc']
|
||||
return None
|
||||
|
||||
|
||||
# On linux we need to initialise X threads, but not when running tests.
|
||||
# This needs to happen on module load and not in get_vlc(), otherwise it can cause crashes on some DE on some setups
|
||||
# (reported on Gnome3, Unity, Cinnamon, all GTK+ based) when using native filedialogs...
|
||||
if is_linux() and 'nose' not in sys.argv[0] and get_vlc():
|
||||
if is_linux() and 'pytest' not in sys.argv[0] and get_vlc():
|
||||
try:
|
||||
try:
|
||||
x11 = ctypes.cdll.LoadLibrary('libX11.so.6')
|
||||
|
@ -172,16 +172,14 @@ class ThemeForm(QtWidgets.QWizard, Ui_ThemeWizard, RegistryProperties):
|
||||
if not event:
|
||||
event = QtGui.QResizeEvent(self.size(), self.size())
|
||||
QtWidgets.QWizard.resizeEvent(self, event)
|
||||
if hasattr(self, 'preview_page') and self.currentPage() == self.preview_page:
|
||||
frame_width = self.preview_box_label.lineWidth()
|
||||
pixmap_width = self.preview_area.width() - 2 * frame_width
|
||||
pixmap_height = self.preview_area.height() - 2 * frame_width
|
||||
aspect_ratio = float(pixmap_width) / pixmap_height
|
||||
if aspect_ratio < self.display_aspect_ratio:
|
||||
pixmap_height = int(pixmap_width / self.display_aspect_ratio + 0.5)
|
||||
else:
|
||||
pixmap_width = int(pixmap_height * self.display_aspect_ratio + 0.5)
|
||||
self.preview_box_label.setFixedSize(pixmap_width + 2 * frame_width, pixmap_height + 2 * frame_width)
|
||||
try:
|
||||
self.display_aspect_ratio = self.renderer.width() / self.renderer.height()
|
||||
except ZeroDivisionError:
|
||||
self.display_aspect_ratio = 1
|
||||
# Make sure we don't resize before the widgets are actually created
|
||||
if hasattr(self, 'preview_area_layout'):
|
||||
self.preview_area_layout.set_aspect_ratio(self.display_aspect_ratio)
|
||||
self.preview_box.set_scale(float(self.preview_box.width()) / self.renderer.width())
|
||||
|
||||
def validateCurrentPage(self):
|
||||
"""
|
||||
@ -206,11 +204,17 @@ class ThemeForm(QtWidgets.QWizard, Ui_ThemeWizard, RegistryProperties):
|
||||
self.setOption(QtWidgets.QWizard.HaveCustomButton1, enabled)
|
||||
if self.page(page_id) == self.preview_page:
|
||||
self.update_theme()
|
||||
frame = self.theme_manager.generate_image(self.theme)
|
||||
frame.setDevicePixelRatio(self.devicePixelRatio())
|
||||
self.preview_box_label.setPixmap(frame)
|
||||
self.display_aspect_ratio = float(frame.width()) / frame.height()
|
||||
self.preview_box.set_theme(self.theme)
|
||||
self.preview_box.clear_slides()
|
||||
self.preview_box.set_scale(float(self.preview_box.width()) / self.renderer.width())
|
||||
try:
|
||||
self.display_aspect_ratio = self.renderer.width() / self.renderer.height()
|
||||
except ZeroDivisionError:
|
||||
self.display_aspect_ratio = 1
|
||||
self.preview_area_layout.set_aspect_ratio(self.display_aspect_ratio)
|
||||
self.resizeEvent()
|
||||
self.preview_box.show()
|
||||
self.preview_box.generate_preview(self.theme, False, False)
|
||||
|
||||
def on_custom_1_button_clicked(self, number):
|
||||
"""
|
||||
@ -398,6 +402,7 @@ class ThemeForm(QtWidgets.QWizard, Ui_ThemeWizard, RegistryProperties):
|
||||
Handle the display and state of the Preview page.
|
||||
"""
|
||||
self.setField('name', self.theme.theme_name)
|
||||
self.preview_box.set_theme(self.theme)
|
||||
|
||||
def on_background_combo_box_current_index_changed(self, index):
|
||||
"""
|
||||
@ -558,5 +563,5 @@ class ThemeForm(QtWidgets.QWizard, Ui_ThemeWizard, RegistryProperties):
|
||||
source_path = self.theme.background_filename
|
||||
if not self.edit_mode and not self.theme_manager.check_if_theme_exists(self.theme.theme_name):
|
||||
return
|
||||
self.theme_manager.save_theme(self.theme, source_path, destination_path)
|
||||
self.theme_manager.save_theme(self.theme, source_path, destination_path, self.preview_box.save_screenshot())
|
||||
return QtWidgets.QDialog.accept(self)
|
||||
|
@ -476,7 +476,7 @@ class ThemeManager(QtWidgets.QWidget, RegistryBase, Ui_ThemeManager, LogMixin, R
|
||||
if not theme_paths:
|
||||
theme = Theme()
|
||||
theme.theme_name = UiStrings().Default
|
||||
self._write_theme(theme)
|
||||
self.save_theme(theme)
|
||||
Settings().setValue(self.settings_section + '/global theme', theme.theme_name)
|
||||
self.application.set_normal_cursor()
|
||||
|
||||
@ -639,24 +639,14 @@ class ThemeManager(QtWidgets.QWidget, RegistryBase, Ui_ThemeManager, LogMixin, R
|
||||
return False
|
||||
return True
|
||||
|
||||
def save_theme(self, theme, image_source_path, image_destination_path):
|
||||
"""
|
||||
Called by theme maintenance Dialog to save the theme and to trigger the reload of the theme list
|
||||
|
||||
:param Theme theme: The theme data object.
|
||||
:param Path image_source_path: Where the theme image is currently located.
|
||||
:param Path image_destination_path: Where the Theme Image is to be saved to
|
||||
:rtype: None
|
||||
"""
|
||||
self._write_theme(theme, image_source_path, image_destination_path)
|
||||
|
||||
def _write_theme(self, theme, image_source_path=None, image_destination_path=None):
|
||||
def save_theme(self, theme, image_source_path=None, image_destination_path=None, image=None):
|
||||
"""
|
||||
Writes the theme to the disk and handles the background image if necessary
|
||||
|
||||
:param Theme theme: The theme data object.
|
||||
:param Path image_source_path: Where the theme image is currently located.
|
||||
:param Path image_destination_path: Where the Theme Image is to be saved to
|
||||
:param image: The example image of the theme. Optionally.
|
||||
:rtype: None
|
||||
"""
|
||||
name = theme.theme_name
|
||||
@ -676,7 +666,15 @@ class ThemeManager(QtWidgets.QWidget, RegistryBase, Ui_ThemeManager, LogMixin, R
|
||||
shutil.copyfile(image_source_path, image_destination_path)
|
||||
except OSError:
|
||||
self.log_exception('Failed to save theme image')
|
||||
self.generate_and_save_image(name, theme)
|
||||
if image:
|
||||
sample_path_name = self.theme_path / '{file_name}.png'.format(file_name=name)
|
||||
if sample_path_name.exists():
|
||||
sample_path_name.unlink()
|
||||
image.save(str(sample_path_name), 'png')
|
||||
thumb_path = self.thumb_path / '{name}.png'.format(name=name)
|
||||
create_thumb(sample_path_name, thumb_path, False)
|
||||
else:
|
||||
self.generate_and_save_image(name, theme)
|
||||
|
||||
def generate_and_save_image(self, theme_name, theme):
|
||||
"""
|
||||
|
@ -31,6 +31,8 @@ from openlp.core.lib.ui import add_welcome_page, create_valign_selection_widgets
|
||||
from openlp.core.ui.icons import UiIcons
|
||||
from openlp.core.widgets.buttons import ColorButton
|
||||
from openlp.core.widgets.edits import PathEdit
|
||||
from openlp.core.widgets.layouts import AspectRatioLayout
|
||||
from openlp.core.display.render import ThemePreviewRenderer
|
||||
|
||||
|
||||
class Ui_ThemeWizard(object):
|
||||
@ -363,16 +365,13 @@ class Ui_ThemeWizard(object):
|
||||
self.preview_layout.addLayout(self.theme_name_layout)
|
||||
self.preview_area = QtWidgets.QWidget(self.preview_page)
|
||||
self.preview_area.setObjectName('PreviewArea')
|
||||
self.preview_area_layout = QtWidgets.QGridLayout(self.preview_area)
|
||||
self.preview_area_layout.setContentsMargins(0, 0, 0, 0)
|
||||
self.preview_area_layout.setColumnStretch(0, 1)
|
||||
self.preview_area_layout.setRowStretch(0, 1)
|
||||
self.preview_area_layout.setObjectName('preview_area_layout')
|
||||
self.preview_box_label = QtWidgets.QLabel(self.preview_area)
|
||||
self.preview_box_label.setFrameShape(QtWidgets.QFrame.Box)
|
||||
self.preview_box_label.setScaledContents(True)
|
||||
self.preview_box_label.setObjectName('preview_box_label')
|
||||
self.preview_area_layout.addWidget(self.preview_box_label)
|
||||
self.preview_area_layout = AspectRatioLayout(self.preview_area, 0.75) # Dummy ratio, will be update
|
||||
self.preview_area_layout.margin = 8
|
||||
self.preview_area_layout.setSpacing(0)
|
||||
self.preview_area_layout.setObjectName('preview_web_layout')
|
||||
self.preview_box = ThemePreviewRenderer(self)
|
||||
self.preview_box.setObjectName('preview_box')
|
||||
self.preview_area_layout.addWidget(self.preview_box)
|
||||
self.preview_layout.addWidget(self.preview_area)
|
||||
theme_wizard.addPage(self.preview_page)
|
||||
self.retranslate_ui(theme_wizard)
|
||||
|
@ -173,7 +173,7 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties):
|
||||
item = self.list_view.currentItem()
|
||||
if item is None:
|
||||
return False
|
||||
filename = item.data(QtCore.Qt.UserRole)
|
||||
filename = str(item.data(QtCore.Qt.UserRole))
|
||||
# Special handling if the filename is a optical clip
|
||||
if filename.startswith('optical:'):
|
||||
(name, title, audio_track, subtitle_track, start, end, clip_name) = parse_optical_path(filename)
|
||||
@ -259,11 +259,12 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties):
|
||||
# TODO needs to be fixed as no idea why this fails
|
||||
# media.sort(key=lambda file_path: get_natural_key(file_path.name))
|
||||
for track in media:
|
||||
track_info = QtCore.QFileInfo(track)
|
||||
track_str = str(track)
|
||||
track_info = QtCore.QFileInfo(track_str)
|
||||
item_name = None
|
||||
if track.startswith('optical:'):
|
||||
if track_str.startswith('optical:'):
|
||||
# Handle optical based item
|
||||
(file_name, title, audio_track, subtitle_track, start, end, clip_name) = parse_optical_path(track)
|
||||
(file_name, title, audio_track, subtitle_track, start, end, clip_name) = parse_optical_path(track_str)
|
||||
item_name = QtWidgets.QListWidgetItem(clip_name)
|
||||
item_name.setIcon(UiIcons().optical)
|
||||
item_name.setData(QtCore.Qt.UserRole, track)
|
||||
@ -272,22 +273,22 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties):
|
||||
end=format_milliseconds(end)))
|
||||
elif not os.path.exists(track):
|
||||
# File doesn't exist, mark as error.
|
||||
file_name = os.path.split(str(track))[1]
|
||||
file_name = os.path.split(track_str)[1]
|
||||
item_name = QtWidgets.QListWidgetItem(file_name)
|
||||
item_name.setIcon(UiIcons().error)
|
||||
item_name.setData(QtCore.Qt.UserRole, track)
|
||||
item_name.setToolTip(track)
|
||||
item_name.setToolTip(track_str)
|
||||
elif track_info.isFile():
|
||||
# Normal media file handling.
|
||||
file_name = os.path.split(str(track))[1]
|
||||
file_name = os.path.split(track_str)[1]
|
||||
item_name = QtWidgets.QListWidgetItem(file_name)
|
||||
search = file_name.split('.')[-1].lower()
|
||||
if '*.{text}'.format(text=search) in self.media_controller.audio_extensions_list:
|
||||
if search in AUDIO_EXT:
|
||||
item_name.setIcon(UiIcons().audio)
|
||||
else:
|
||||
item_name.setIcon(UiIcons().video)
|
||||
item_name.setData(QtCore.Qt.UserRole, track)
|
||||
item_name.setToolTip(track)
|
||||
item_name.setToolTip(track_str)
|
||||
if item_name:
|
||||
self.list_view.addItem(item_name)
|
||||
|
||||
|
@ -88,7 +88,7 @@ class SongsTab(SettingsTab):
|
||||
self.footer_group_box = QtWidgets.QGroupBox(self.left_column)
|
||||
self.footer_group_box.setObjectName('footer_group_box')
|
||||
self.footer_layout = QtWidgets.QVBoxLayout(self.footer_group_box)
|
||||
self.footer_layout.setObjectName('chords_layout')
|
||||
self.footer_layout.setObjectName('footer_layout')
|
||||
self.footer_info_label = QtWidgets.QLabel(self.footer_group_box)
|
||||
self.footer_layout.addWidget(self.footer_info_label)
|
||||
self.footer_placeholder_info = QtWidgets.QTextEdit(self.footer_group_box)
|
||||
|
@ -83,7 +83,7 @@ class TestThemeManager(TestCase):
|
||||
|
||||
@patch('openlp.core.ui.thememanager.shutil')
|
||||
@patch('openlp.core.ui.thememanager.create_paths')
|
||||
def test_write_theme_same_image(self, mocked_create_paths, mocked_shutil):
|
||||
def test_save_theme_same_image(self, mocked_create_paths, mocked_shutil):
|
||||
"""
|
||||
Test that we don't try to overwrite a theme background image with itself
|
||||
"""
|
||||
@ -98,16 +98,16 @@ class TestThemeManager(TestCase):
|
||||
mocked_theme.extract_formatted_xml = MagicMock()
|
||||
mocked_theme.extract_formatted_xml.return_value = 'fake_theme_xml'.encode()
|
||||
|
||||
# WHEN: Calling _write_theme with path to the same image, but the path written slightly different
|
||||
# WHEN: Calling save_theme with path to the same image, but the path written slightly different
|
||||
file_path_1 = RESOURCE_PATH / 'church.jpg'
|
||||
theme_manager._write_theme(mocked_theme, file_path_1, file_path_1)
|
||||
theme_manager.save_theme(mocked_theme, file_path_1, file_path_1)
|
||||
|
||||
# THEN: The mocked_copyfile should not have been called
|
||||
assert mocked_shutil.copyfile.called is False, 'copyfile should not be called'
|
||||
|
||||
@patch('openlp.core.ui.thememanager.shutil')
|
||||
@patch('openlp.core.ui.thememanager.create_paths')
|
||||
def test_write_theme_diff_images(self, mocked_create_paths, mocked_shutil):
|
||||
def test_save_theme_diff_images(self, mocked_create_paths, mocked_shutil):
|
||||
"""
|
||||
Test that we do overwrite a theme background image when a new is submitted
|
||||
"""
|
||||
@ -121,15 +121,15 @@ class TestThemeManager(TestCase):
|
||||
mocked_theme.theme_name = 'themename'
|
||||
mocked_theme.filename = "filename"
|
||||
|
||||
# WHEN: Calling _write_theme with path to different images
|
||||
# WHEN: Calling save_theme with path to different images
|
||||
file_path_1 = RESOURCE_PATH / 'church.jpg'
|
||||
file_path_2 = RESOURCE_PATH / 'church2.jpg'
|
||||
theme_manager._write_theme(mocked_theme, file_path_1, file_path_2)
|
||||
theme_manager.save_theme(mocked_theme, file_path_1, file_path_2)
|
||||
|
||||
# THEN: The mocked_copyfile should not have been called
|
||||
assert mocked_shutil.copyfile.called is True, 'copyfile should be called'
|
||||
|
||||
def test_write_theme_special_char_name(self):
|
||||
def test_save_theme_special_char_name(self):
|
||||
"""
|
||||
Test that we can save themes with special characters in the name
|
||||
"""
|
||||
@ -142,8 +142,8 @@ class TestThemeManager(TestCase):
|
||||
mocked_theme.theme_name = 'theme 愛 name'
|
||||
mocked_theme.export_theme.return_value = "{}"
|
||||
|
||||
# WHEN: Calling _write_theme with a theme with a name with special characters in it
|
||||
theme_manager._write_theme(mocked_theme)
|
||||
# WHEN: Calling save_theme with a theme with a name with special characters in it
|
||||
theme_manager.save_theme(mocked_theme)
|
||||
|
||||
# THEN: It should have been created
|
||||
assert os.path.exists(os.path.join(self.temp_folder, 'theme 愛 name', 'theme 愛 name.json')) is True, \
|
||||
|
@ -23,6 +23,7 @@
|
||||
Interface tests to test the ThemeWizard class and related methods.
|
||||
"""
|
||||
from unittest import TestCase
|
||||
from unittest.mock import patch
|
||||
|
||||
from openlp.core.common.registry import Registry
|
||||
from openlp.core.ui.themeform import ThemeForm
|
||||
@ -39,7 +40,8 @@ class TestThemeManager(TestCase, TestMixin):
|
||||
"""
|
||||
Registry.create()
|
||||
|
||||
def test_create_theme_wizard(self):
|
||||
@patch('openlp.core.display.window.QtWidgets.QVBoxLayout')
|
||||
def test_create_theme_wizard(self, mocked_qvboxlayout):
|
||||
"""
|
||||
Test creating a ThemeForm instance
|
||||
"""
|
||||
|
Loading…
Reference in New Issue
Block a user