diff --git a/openlp/core/common/settings.py b/openlp/core/common/settings.py index 0bedd69b6..68b0763df 100644 --- a/openlp/core/common/settings.py +++ b/openlp/core/common/settings.py @@ -252,7 +252,8 @@ class Settings(QtCore.QSettings): 'shortcuts/blankScreen': [QtGui.QKeySequence(QtCore.Qt.Key_Period)], 'shortcuts/collapse': [QtGui.QKeySequence(QtCore.Qt.Key_Minus)], 'shortcuts/desktopScreen': [QtGui.QKeySequence(QtCore.Qt.Key_D)], - 'shortcuts/delete': [QtGui.QKeySequence(QtGui.QKeySequence.Delete), QtGui.QKeySequence(QtCore.Qt.Key_Delete)], + 'shortcuts/delete': [QtGui.QKeySequence(QtGui.QKeySequence.Delete), + QtGui.QKeySequence(QtCore.Qt.Key_Delete)], 'shortcuts/down': [QtGui.QKeySequence(QtCore.Qt.Key_Down)], 'shortcuts/editSong': [], 'shortcuts/escapeItem': [QtGui.QKeySequence(QtCore.Qt.Key_Escape)], @@ -329,7 +330,8 @@ class Settings(QtCore.QSettings): 'shortcuts/moveBottom': [QtGui.QKeySequence(QtCore.Qt.Key_End)], 'shortcuts/moveDown': [QtGui.QKeySequence(QtCore.Qt.Key_PageDown)], 'shortcuts/nextTrackItem': [], - 'shortcuts/nextItem_live': [QtGui.QKeySequence(QtCore.Qt.Key_Down), QtGui.QKeySequence(QtCore.Qt.Key_PageDown)], + 'shortcuts/nextItem_live': [QtGui.QKeySequence(QtCore.Qt.Key_Down), + QtGui.QKeySequence(QtCore.Qt.Key_PageDown)], 'shortcuts/nextItem_preview': [QtGui.QKeySequence(QtCore.Qt.Key_Down), QtGui.QKeySequence(QtCore.Qt.Key_PageDown)], 'shortcuts/nextService': [QtGui.QKeySequence(QtCore.Qt.Key_Right)], @@ -339,7 +341,8 @@ class Settings(QtCore.QSettings): QtGui.QKeySequence(QtCore.Qt.ALT + QtCore.Qt.Key_F1)], 'shortcuts/openService': [], 'shortcuts/saveService': [], - 'shortcuts/previousItem_live': [QtGui.QKeySequence(QtCore.Qt.Key_Up), QtGui.QKeySequence(QtCore.Qt.Key_PageUp)], + 'shortcuts/previousItem_live': [QtGui.QKeySequence(QtCore.Qt.Key_Up), + QtGui.QKeySequence(QtCore.Qt.Key_PageUp)], 'shortcuts/playbackPause': [], 'shortcuts/playbackPlay': [], 'shortcuts/playbackStop': [], diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index bc2a01ed4..e22b8f2ba 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -34,7 +34,7 @@ import logging from PyQt5 import QtCore, QtWidgets, QtWebKit, QtWebKitWidgets, QtOpenGL, QtGui, QtMultimedia -from openlp.core.common import Registry, RegistryProperties, OpenLPMixin, Settings, translate, is_macosx +from openlp.core.common import 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.theme import BackgroundType from openlp.core.ui import HideMode, AlertLocation @@ -90,7 +90,7 @@ class Display(QtWidgets.QGraphicsView): # OpenGL. Only white blank screen is shown on the 2nd monitor all the # time. We need to investigate more how to use OpenGL properly on Mac OS # X. - if not is_macosx(): + if not is_macosx() and not is_win(): self.setViewport(QtOpenGL.QGLWidget()) def setup(self): @@ -121,7 +121,8 @@ class Display(QtWidgets.QGraphicsView): :param event: The event to be handled """ - self.web_view.setGeometry(0, 0, self.width(), self.height()) + if hasattr(self, 'web_view'): + self.web_view.setGeometry(0, 0, self.width(), self.height()) def is_web_loaded(self, field=None): """ diff --git a/openlp/core/ui/themeform.py b/openlp/core/ui/themeform.py index 3a652cebc..cd81ec800 100644 --- a/openlp/core/ui/themeform.py +++ b/openlp/core/ui/themeform.py @@ -159,7 +159,7 @@ class ThemeForm(QtWidgets.QWizard, Ui_ThemeWizard, RegistryProperties): if not event: event = QtGui.QResizeEvent(self.size(), self.size()) QtWidgets.QWizard.resizeEvent(self, event) - if self.currentPage() == self.preview_page: + 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 diff --git a/openlp/plugins/custom/lib/mediaitem.py b/openlp/plugins/custom/lib/mediaitem.py index b5b536603..225226f7d 100644 --- a/openlp/plugins/custom/lib/mediaitem.py +++ b/openlp/plugins/custom/lib/mediaitem.py @@ -190,7 +190,7 @@ class CustomMediaItem(MediaManagerItem): if QtWidgets.QMessageBox.question( self, UiStrings().ConfirmDelete, translate('CustomPlugin.MediaItem', - 'Are you sure you want to delete the "%d" selected custom slide(s)?') %len(items), + 'Are you sure you want to delete the "%d" selected custom slide(s)?') % len(items), QtWidgets.QMessageBox.StandardButtons( QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No), QtWidgets.QMessageBox.Yes) == QtWidgets.QMessageBox.No: diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py index 251a31a71..545e14d60 100644 --- a/openlp/plugins/songs/lib/importer.py +++ b/openlp/plugins/songs/lib/importer.py @@ -153,23 +153,23 @@ class SongFormat(object): EasyWorshipDB = 6 EasyWorshipService = 7 FoilPresenter = 8 - MediaShout = 9 - OpenSong = 10 - PowerPraise = 11 - PowerSong = 12 - PresentationManager = 13 - ProPresenter = 14 - SongBeamer = 15 - SongPro = 16 - SongShowPlus = 17 - SongsOfFellowship = 18 - SundayPlus = 19 - WordsOfWorship = 20 - WorshipAssistant = 21 - WorshipCenterPro = 22 - ZionWorx = 23 - Lyrix = 24 - VideoPsalm = 25 + Lyrix = 9 + MediaShout = 10 + OpenSong = 11 + PowerPraise = 12 + PowerSong = 13 + PresentationManager = 14 + ProPresenter = 15 + SongBeamer = 16 + SongPro = 17 + SongShowPlus = 18 + SongsOfFellowship = 19 + SundayPlus = 20 + VideoPsalm = 21 + WordsOfWorship = 22 + WorshipAssistant = 23 + WorshipCenterPro = 24 + ZionWorx = 25 # Set optional attribute defaults __defaults__ = { diff --git a/openlp/plugins/songs/lib/importers/easyslides.py b/openlp/plugins/songs/lib/importers/easyslides.py index 119cb91dc..3137e2baa 100644 --- a/openlp/plugins/songs/lib/importers/easyslides.py +++ b/openlp/plugins/songs/lib/importers/easyslides.py @@ -65,7 +65,8 @@ class EasySlidesImport(SongImport): self._add_unicode_attribute('song_number', song.SongNumber) if self.song_number == '0': self.song_number = '' - self._add_authors(song) + if hasattr(song, 'Writer'): + self._add_authors(song.Writer) if hasattr(song, 'Copyright'): self._add_copyright(song.Copyright) if hasattr(song, 'LicenceAdmin1'): @@ -102,15 +103,12 @@ class EasySlidesImport(SongImport): if mandatory: self._success = False - def _add_authors(self, song): + def _add_authors(self, writer): try: - authors = str(song.Writer).split(',') - self.authors = [author.strip() for author in authors if author.strip()] - except UnicodeDecodeError: + self.parse_author(str(writer)) + except UnicodeDecodeError as e: log.exception('Unicode decode error while decoding Writer') self._success = False - except AttributeError: - pass def _add_copyright(self, element): """ @@ -234,11 +232,10 @@ class EasySlidesImport(SongImport): for [reg, vt, vn, inst] in our_verse_order: if self._list_has(verses, [reg, vt, vn, inst]): # this is false, but needs user input - lang = None versetag = '%s%s' % (vt, vn) versetags.append(versetag) lines = '\n'.join(verses[reg][vt][vn][inst]) - self.verses.append([versetag, lines, lang]) + self.add_verse(lines, versetag) SeqTypes = { 'p': 'P1', 'q': 'P2', diff --git a/openlp/plugins/songs/lib/importers/sundayplus.py b/openlp/plugins/songs/lib/importers/sundayplus.py index 9f34611c4..1f10004e7 100644 --- a/openlp/plugins/songs/lib/importers/sundayplus.py +++ b/openlp/plugins/songs/lib/importers/sundayplus.py @@ -22,6 +22,8 @@ import os import re +import logging + from openlp.plugins.songs.lib import VerseType, retrieve_windows_encoding from openlp.plugins.songs.lib import strip_rtf @@ -53,8 +55,8 @@ class SundayPlusImport(SongImport): """ Initialise the class. """ - SongImport.__init__(self, manager, **kwargs) - self.encoding = 'us-ascii' + super(SundayPlusImport, self).__init__(manager, **kwargs) + self.encoding = 'cp1252' def do_import(self): self.import_wizard.progress_bar.setMaximum(len(self.import_source)) @@ -73,7 +75,7 @@ class SundayPlusImport(SongImport): if not self.parse(file.read()): self.log_error(file.name) return - if not self.title: + if self.title == '': self.title = self.title_from_filename(file.name) if not self.finish(): self.log_error(file.name) @@ -86,7 +88,7 @@ class SundayPlusImport(SongImport): :param cell: ? :return: """ - if len(data) == 0 or data[0:1] != '[' or data[-1] != ']': + if not cell and (len(data) == 0 or data[0:1] != b'[' or data.strip()[-1:] != b']'): self.log_error('File is malformed') return False i = 1 @@ -94,31 +96,31 @@ class SundayPlusImport(SongImport): while i < len(data): # Data is held as #name: value pairs inside groups marked as []. # Now we are looking for the name. - if data[i:i + 1] == '#': - name_end = data.find(':', i + 1) - name = data[i + 1:name_end].upper() + if data[i:i + 1] == b'#': + name_end = data.find(b':', i + 1) + name = data[i + 1:name_end].decode(self.encoding).upper() i = name_end + 1 - while data[i:i + 1] == ' ': + while data[i:i + 1] == b' ': i += 1 - if data[i:i + 1] == '"': - end = data.find('"', i + 1) + if data[i:i + 1] == b'"': + end = data.find(b'"', i + 1) value = data[i + 1:end] - elif data[i:i + 1] == '[': + elif data[i:i + 1] == b'[': j = i inside_quotes = False while j < len(data): char = data[j:j + 1] - if char == '"': + if char == b'"': inside_quotes = not inside_quotes - elif not inside_quotes and char == ']': + elif not inside_quotes and char == b']': end = j + 1 break j += 1 value = data[i:end] else: - end = data.find(',', i + 1) - if data.find('(', i, end) != -1: - end = data.find(')', i) + 1 + end = data.find(b',', i + 1) + if data.find(b'(', i, end) != -1: + end = data.find(b')', i) + 1 value = data[i:end] # If we are in the main group. if not cell: @@ -129,27 +131,29 @@ class SundayPlusImport(SongImport): if len(author): self.add_author(author) elif name == 'COPYRIGHT': - self.copyright = self.decode(self.unescape(value)) + self.add_copyright(self.decode(self.unescape(value))) elif name[0:4] == 'CELL': self.parse(value, cell=name[4:]) # We are in a verse group. else: if name == 'MARKER_NAME': - value = value.strip() + value = self.decode(value).strip() if len(value): verse_type = VerseType.tags[VerseType.from_loose_input(value[0])] if len(value) >= 2 and value[-1] in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']: verse_type = "%s%s" % (verse_type, value[-1]) elif name == 'HOTKEY': + value = self.decode(value).strip() # HOTKEY always appears after MARKER_NAME, so it # effectively overrides MARKER_NAME, if present. if len(value) and value in list(HOTKEY_TO_VERSE_TYPE.keys()): verse_type = HOTKEY_TO_VERSE_TYPE[value] if name == 'RTF': value = self.unescape(value) + value = self.decode(value) result = strip_rtf(value, self.encoding) if result is None: - return + return False verse, self.encoding = result lines = verse.strip().split('\n') # If any line inside any verse contains CCLI or @@ -164,7 +168,7 @@ class SundayPlusImport(SongImport): self.ccli_number = int(m.group(0)) continue elif line.lower() == 'public domain': - self.copyright = 'Public Domain' + self.add_copyright('Public Domain') continue processed_lines.append(line) self.add_verse('\n'.join(processed_lines).strip(), verse_type) @@ -192,11 +196,11 @@ class SundayPlusImport(SongImport): def decode(self, blob): while True: try: - return str(blob, self.encoding) - except: + return blob.decode(self.encoding) + except Exception as e: self.encoding = retrieve_windows_encoding() def unescape(self, text): - text = text.replace('^^', '"') - text = text.replace('^', '\'') + text = text.replace(b'^^', b'"') + text = text.replace(b'^', b'\'') return text.strip() diff --git a/openlp/plugins/songs/lib/importers/videopsalm.py b/openlp/plugins/songs/lib/importers/videopsalm.py index 3a48cc800..0bc581239 100644 --- a/openlp/plugins/songs/lib/importers/videopsalm.py +++ b/openlp/plugins/songs/lib/importers/videopsalm.py @@ -28,7 +28,6 @@ import json import os from openlp.core.common import translate -from openlp.plugins.songs.lib import VerseType from openlp.plugins.songs.lib.importers.songimport import SongImport from openlp.plugins.songs.lib.db import AuthorType diff --git a/tests/functional/openlp_core_lib/test_mediamanageritem.py b/tests/functional/openlp_core_lib/test_mediamanageritem.py index a3674f591..892b67f2d 100644 --- a/tests/functional/openlp_core_lib/test_mediamanageritem.py +++ b/tests/functional/openlp_core_lib/test_mediamanageritem.py @@ -75,7 +75,6 @@ class TestMediaManagerItem(TestCase, TestMixin): self.assertTrue(mmi.has_delete_icon, 'By default a delete icon should be present') self.assertFalse(mmi.add_to_service_item, 'There should be no add_to_service icon by default') - @patch(u'openlp.core.lib.mediamanageritem.Settings') @patch(u'openlp.core.lib.mediamanageritem.MediaManagerItem.on_live_click') def on_double_clicked_go_live_test(self, mocked_on_live_click, MockedSettings): diff --git a/tests/functional/openlp_core_lib/test_projectordb.py b/tests/functional/openlp_core_lib/test_projectordb.py index 3559e9e8c..58eff13bc 100644 --- a/tests/functional/openlp_core_lib/test_projectordb.py +++ b/tests/functional/openlp_core_lib/test_projectordb.py @@ -185,4 +185,3 @@ class TestProjectorDB(TestCase): # THEN: Projector should have the same source entry item = self.projector.get_projector_by_id(item_id) self.assertTrue(compare_source(item.source_list[0], source)) - diff --git a/tests/functional/openlp_plugins/songs/test_easyslidesimport.py b/tests/functional/openlp_plugins/songs/test_easyslidesimport.py new file mode 100644 index 000000000..fa2391bbb --- /dev/null +++ b/tests/functional/openlp_plugins/songs/test_easyslidesimport.py @@ -0,0 +1,45 @@ +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2016 OpenLP Developers # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### +""" +This module contains tests for the EasySlides song importer. +""" + +import os + +from tests.helpers.songfileimport import SongImportTestHelper + +TEST_PATH = os.path.abspath( + os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'easyslidessongs')) + + +class TestEasySlidesFileImport(SongImportTestHelper): + + def __init__(self, *args, **kwargs): + self.importer_class_name = 'EasySlidesImport' + self.importer_module_name = 'easyslides' + super(TestEasySlidesFileImport, self).__init__(*args, **kwargs) + + def test_song_import(self): + """ + Test that loading an EasySlides file works correctly on various files + """ + self.file_import(os.path.join(TEST_PATH, 'amazing-grace.xml'), + self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json'))) diff --git a/tests/functional/openlp_plugins/songs/test_songformat.py b/tests/functional/openlp_plugins/songs/test_songformat.py index eab9760b8..0c82b049c 100644 --- a/tests/functional/openlp_plugins/songs/test_songformat.py +++ b/tests/functional/openlp_plugins/songs/test_songformat.py @@ -81,4 +81,3 @@ class TestSongFormat(TestCase): # THEN: Return all attributes that were specified self.assertEquals(len(SongFormat.get(song_format, 'canDisable', 'availability')), 2, "Did not return the correct number of attributes when retrieving multiple attributes at once") - diff --git a/tests/functional/openlp_plugins/songs/test_sundayplusimport.py b/tests/functional/openlp_plugins/songs/test_sundayplusimport.py new file mode 100644 index 000000000..3b01e6ec1 --- /dev/null +++ b/tests/functional/openlp_plugins/songs/test_sundayplusimport.py @@ -0,0 +1,51 @@ +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2016 OpenLP Developers # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### +""" +This module contains tests for the VideoPsalm song importer. +""" + +import os + +from tests.helpers.songfileimport import SongImportTestHelper +from tests.functional import patch + +TEST_PATH = os.path.abspath( + os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'sundayplussongs')) + + +class TestSundayPlusFileImport(SongImportTestHelper): + + def __init__(self, *args, **kwargs): + self.importer_class_name = 'SundayPlusImport' + self.importer_module_name = 'sundayplus' + super(TestSundayPlusFileImport, self).__init__(*args, **kwargs) + + def test_song_import(self): + """ + Test that loading an SundayPlus file works correctly on various files + """ + with patch('openlp.plugins.songs.lib.importers.sundayplus.retrieve_windows_encoding') as \ + mocked_retrieve_windows_encoding: + mocked_retrieve_windows_encoding.return_value = 'cp1252' + self.file_import([os.path.join(TEST_PATH, 'Abba Fader.ptf')], + self.load_external_result_data(os.path.join(TEST_PATH, 'abba-fader.json'))) + self.file_import([os.path.join(TEST_PATH, 'Amazing Grace.ptf')], + self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json'))) diff --git a/tests/functional/openlp_plugins/songs/test_videopsalm.py b/tests/functional/openlp_plugins/songs/test_videopsalm.py index 3baa88419..f75a67627 100644 --- a/tests/functional/openlp_plugins/songs/test_videopsalm.py +++ b/tests/functional/openlp_plugins/songs/test_videopsalm.py @@ -26,7 +26,6 @@ import os from unittest import TestCase from tests.helpers.songfileimport import SongImportTestHelper -from openlp.plugins.songs.lib.importers.opensong import OpenSongImport from openlp.core.common import Registry from tests.functional import patch, MagicMock diff --git a/tests/helpers/testmixin.py b/tests/helpers/testmixin.py index e3f7a83b7..6aaaccbf2 100644 --- a/tests/helpers/testmixin.py +++ b/tests/helpers/testmixin.py @@ -48,13 +48,17 @@ class TestMixin(object): """ Build the settings Object and initialise it """ - Settings.setDefaultFormat(Settings.IniFormat) self.fd, self.ini_file = mkstemp('.ini') - Settings().set_filename(self.ini_file) + Settings.set_filename(self.ini_file) + Settings().setDefaultFormat(Settings.IniFormat) + # Needed on windows to make sure a Settings object is available during the tests + self.setting = Settings() + Settings().setValue('themes/global theme', 'my_theme') def destroy_settings(self): """ Destroy the Settings Object """ + del self.setting os.close(self.fd) os.unlink(Settings().fileName()) diff --git a/tests/interfaces/openlp_core_ui/test_projectoreditform.py b/tests/interfaces/openlp_core_ui/test_projectoreditform.py index 0f42e38ae..7518f139e 100644 --- a/tests/interfaces/openlp_core_ui/test_projectoreditform.py +++ b/tests/interfaces/openlp_core_ui/test_projectoreditform.py @@ -103,5 +103,3 @@ class TestProjectorEditForm(TestCase, TestMixin): 'Projector edit form should be marked as existing entry') self.assertTrue((item.ip is TEST1_DATA['ip'] and item.name is TEST1_DATA['name']), 'Projector edit form should have TEST1_DATA() instance to edit') - - diff --git a/tests/resources/easyslidessongs/Amazing Grace.json b/tests/resources/easyslidessongs/Amazing Grace.json new file mode 100644 index 000000000..10579e652 --- /dev/null +++ b/tests/resources/easyslidessongs/Amazing Grace.json @@ -0,0 +1,32 @@ +{ + "title": "Amazing Grace", + "authors": [ + "John Newton (1725-1807)" + ], + "verses": [ + [ + "Amazing grace! How sweet the sound\nThat saved a wretch like me;\nI once was lost, but now am found,\nWas blind, but now I see.", + "V1" + ], + [ + "'Twas grace that taught my heart to fear,\nAnd grace my fears relieved;\nHow precious did that grace appear,\nThe hour I first believed!", + "V2" + ], + [ + "Through many dangers, toils and snares\nI have already come;\n'Tis grace that brought me safe thus far,\nAnd grace will lead me home.", + "V3" + ], + [ + "The Lord has promised good to me,\nHis word my hope secures;\nHe will my shield and portion be\nAs long as life endures.", + "V4" + ], + [ + "Yes, when this heart and flesh shall fail,\nAnd mortal life shall cease,\nI shall possess within the veil\nA life of joy and peace.", + "V5" + ], + [ + "When we've been there a thousand years,\nBright shining as the sun,\nWe've no less days to sing God's praise\nThan when we first begun.", + "V6" + ] + ] +} diff --git a/tests/resources/easyslidessongs/amazing-grace.xml b/tests/resources/easyslidessongs/amazing-grace.xml new file mode 100644 index 000000000..209fe1fc6 --- /dev/null +++ b/tests/resources/easyslidessongs/amazing-grace.xml @@ -0,0 +1,53 @@ + + + + Amazing Grace + + English + 0 + [1] +Amazing grace! How sweet the sound +That saved a wretch like me; +I once was lost, but now am found, +Was blind, but now I see. +[2] +'Twas grace that taught my heart to fear, +And grace my fears relieved; +How precious did that grace appear, +The hour I first believed! +[3] +Through many dangers, toils and snares +I have already come; +'Tis grace that brought me safe thus far, +And grace will lead me home. +[4] +The Lord has promised good to me, +His word my hope secures; +He will my shield and portion be +As long as life endures. +[5] +Yes, when this heart and flesh shall fail, +And mortal life shall cease, +I shall possess within the veil +A life of joy and peace. +[6] +When we've been there a thousand years, +Bright shining as the sun, +We've no less days to sing God's praise +Than when we first begun. + + + John Newton (1725-1807) + + + + + -1 + Public Domain + + SF19, MP31, TS18 + + + + + diff --git a/tests/resources/sundayplussongs/Abba Fader.ptf b/tests/resources/sundayplussongs/Abba Fader.ptf new file mode 100644 index 000000000..28dc36cb3 --- /dev/null +++ b/tests/resources/sundayplussongs/Abba Fader.ptf @@ -0,0 +1,8 @@ +[#PTFVersion: 2, #GLOBAL_RECT: rect(47,2,1026,770), #opacity: 100, #SHADOW_ON: 0, #SHADOW_COLOR: rgb( 0, 0, 0), #SHADOW_OPACITY: 100, #SHADOW_POSITION: "RB", #SHADOW_OFFSET: [0, 0], #FILE_TYPE: "Song", #title: "Abba Fader", #Author: "Okänd", #Copyright: "ccc", #CELL1: [#MARKER_NAME: "Abba Fader", #Hotkey: "1", #rtf: "{\rtf1\ansi\ansicpg1252\deff0\deflang1053{\fonttbl{\f0\froman\fprq2\fcharset0 Verdana;}{\f1\froman\fcharset0 Verdana;}} +{\colortbl ;\red255\green255\blue0;\red224\green223\blue227;} +\viewkind4\uc1\pard\cf1\b\f0\fs86 Abba Fader\par +\par +Vi \^e4r h\^e4r f\^f6r att prisa Dig\line Vi \^e4r h\^e4r med f\^f6rv\^e4ntan\line Vi \^e4r h\^e4r som ett enat folk\line Vi kommer fram till Dig\line Med v\^e5r lovs\^e5ng\line\fs59\line\fs86 Vi ropar Abba Fader\line Du som har all makt\line Vi ropar Abba Fader\line Till Dig st\^e5r allt v\^e5rt hopp\line Vi ropar Abba Fader\line V\^e5r fr\^e4lsare, befriare \^e4r Du\b0\line\pard\tx720\f1\par +\cf2\par +} +", #Align: #Left]] \ No newline at end of file diff --git a/tests/resources/sundayplussongs/Amazing Grace.json b/tests/resources/sundayplussongs/Amazing Grace.json new file mode 100644 index 000000000..a8be7accb --- /dev/null +++ b/tests/resources/sundayplussongs/Amazing Grace.json @@ -0,0 +1,26 @@ +{ + "title": "Amazing Grace", + "authors": [ + "John Newton" + ], + "copyright": "Public Domain", + "cclinumber": "1234", + "verses": [ + [ + "Amazing grace how sweet the sound\nThat saved a wretch like me;\nI once was lost, but now am found,\nWas blind, but now I see.", + "v" + ], + [ + "’Twas grace that taught my heart to fear,\nAnd grace my fears relieved;\nHow precious did that grace appear,\nThe hour I first believed!", + "v" + ], + [ + "Through many dangers, toils and snares\nI have already come;\n’Tis grace hath brought me safe thus far,\nAnd grace will lead me home.", + "v" + ], + [ + "When we’ve been there ten thousand years,\nBright shining as the sun,\nWe’ve no less days to sing God’s praise\nThan when we first begun.", + "v" + ] + ] +} diff --git a/tests/resources/sundayplussongs/Amazing Grace.ptf b/tests/resources/sundayplussongs/Amazing Grace.ptf new file mode 100644 index 000000000..568f2d7f6 --- /dev/null +++ b/tests/resources/sundayplussongs/Amazing Grace.ptf @@ -0,0 +1,43 @@ +[#GLOBAL_RECT: rect(100, 150, 900, 1024), #Opacity: 100, #SHADOW_ON: 1, #SHADOW_COLOR: rgb( 0, 0, 0 ), #SHADOW_OPACITY: 100, #SHADOW_POSITION: "RB", #SHADOW_OFFSET: [4, 4], #FILE_TYPE: "Song", #title: "", #Author: "John Newton", #Copyright: "Public Domain", #CCLI: "1234", #Cell1: [#rtf: "{\rtf1\ansi\deff0 {\fonttbl{\f0\fswiss Arial;}{\f1\fmodern Monotype Corsiva;}{\f2\fswiss MS Serif;}{\f3\fnil Verdana;}}{\colortbl +\red0\green0\blue0;\red0\green0\blue224;\red224\green0\blue0;\red224\green0\blue224;\red102\green102\blue153;\red51\green153\blue102; +\red0\green255\blue0;\red255\green255\blue0;\red248\green248\blue248;}{\stylesheet{\s0\fs24\ql\li0\ri0\fi0\sb0\sa0\sl0 Normal;}{\s2 +\fs24\ql\li0\ri0\fi0\sb0\sa0\sl0 Normal Text;}{\s3\fs24\ql\li0\ri0\fi0\sb0\sa0\sl0 Plain Text;}{\s4\fs130\cf4\ql\li0\ri0\fi0\sb0\sa0 +\sl0 heading 1;}{\s5\fs192\cf5\ql\li0\ri0\fi0\sb0\sa0\sl0 heading 2;}{\s6\fs96\cf4\ql\li0\ri0\fi0\sb0\sa0\sl0 Body Text;}{\s7\b\fs96 +\cf6\ql\li0\ri0\fi0\sb0\sa0\sl0 Author;}{\s8\b\fs40\ql\li0\ri0\fi0\sb0\sa0\sl0 CCLI;}{\s9\b\fs40\ql\li0\ri0\fi0\sb0\sa0\sl0 Copyright;} +{\s10\fs120\cf7\ql\li0\ri0\fi0\sb0\sa0\sl0 Lyrics;}{\s11\b\f1\fs144\ql\li0\ri0\fi0\sb0\sa0\sl0 Title;}{\s12\f2\fs16 02 VERSES;}{\s13 +\f2\fs16 03 CHORUS (itals);}{\s14\f2\fs12 01a ATTRIBUTION (1 fig);}{\s15\f2\fs12 01b ATTRIBUTION (2 fig);}{\s16\f2\fs12 01c ATTRIBUTION (3 fig);} +{\s17\f2\fs12 01d ATTRIBUTION (4 fig);}}\margl1800 \margr1800 \margt1440 \margb1440 \pard \f0\fs24{\pard \s12\b\f3\fs96\cf8\ql\li0 +\ri0\fi0\sb0\sa0\sl0 Amazing grace how sweet the sound\par +That saved a wretch like me;\par +I once was lost, but now am found,\par +Was blind, but now I see.\par +\par +}}", #Align: #left, #MARKER_NAME: "AMAZING GRACE", #Hotkey: "1"], #Cell2: [#rtf: "{\rtf1\ansi\deff0 {\fonttbl{\f0\fswiss Arial;}{\f1\fmodern Monotype Corsiva;}{\f2\fswiss MS Serif;}{\f3\fnil Verdana;}}{\colortbl +\red0\green0\blue0;\red0\green0\blue224;\red224\green0\blue0;\red224\green0\blue224;\red102\green102\blue153;\red51\green153\blue102; +\red0\green255\blue0;\red255\green255\blue0;\red248\green248\blue248;}{\stylesheet{\s0\fs24\ql\li0\ri0\fi0\sb0\sa0\sl0 Normal Text;} +{\s2\fs24\ql\li0\ri0\fi0\sb0\sa0\sl0 Normal;}{\s3\fs24\ql\li0\ri0\fi0\sb0\sa0\sl0 Plain Text;}{\s4\fs130\cf4\ql\li0\ri0\fi0\sb0\sa0 +\sl0 heading 1;}{\s5\fs192\cf5\ql\li0\ri0\fi0\sb0\sa0\sl0 heading 2;}{\s6\fs96\cf4\ql\li0\ri0\fi0\sb0\sa0\sl0 Body Text;}{\s7\b\fs96 +\cf6 Author;}{\s8\b\fs40 CCLI;}{\s9\b\fs40 Copyright;}{\s10\fs120\cf7 Lyrics;}{\s11\b\f1\fs144 Title;}{\s12\f2\fs16 02 VERSES;}}\margl1800 +\margr1800 \margt1440 \margb1440 \pard \f0\fs24{\b\f3\fs96\cf8 \^92Twas grace that taught my heart to fear,\par +And grace my fears relieved;\par +How precious did that grace appear,\par +The hour I first believed!\par +\par +}}", #Align: #left, #MARKER_NAME: "AMAZING GRACE", #Hotkey: "2"], #Cell3: [#rtf: "{\rtf1\ansi\deff0 {\fonttbl{\f0\fswiss Arial;}{\f1\fmodern Monotype Corsiva;}{\f2\fswiss MS Serif;}{\f3\fnil Verdana;}}{\colortbl +\red0\green0\blue0;\red0\green0\blue224;\red224\green0\blue0;\red224\green0\blue224;\red102\green102\blue153;\red51\green153\blue102; +\red0\green255\blue0;\red255\green255\blue0;\red248\green248\blue248;}{\stylesheet{\s0\fs24\ql\li0\ri0\fi0\sb0\sa0\sl0 Normal Text;} +{\s2\fs24\ql\li0\ri0\fi0\sb0\sa0\sl0 Normal;}{\s3\fs24\ql\li0\ri0\fi0\sb0\sa0\sl0 Plain Text;}{\s4\fs130\cf4\ql\li0\ri0\fi0\sb0\sa0 +\sl0 heading 1;}{\s5\fs192\cf5\ql\li0\ri0\fi0\sb0\sa0\sl0 heading 2;}{\s6\fs96\cf4\ql\li0\ri0\fi0\sb0\sa0\sl0 Body Text;}{\s7\b\fs96 +\cf6 Author;}{\s8\b\fs40 CCLI;}{\s9\b\fs40 Copyright;}{\s10\fs120\cf7 Lyrics;}{\s11\b\f1\fs144 Title;}{\s12\f2\fs16 02 VERSES;}}\margl1800 +\margr1800 \margt1440 \margb1440 \pard \f0\fs24{\b\f3\fs96\cf8 Through many dangers, toils and snares\par +I have already come;\par +\^92Tis grace hath brought me safe thus far,\par +And grace will lead me home.\par +\par +}}", #Align: #left, #MARKER_NAME: "AMAZING GRACE", #Hotkey: "3"], #CELL4: [#rtf: "{\rtf1\ansi\deff0 {\fonttbl{\f0\fswiss Arial;}{\f1\fnil Verdana;}}{\colortbl\red0\green0\blue0;\red0\green0\blue224;\red224\green0 +\blue0;\red224\green0\blue224;\red248\green248\blue248;}{\stylesheet{\s0\fs24 Normal Text;}}\margl1800 \margr1800 \margt1440 \margb1440 +\pard \f0\fs24{\b\f1\fs96\cf4 When we\^92ve been there ten thousand years,\par +Bright shining as the sun,\par +We\^92ve no less days to sing God\^92s praise\par +Than when we first begun.\par +}}", #Align: #left, #MARKER_NAME: "AMAZING GRACE", #Hotkey: "4"], #CELL5: [:]] diff --git a/tests/resources/sundayplussongs/abba-fader.json b/tests/resources/sundayplussongs/abba-fader.json new file mode 100644 index 000000000..7172872e5 --- /dev/null +++ b/tests/resources/sundayplussongs/abba-fader.json @@ -0,0 +1,13 @@ +{ + "authors": [ + ["Okänd"] + ], + "title": "Abba Fader", + "verse_order_list": [], + "verses": [ + [ + "Abba Fader\n\nVi är här för att prisa Dig\nVi är här med förväntan\nVi är här som ett enat folk\nVi kommer fram till Dig\nMed vÃ¥r lovsÃ¥ng\n\nVi ropar Abba Fader\nDu som har all makt\nVi ropar Abba Fader\nTill Dig stÃ¥r allt vÃ¥rt hopp\nVi ropar Abba Fader\nVÃ¥r frälsare, befriare är Du", + "v1" + ] + ] +}