This commit is contained in:
Tomas Groth 2014-08-24 15:38:17 +01:00
commit 43d3823bfb
12 changed files with 135 additions and 17 deletions

View File

@ -660,7 +660,7 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager, R
finally: finally:
if out_file: if out_file:
out_file.close() out_file.close()
if image_from and image_from != image_to: if image_from and os.path.abspath(image_from) != os.path.abspath(image_to):
try: try:
encoding = get_filesystem_encoding() encoding = get_filesystem_encoding()
shutil.copyfile(str(image_from).encode(encoding), str(image_to).encode(encoding)) shutil.copyfile(str(image_from).encode(encoding), str(image_to).encode(encoding))

View File

@ -290,9 +290,9 @@ class SongFormat(object):
}, },
ProPresenter: { ProPresenter: {
'class': ProPresenterImport, 'class': ProPresenterImport,
'name': 'ProPresenter', 'name': 'ProPresenter 4',
'prefix': 'proPresenter', 'prefix': 'proPresenter',
'filter': '%s (*.pro4)' % translate('SongsPlugin.ImportWizardForm', 'ProPresenter Song Files') 'filter': '%s (*.pro4)' % translate('SongsPlugin.ImportWizardForm', 'ProPresenter 4 Song Files')
}, },
SongBeamer: { SongBeamer: {
'class': SongBeamerImport, 'class': SongBeamerImport,

View File

@ -27,5 +27,5 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
""" """
The :mod:`~openlp.plugins.songs.lib.import` module contains importers for the Songs plugin. The :mod:`~openlp.plugins.songs.lib.importers` module contains importers for the Songs plugin.
""" """

View File

@ -33,17 +33,20 @@ ProPresenter song files into the current installation database.
import os import os
import base64 import base64
import logging
from lxml import objectify from lxml import objectify
from openlp.core.ui.wizard import WizardStrings from openlp.core.ui.wizard import WizardStrings
from openlp.plugins.songs.lib import strip_rtf from openlp.plugins.songs.lib import strip_rtf
from .songimport import SongImport from .songimport import SongImport
log = logging.getLogger(__name__)
class ProPresenterImport(SongImport): class ProPresenterImport(SongImport):
""" """
The :class:`ProPresenterImport` class provides OpenLP with the The :class:`ProPresenterImport` class provides OpenLP with the
ability to import ProPresenter song files. ability to import ProPresenter 4 song files.
""" """
def do_import(self): def do_import(self):
self.import_wizard.progress_bar.setMaximum(len(self.import_source)) self.import_wizard.progress_bar.setMaximum(len(self.import_source))
@ -52,11 +55,11 @@ class ProPresenterImport(SongImport):
return return
self.import_wizard.increment_progress_bar(WizardStrings.ImportingType % os.path.basename(file_path)) self.import_wizard.increment_progress_bar(WizardStrings.ImportingType % os.path.basename(file_path))
root = objectify.parse(open(file_path, 'rb')).getroot() root = objectify.parse(open(file_path, 'rb')).getroot()
self.process_song(root) self.process_song(root, file_path)
def process_song(self, root): def process_song(self, root, filename):
self.set_defaults() self.set_defaults()
self.title = root.get('CCLISongTitle') self.title = os.path.basename(filename).rstrip('.pro4')
self.copyright = root.get('CCLICopyrightInfo') self.copyright = root.get('CCLICopyrightInfo')
self.comments = root.get('notes') self.comments = root.get('notes')
self.ccli_number = root.get('CCLILicenseNumber') self.ccli_number = root.get('CCLILicenseNumber')
@ -67,6 +70,9 @@ class ProPresenterImport(SongImport):
count = 0 count = 0
for slide in root.slides.RVDisplaySlide: for slide in root.slides.RVDisplaySlide:
count += 1 count += 1
if not hasattr(slide.displayElements, 'RVTextElement'):
log.debug('No text found, may be an image slide')
continue
RTFData = slide.displayElements.RVTextElement.get('RTFData') RTFData = slide.displayElements.RVTextElement.get('RTFData')
rtf = base64.standard_b64decode(RTFData) rtf = base64.standard_b64decode(RTFData)
words, encoding = strip_rtf(rtf.decode()) words, encoding = strip_rtf(rtf.decode())

View File

@ -67,7 +67,8 @@ class OpenLPJobs(object):
Branch_PEP = 'Branch-05a-Code_Analysis' Branch_PEP = 'Branch-05a-Code_Analysis'
Branch_Coverage = 'Branch-05b-Test_Coverage' Branch_Coverage = 'Branch-05b-Test_Coverage'
Jobs = [Branch_Pull, Branch_Functional, Branch_Interface, Branch_Windows_Functional, Branch_Windows_Interface, Branch_PEP, Branch_Coverage] Jobs = [Branch_Pull, Branch_Functional, Branch_Interface, Branch_Windows_Functional, Branch_Windows_Interface,
Branch_PEP, Branch_Coverage]
class Colour(object): class Colour(object):

View File

@ -36,27 +36,101 @@ from unittest import TestCase
from tests.interfaces import MagicMock from tests.interfaces import MagicMock
from openlp.core.ui import ThemeManager from openlp.core.ui import ThemeManager
from openlp.core.common import Registry
RESOURCES_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', 'resources', 'themes')) from tests.utils.constants import TEST_RESOURCES_PATH
from tests.interfaces import MagicMock, patch
class TestThemeManager(TestCase): class TestThemeManager(TestCase):
def setUp(self):
"""
Set up the tests
"""
Registry.create()
def export_theme_test(self): def export_theme_test(self):
""" """
Test exporting a theme . Test exporting a theme .
""" """
# GIVEN: A new ThemeManager instance. # GIVEN: A new ThemeManager instance.
theme_manager = ThemeManager() theme_manager = ThemeManager()
theme_manager.path = RESOURCES_PATH theme_manager.path = os.path.join(TEST_RESOURCES_PATH, 'themes')
zipfile.ZipFile.__init__ = MagicMock() zipfile.ZipFile.__init__ = MagicMock()
zipfile.ZipFile.__init__.return_value = None zipfile.ZipFile.__init__.return_value = None
zipfile.ZipFile.write = MagicMock() zipfile.ZipFile.write = MagicMock()
# WHEN: The theme is exported # WHEN: The theme is exported
theme_manager._export_theme('/some/path', 'Default') theme_manager._export_theme(os.path.join('some', 'path'), 'Default')
# THEN: The zipfile should be created at the given path # THEN: The zipfile should be created at the given path
zipfile.ZipFile.__init__.assert_called_with('/some/path/Default.otz', 'w') zipfile.ZipFile.__init__.assert_called_with(os.path.join('some', 'path', 'Default.otz'), 'w')
zipfile.ZipFile.write.assert_called_with(os.path.join(RESOURCES_PATH, 'Default', 'Default.xml'), zipfile.ZipFile.write.assert_called_with(os.path.join(TEST_RESOURCES_PATH, 'themes', 'Default', 'Default.xml'),
'Default/Default.xml') os.path.join('Default', 'Default.xml'))
def initial_theme_manager_test(self):
"""
Test the instantiation of theme manager.
"""
# GIVEN: A new service manager instance.
ThemeManager(None)
# WHEN: the default theme manager is built.
# THEN: The the controller should be registered in the registry.
self.assertIsNotNone(Registry().get('theme_manager'), 'The base theme manager should be registered')
def write_theme_same_image_test(self):
"""
Test that we don't try to overwrite a theme background image with itself
"""
# GIVEN: A new theme manager instance, with mocked builtins.open, shutil.copyfile,
# theme, check_directory_exists and thememanager-attributes.
with patch('builtins.open') as mocked_open, \
patch('openlp.core.ui.thememanager.shutil.copyfile') as mocked_copyfile, \
patch('openlp.core.ui.thememanager.check_directory_exists') as mocked_check_directory_exists:
mocked_open.return_value = MagicMock()
theme_manager = ThemeManager(None)
theme_manager.old_background_image = None
theme_manager.generate_and_save_image = MagicMock()
theme_manager.path = ''
mocked_theme = MagicMock()
mocked_theme.theme_name = 'themename'
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
file_name1 = os.path.join(TEST_RESOURCES_PATH, 'church.jpg')
# Do replacement from end of string to avoid problems with path start
file_name2 = file_name1[::-1].replace(os.sep, os.sep + os.sep, 2)[::-1]
theme_manager._write_theme(mocked_theme, file_name1, file_name2)
# THEN: The mocked_copyfile should not have been called
self.assertFalse(mocked_copyfile.called, 'shutil.copyfile should not be called')
def write_theme_diff_images_test(self):
"""
Test that we do overwrite a theme background image when a new is submitted
"""
# GIVEN: A new theme manager instance, with mocked builtins.open, shutil.copyfile,
# theme, check_directory_exists and thememanager-attributes.
with patch('builtins.open') as mocked_open, \
patch('openlp.core.ui.thememanager.shutil.copyfile') as mocked_copyfile, \
patch('openlp.core.ui.thememanager.check_directory_exists') as mocked_check_directory_exists:
mocked_open.return_value = MagicMock()
theme_manager = ThemeManager(None)
theme_manager.old_background_image = None
theme_manager.generate_and_save_image = MagicMock()
theme_manager.path = ''
mocked_theme = MagicMock()
mocked_theme.theme_name = 'themename'
mocked_theme.extract_formatted_xml = MagicMock()
mocked_theme.extract_formatted_xml.return_value = 'fake_theme_xml'.encode()
# WHEN: Calling _write_theme with path to different images
file_name1 = os.path.join(TEST_RESOURCES_PATH, 'church.jpg')
file_name2 = os.path.join(TEST_RESOURCES_PATH, 'church2.jpg')
theme_manager._write_theme(mocked_theme, file_name1, file_name2)
# THEN: The mocked_copyfile should not have been called
self.assertTrue(mocked_copyfile.called, 'shutil.copyfile should be called')

View File

@ -50,7 +50,7 @@ class TestPowerPraiseFileImport(SongImportTestHelper):
""" """
Test that loading a PowerPraise file works correctly Test that loading a PowerPraise file works correctly
""" """
self.file_import([os.path.join(TEST_PATH, 'Näher, mein Gott zu Dir.ppl')], self.file_import([os.path.join(TEST_PATH, 'Naher, mein Gott zu Dir.ppl')],
self.load_external_result_data(os.path.join(TEST_PATH, 'Näher, mein Gott zu Dir.json'))) self.load_external_result_data(os.path.join(TEST_PATH, 'Naher, mein Gott zu Dir.json')))
self.file_import([os.path.join(TEST_PATH, 'You are so faithful.ppl')], self.file_import([os.path.join(TEST_PATH, 'You are so faithful.ppl')],
self.load_external_result_data(os.path.join(TEST_PATH, 'You are so faithful.json'))) self.load_external_result_data(os.path.join(TEST_PATH, 'You are so faithful.json')))

View File

@ -52,3 +52,5 @@ class TestProPresenterFileImport(SongImportTestHelper):
""" """
self.file_import([os.path.join(TEST_PATH, 'Amazing Grace.pro4')], self.file_import([os.path.join(TEST_PATH, 'Amazing Grace.pro4')],
self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json'))) self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))
self.file_import([os.path.join(TEST_PATH, 'Vaste Grond.pro4')],
self.load_external_result_data(os.path.join(TEST_PATH, 'Vaste Grond.json')))

View File

@ -0,0 +1,34 @@
{
"title": "Vaste Grond",
"verse_order_list": [],
"verses": [
[
"God voor U is niets onmogelijk\nHoe ongelofelijk\nU heeft alles in de hand",
"v1"
],
[
"U bent God en trekt Uw eigen plan\nU bent voor niemand bang\nVoor niets en niemand bang",
"v2"
],
[
"U houd me vast en geeft me moed\nOm door te gaan als ik niet durf\nIk wil van U zijn",
"v3"
],
[
"U geeft me kracht, en bent de vaste grond\nwaarop ik stevig sta\nik wil van U zijn, voor altijd van U zijn\nO God.",
"v4"
],
[
"Grote God, U bent uitzonderlijk\nen ondoorgrondelijk\nU biedt Uw liefde aan",
"v5"
],
[
"Wie ben ik, dat U mij ziet staan\nen met mij om wilt gaan?\nIk kan U niet weerstaan",
"v6"
],
[
"Onweerstaanbaar,\nonweerstaanbare God",
"v7"
]
]
}

File diff suppressed because one or more lines are too long