forked from openlp/openlp
Merge branch 'beta_fixes_3' into 'master'
Beta fixes 3 Closes #454, #604, #605, #521, #551, #441, #644, #661, #656, #669, #678, and #680 See merge request openlp/openlp!260
This commit is contained in:
commit
6ea2025888
@ -25,7 +25,6 @@ import datetime
|
|||||||
import logging
|
import logging
|
||||||
import ntpath
|
import ntpath
|
||||||
import os
|
import os
|
||||||
import urllib.request
|
|
||||||
import uuid
|
import uuid
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@ -39,9 +38,9 @@ from openlp.core.common.enum import ServiceItemType
|
|||||||
from openlp.core.common.i18n import translate
|
from openlp.core.common.i18n import translate
|
||||||
from openlp.core.common.mixins import RegistryProperties
|
from openlp.core.common.mixins import RegistryProperties
|
||||||
from openlp.core.common.registry import Registry
|
from openlp.core.common.registry import Registry
|
||||||
|
from openlp.core.common.utils import wait_for
|
||||||
from openlp.core.display.render import remove_tags, render_tags, render_chords_for_printing
|
from openlp.core.display.render import remove_tags, render_tags, render_chords_for_printing
|
||||||
from openlp.core.lib import ItemCapabilities
|
from openlp.core.lib import create_thumb, image_to_data_uri, ItemCapabilities
|
||||||
from openlp.core.lib import create_thumb
|
|
||||||
from openlp.core.lib.theme import BackgroundType, TransitionSpeed
|
from openlp.core.lib.theme import BackgroundType, TransitionSpeed
|
||||||
from openlp.core.state import State
|
from openlp.core.state import State
|
||||||
from openlp.core.ui.icons import UiIcons
|
from openlp.core.ui.icons import UiIcons
|
||||||
@ -70,6 +69,7 @@ class ServiceItem(RegistryProperties):
|
|||||||
self._rendered_slides = None
|
self._rendered_slides = None
|
||||||
self._display_slides = None
|
self._display_slides = None
|
||||||
self._print_slides = None
|
self._print_slides = None
|
||||||
|
self._creating_slides = False
|
||||||
self.title = ''
|
self.title = ''
|
||||||
self.slides = []
|
self.slides = []
|
||||||
self.processor = None
|
self.processor = None
|
||||||
@ -202,6 +202,8 @@ class ServiceItem(RegistryProperties):
|
|||||||
"""
|
"""
|
||||||
Create frames for rendering and display
|
Create frames for rendering and display
|
||||||
"""
|
"""
|
||||||
|
wait_for(lambda: not self._creating_slides)
|
||||||
|
self._creating_slides = True
|
||||||
self._rendered_slides = []
|
self._rendered_slides = []
|
||||||
self._display_slides = []
|
self._display_slides = []
|
||||||
|
|
||||||
@ -234,12 +236,14 @@ class ServiceItem(RegistryProperties):
|
|||||||
}
|
}
|
||||||
self._display_slides.append(display_slide)
|
self._display_slides.append(display_slide)
|
||||||
index += 1
|
index += 1
|
||||||
|
self._creating_slides = False
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def rendered_slides(self):
|
def rendered_slides(self):
|
||||||
"""
|
"""
|
||||||
Render the frames and return them
|
Render the frames and return them
|
||||||
"""
|
"""
|
||||||
|
wait_for(lambda: not self._creating_slides)
|
||||||
if not self._rendered_slides:
|
if not self._rendered_slides:
|
||||||
self._create_slides()
|
self._create_slides()
|
||||||
return self._rendered_slides
|
return self._rendered_slides
|
||||||
@ -249,6 +253,7 @@ class ServiceItem(RegistryProperties):
|
|||||||
"""
|
"""
|
||||||
Render the frames and return them
|
Render the frames and return them
|
||||||
"""
|
"""
|
||||||
|
wait_for(lambda: not self._creating_slides)
|
||||||
if not self._display_slides:
|
if not self._display_slides:
|
||||||
self._create_slides()
|
self._create_slides()
|
||||||
return self._display_slides
|
return self._display_slides
|
||||||
@ -868,6 +873,7 @@ class ServiceItem(RegistryProperties):
|
|||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
"""
|
"""
|
||||||
Convert the service item into a dictionary
|
Convert the service item into a dictionary
|
||||||
|
Images and thumbnails are put in dict as data uri strings.
|
||||||
"""
|
"""
|
||||||
data_dict = {
|
data_dict = {
|
||||||
'title': self.title,
|
'title': self.title,
|
||||||
@ -902,7 +908,7 @@ class ServiceItem(RegistryProperties):
|
|||||||
full_thumbnail_path = AppLocation.get_data_path() / thumbnail_path
|
full_thumbnail_path = AppLocation.get_data_path() / thumbnail_path
|
||||||
if not full_thumbnail_path.exists():
|
if not full_thumbnail_path.exists():
|
||||||
create_thumb(Path(self.get_frame_path(index)), full_thumbnail_path, False)
|
create_thumb(Path(self.get_frame_path(index)), full_thumbnail_path, False)
|
||||||
item['img'] = urllib.request.pathname2url(os.path.sep + str(thumbnail_path))
|
item['img'] = image_to_data_uri(full_thumbnail_path)
|
||||||
item['text'] = str(frame['title'])
|
item['text'] = str(frame['title'])
|
||||||
item['html'] = str(frame['title'])
|
item['html'] = str(frame['title'])
|
||||||
else:
|
else:
|
||||||
@ -921,7 +927,7 @@ class ServiceItem(RegistryProperties):
|
|||||||
log.warning('Service item "{title}" is missing a thumbnail or has an invalid thumbnail path'
|
log.warning('Service item "{title}" is missing a thumbnail or has an invalid thumbnail path'
|
||||||
.format(title=self.title))
|
.format(title=self.title))
|
||||||
else:
|
else:
|
||||||
item['img'] = urllib.request.pathname2url(os.path.sep + str(relative_file))
|
item['img'] = image_to_data_uri(AppLocation.get_data_path() / relative_file)
|
||||||
item['text'] = str(frame['title'])
|
item['text'] = str(frame['title'])
|
||||||
item['html'] = str(frame['title'])
|
item['html'] = str(frame['title'])
|
||||||
data_dict['slides'].append(item)
|
data_dict['slides'].append(item)
|
||||||
|
@ -738,6 +738,8 @@ class ThemeManager(QtWidgets.QWidget, RegistryBase, Ui_ThemeManager, LogMixin, R
|
|||||||
for theme_name in theme_name_list:
|
for theme_name in theme_name_list:
|
||||||
theme_data = self._get_theme_data(theme_name)
|
theme_data = self._get_theme_data(theme_name)
|
||||||
preview_pixmap = self.progress_form.get_preview(theme_name, theme_data)
|
preview_pixmap = self.progress_form.get_preview(theme_name, theme_data)
|
||||||
|
if preview_pixmap is None:
|
||||||
|
break
|
||||||
self.save_preview(theme_name, preview_pixmap)
|
self.save_preview(theme_name, preview_pixmap)
|
||||||
self.progress_form.close()
|
self.progress_form.close()
|
||||||
self.load_themes()
|
self.load_themes()
|
||||||
|
@ -49,11 +49,20 @@ class ThemeProgressForm(QtWidgets.QDialog, UiThemeProgressDialog, RegistryProper
|
|||||||
return super().show()
|
return super().show()
|
||||||
|
|
||||||
def get_preview(self, theme_name, theme_data):
|
def get_preview(self, theme_name, theme_data):
|
||||||
|
"""
|
||||||
|
Fetch a screenshot of the webengine preview
|
||||||
|
|
||||||
|
:return: Image of the webengine, can be None
|
||||||
|
"""
|
||||||
self.label.setText(theme_name)
|
self.label.setText(theme_name)
|
||||||
self.progress_bar.setValue(self.progress_bar.value() + 1)
|
self.progress_bar.setValue(self.progress_bar.value() + 1)
|
||||||
wait_for(lambda: self.theme_display.is_initialised)
|
wait_for(lambda: self.theme_display.is_initialised)
|
||||||
self.theme_display.set_scale(float(self.theme_display.width()) / self.renderer.width())
|
self.theme_display.set_scale(float(self.theme_display.width()) / self.renderer.width())
|
||||||
return self.theme_display.generate_preview(theme_data, generate_screenshot=True)
|
screenshot = self.theme_display.generate_preview(theme_data, generate_screenshot=True)
|
||||||
|
if self.isVisible():
|
||||||
|
return screenshot
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
def _get_theme_list(self):
|
def _get_theme_list(self):
|
||||||
"""Property getter"""
|
"""Property getter"""
|
||||||
|
@ -24,7 +24,7 @@ Package to test the openlp.core.lib package.
|
|||||||
import os
|
import os
|
||||||
import pytest
|
import pytest
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from unittest.mock import Mock, MagicMock, patch, ANY
|
from unittest.mock import Mock, MagicMock, patch
|
||||||
|
|
||||||
from openlp.core.common import ThemeLevel, is_win
|
from openlp.core.common import ThemeLevel, is_win
|
||||||
from openlp.core.common.enum import ServiceItemType
|
from openlp.core.common.enum import ServiceItemType
|
||||||
@ -809,7 +809,9 @@ def test_to_dict_text_item(state_media, settings, service_item_env):
|
|||||||
assert result == expected_dict
|
assert result == expected_dict
|
||||||
|
|
||||||
|
|
||||||
def test_to_dict_image_item(state_media, settings, service_item_env):
|
@patch('openlp.core.lib.serviceitem.AppLocation.get_data_path')
|
||||||
|
@patch('openlp.core.lib.serviceitem.image_to_data_uri')
|
||||||
|
def test_to_dict_image_item(mocked_image_to_data_uri, mocked_get_data_path, state_media, settings, service_item_env):
|
||||||
"""
|
"""
|
||||||
Test that the to_dict() method returns the correct data for the service item
|
Test that the to_dict() method returns the correct data for the service item
|
||||||
"""
|
"""
|
||||||
@ -820,6 +822,8 @@ def test_to_dict_image_item(state_media, settings, service_item_env):
|
|||||||
service_item.add_icon = MagicMock()
|
service_item.add_icon = MagicMock()
|
||||||
FormattingTags.load_tags()
|
FormattingTags.load_tags()
|
||||||
line = convert_file_service_item(TEST_PATH, 'serviceitem_image_2.osj')
|
line = convert_file_service_item(TEST_PATH, 'serviceitem_image_2.osj')
|
||||||
|
mocked_get_data_path.return_value = Path('/path/to/')
|
||||||
|
mocked_image_to_data_uri.side_effect = lambda x: 'your image uri at: {}'.format(x)
|
||||||
|
|
||||||
with patch('openlp.core.lib.serviceitem.sha256_file_hash') as mocked_sha256_file_hash:
|
with patch('openlp.core.lib.serviceitem.sha256_file_hash') as mocked_sha256_file_hash:
|
||||||
mocked_sha256_file_hash.return_value = '3a7ccbdb0b5a3db169c4692d7aad0ec8'
|
mocked_sha256_file_hash.return_value = '3a7ccbdb0b5a3db169c4692d7aad0ec8'
|
||||||
@ -841,7 +845,7 @@ def test_to_dict_image_item(state_media, settings, service_item_env):
|
|||||||
'slides': [
|
'slides': [
|
||||||
{
|
{
|
||||||
'html': 'image_1.jpg',
|
'html': 'image_1.jpg',
|
||||||
'img': '/images/thumbnails/image_1.jpg',
|
'img': 'your image uri at: /path/to/images/thumbnails/image_1.jpg',
|
||||||
'selected': False,
|
'selected': False,
|
||||||
'tag': 1,
|
'tag': 1,
|
||||||
'text': 'image_1.jpg',
|
'text': 'image_1.jpg',
|
||||||
@ -856,7 +860,8 @@ def test_to_dict_image_item(state_media, settings, service_item_env):
|
|||||||
|
|
||||||
|
|
||||||
@patch('openlp.core.lib.serviceitem.AppLocation.get_data_path')
|
@patch('openlp.core.lib.serviceitem.AppLocation.get_data_path')
|
||||||
def test_to_dict_presentation_item(mocked_get_data_path, state_media, settings, service_item_env):
|
@patch('openlp.core.lib.serviceitem.image_to_data_uri')
|
||||||
|
def test_to_dict_presentation_item(mocked_image_uri, mocked_get_data_path, state_media, settings, service_item_env):
|
||||||
"""
|
"""
|
||||||
Test that the to_dict() method returns the correct data for the service item
|
Test that the to_dict() method returns the correct data for the service item
|
||||||
"""
|
"""
|
||||||
@ -870,6 +875,7 @@ def test_to_dict_presentation_item(mocked_get_data_path, state_media, settings,
|
|||||||
image = Path('thumbnails/abcd/slide1.png')
|
image = Path('thumbnails/abcd/slide1.png')
|
||||||
display_title = 'DisplayTitle'
|
display_title = 'DisplayTitle'
|
||||||
notes = 'Note1\nNote2\n'
|
notes = 'Note1\nNote2\n'
|
||||||
|
mocked_image_uri.side_effect = lambda x: 'your img uri at: {}'.format(x)
|
||||||
|
|
||||||
# WHEN: adding presentation to service_item
|
# WHEN: adding presentation to service_item
|
||||||
with patch('openlp.core.lib.serviceitem.sha256_file_hash') as mocked_sha256_file_hash,\
|
with patch('openlp.core.lib.serviceitem.sha256_file_hash') as mocked_sha256_file_hash,\
|
||||||
@ -898,7 +904,7 @@ def test_to_dict_presentation_item(mocked_get_data_path, state_media, settings,
|
|||||||
'tag': 1,
|
'tag': 1,
|
||||||
'text': 'test.pptx',
|
'text': 'test.pptx',
|
||||||
'title': '',
|
'title': '',
|
||||||
'img': ANY
|
'img': 'your img uri at: /path/to/presentations/thumbnails/4a067fed6834ea2bc4b8819f11636365/slide1.png'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
'theme': None,
|
'theme': None,
|
||||||
|
@ -36,7 +36,9 @@ def _get_theme_progress_form():
|
|||||||
|
|
||||||
|
|
||||||
def test_init(qapp):
|
def test_init(qapp):
|
||||||
"""Test that the ThemeProgressForm is created without problems"""
|
"""
|
||||||
|
Test that the ThemeProgressForm is created without problems
|
||||||
|
"""
|
||||||
# GIVEN: ThemeProgressForm class
|
# GIVEN: ThemeProgressForm class
|
||||||
# WHEN: An object is instatiated
|
# WHEN: An object is instatiated
|
||||||
# THEN: There is no problem
|
# THEN: There is no problem
|
||||||
@ -46,7 +48,9 @@ def test_init(qapp):
|
|||||||
@patch('openlp.core.ui.themeprogressform.ScreenList')
|
@patch('openlp.core.ui.themeprogressform.ScreenList')
|
||||||
@patch('openlp.core.ui.themeprogressform.QtWidgets.QDialog.show')
|
@patch('openlp.core.ui.themeprogressform.QtWidgets.QDialog.show')
|
||||||
def test_show(mocked_show, MockScreenList, settings):
|
def test_show(mocked_show, MockScreenList, settings):
|
||||||
"""Test that the ThemeProgressForm is created without problems"""
|
"""
|
||||||
|
Test that the ThemeProgressForm is created without problems
|
||||||
|
"""
|
||||||
# GIVEN: ThemeProgressForm object
|
# GIVEN: ThemeProgressForm object
|
||||||
form = _get_theme_progress_form()
|
form = _get_theme_progress_form()
|
||||||
mocked_screen_list = MagicMock()
|
mocked_screen_list = MagicMock()
|
||||||
@ -70,7 +74,9 @@ def test_show(mocked_show, MockScreenList, settings):
|
|||||||
@patch('openlp.core.ui.themeprogressform.ScreenList')
|
@patch('openlp.core.ui.themeprogressform.ScreenList')
|
||||||
@patch('openlp.core.ui.themeprogressform.QtWidgets.QDialog.show')
|
@patch('openlp.core.ui.themeprogressform.QtWidgets.QDialog.show')
|
||||||
def test_show_divide_by_zero(mocked_show, MockScreenList, settings):
|
def test_show_divide_by_zero(mocked_show, MockScreenList, settings):
|
||||||
"""Test that the ThemeProgressForm is created without problems even if there's a divide by zero exception"""
|
"""
|
||||||
|
Test that the ThemeProgressForm is created without problems even if there's a divide by zero exception
|
||||||
|
"""
|
||||||
# GIVEN: ThemeProgressForm object
|
# GIVEN: ThemeProgressForm object
|
||||||
form = _get_theme_progress_form()
|
form = _get_theme_progress_form()
|
||||||
mocked_screen_list = MagicMock()
|
mocked_screen_list = MagicMock()
|
||||||
@ -92,7 +98,9 @@ def test_show_divide_by_zero(mocked_show, MockScreenList, settings):
|
|||||||
|
|
||||||
|
|
||||||
def test_get_preview(settings):
|
def test_get_preview(settings):
|
||||||
"""Test that the get_preview() method returns a preview image"""
|
"""
|
||||||
|
Test that the get_preview() method returns a preview image
|
||||||
|
"""
|
||||||
# GIVEN: ThemeProgressForm object
|
# GIVEN: ThemeProgressForm object
|
||||||
Registry.create()
|
Registry.create()
|
||||||
mocked_renderer = MagicMock()
|
mocked_renderer = MagicMock()
|
||||||
@ -100,6 +108,7 @@ def test_get_preview(settings):
|
|||||||
test_theme_name = 'Test Theme'
|
test_theme_name = 'Test Theme'
|
||||||
test_theme_data = {'name': test_theme_name}
|
test_theme_data = {'name': test_theme_name}
|
||||||
form = _get_theme_progress_form()
|
form = _get_theme_progress_form()
|
||||||
|
form.isVisible = MagicMock(return_value=True)
|
||||||
form.progress_bar = MagicMock(**{'value.return_value': 0})
|
form.progress_bar = MagicMock(**{'value.return_value': 0})
|
||||||
form.label = MagicMock()
|
form.label = MagicMock()
|
||||||
form.theme_display = MagicMock(**{'width.return_value': 192, 'generate_preview.return_value': 'preview'})
|
form.theme_display = MagicMock(**{'width.return_value': 192, 'generate_preview.return_value': 'preview'})
|
||||||
@ -119,6 +128,30 @@ def test_get_preview(settings):
|
|||||||
assert preview == 'preview'
|
assert preview == 'preview'
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_preview_not_visible(settings):
|
||||||
|
"""
|
||||||
|
Test that the get_preview() method does not return a preview image when display is not visible
|
||||||
|
"""
|
||||||
|
# GIVEN: ThemeProgressForm object
|
||||||
|
Registry.create()
|
||||||
|
mocked_renderer = MagicMock()
|
||||||
|
Registry().register('renderer', mocked_renderer)
|
||||||
|
test_theme_name = 'Test Theme'
|
||||||
|
test_theme_data = {'name': test_theme_name}
|
||||||
|
form = _get_theme_progress_form()
|
||||||
|
form.isVisible = MagicMock(return_value=False)
|
||||||
|
form.progress_bar = MagicMock(**{'value.return_value': 0})
|
||||||
|
form.label = MagicMock()
|
||||||
|
form.theme_display = MagicMock(**{'width.return_value': 192, 'generate_preview.return_value': 'preview'})
|
||||||
|
form.renderer.width = MagicMock(return_value=1920)
|
||||||
|
|
||||||
|
# WHEN: get_preview() is called
|
||||||
|
preview = form.get_preview(test_theme_name, test_theme_data)
|
||||||
|
|
||||||
|
# THEN: Result should be None
|
||||||
|
assert preview is None
|
||||||
|
|
||||||
|
|
||||||
def test_theme_list(qapp):
|
def test_theme_list(qapp):
|
||||||
# GIVEN: ThemeProgressForm object and theme list
|
# GIVEN: ThemeProgressForm object and theme list
|
||||||
test_theme_list = ['Theme 1', 'Theme 2']
|
test_theme_list = ['Theme 1', 'Theme 2']
|
||||||
|
Loading…
Reference in New Issue
Block a user