forked from openlp/openlp
trunk
This commit is contained in:
commit
c50619212d
@ -286,6 +286,7 @@ class Settings(QtCore.QSettings):
|
|||||||
'themes/last directory export': '',
|
'themes/last directory export': '',
|
||||||
'themes/last directory import': '',
|
'themes/last directory import': '',
|
||||||
'themes/theme level': ThemeLevel.Song,
|
'themes/theme level': ThemeLevel.Song,
|
||||||
|
'themes/wrap footer': False,
|
||||||
'user interface/live panel': True,
|
'user interface/live panel': True,
|
||||||
'user interface/live splitter geometry': QtCore.QByteArray(),
|
'user interface/live splitter geometry': QtCore.QByteArray(),
|
||||||
'user interface/lock panel': False,
|
'user interface/lock panel': False,
|
||||||
|
@ -96,9 +96,10 @@ def upgrade_db(url, upgrade):
|
|||||||
mapper(Metadata, metadata_table)
|
mapper(Metadata, metadata_table)
|
||||||
version_meta = session.query(Metadata).get('version')
|
version_meta = session.query(Metadata).get('version')
|
||||||
if version_meta is None:
|
if version_meta is None:
|
||||||
version_meta = Metadata.populate(key='version', value='0')
|
# Tables have just been created - fill the version field with the most recent version
|
||||||
|
version = upgrade.__version__
|
||||||
|
version_meta = Metadata.populate(key='version', value=version)
|
||||||
session.add(version_meta)
|
session.add(version_meta)
|
||||||
version = 0
|
|
||||||
else:
|
else:
|
||||||
version = int(version_meta.value)
|
version = int(version_meta.value)
|
||||||
if version > upgrade.__version__:
|
if version > upgrade.__version__:
|
||||||
|
@ -398,6 +398,7 @@ import logging
|
|||||||
|
|
||||||
from PyQt4 import QtWebKit
|
from PyQt4 import QtWebKit
|
||||||
|
|
||||||
|
from openlp.core.common import Settings
|
||||||
from openlp.core.lib.theme import BackgroundType, BackgroundGradientType, VerticalType, HorizontalType
|
from openlp.core.lib.theme import BackgroundType, BackgroundGradientType, VerticalType, HorizontalType
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@ -750,12 +751,13 @@ def build_footer_css(item, height):
|
|||||||
font-size: %spt;
|
font-size: %spt;
|
||||||
color: %s;
|
color: %s;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
white-space: nowrap;
|
white-space: %s;
|
||||||
"""
|
"""
|
||||||
theme = item.theme_data
|
theme = item.theme_data
|
||||||
if not theme or not item.footer:
|
if not theme or not item.footer:
|
||||||
return ''
|
return ''
|
||||||
bottom = height - int(item.footer.y()) - int(item.footer.height())
|
bottom = height - int(item.footer.y()) - int(item.footer.height())
|
||||||
|
whitespace = 'normal' if Settings().value('themes/wrap footer') else 'nowrap'
|
||||||
lyrics_html = style % (item.footer.x(), bottom, item.footer.width(),
|
lyrics_html = style % (item.footer.x(), bottom, item.footer.width(),
|
||||||
theme.font_footer_name, theme.font_footer_size, theme.font_footer_color)
|
theme.font_footer_name, theme.font_footer_size, theme.font_footer_color, whitespace)
|
||||||
return lyrics_html
|
return lyrics_html
|
||||||
|
@ -993,7 +993,7 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage
|
|||||||
service_item.auto_play_slides_once = False
|
service_item.auto_play_slides_once = False
|
||||||
self.set_modified()
|
self.set_modified()
|
||||||
|
|
||||||
def on_auto_start(self):
|
def on_auto_start(self, field=None):
|
||||||
"""
|
"""
|
||||||
Toggles to Auto Start Setting.
|
Toggles to Auto Start Setting.
|
||||||
"""
|
"""
|
||||||
|
@ -384,16 +384,8 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager, R
|
|||||||
self.application.set_busy_cursor()
|
self.application.set_busy_cursor()
|
||||||
if path:
|
if path:
|
||||||
Settings().setValue(self.settings_section + '/last directory export', path)
|
Settings().setValue(self.settings_section + '/last directory export', path)
|
||||||
theme_path = os.path.join(path, theme + '.otz')
|
|
||||||
theme_zip = None
|
|
||||||
try:
|
try:
|
||||||
theme_zip = zipfile.ZipFile(theme_path, 'w')
|
self._export_theme(path, theme)
|
||||||
source = os.path.join(self.path, theme)
|
|
||||||
for files in os.walk(source):
|
|
||||||
for name in files[2]:
|
|
||||||
theme_zip.write(
|
|
||||||
os.path.join(source, name).encode('utf-8'), os.path.join(theme, name).encode('utf-8')
|
|
||||||
)
|
|
||||||
QtGui.QMessageBox.information(self,
|
QtGui.QMessageBox.information(self,
|
||||||
translate('OpenLP.ThemeManager', 'Theme Exported'),
|
translate('OpenLP.ThemeManager', 'Theme Exported'),
|
||||||
translate('OpenLP.ThemeManager',
|
translate('OpenLP.ThemeManager',
|
||||||
@ -403,11 +395,29 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager, R
|
|||||||
critical_error_message_box(translate('OpenLP.ThemeManager', 'Theme Export Failed'),
|
critical_error_message_box(translate('OpenLP.ThemeManager', 'Theme Export Failed'),
|
||||||
translate('OpenLP.ThemeManager',
|
translate('OpenLP.ThemeManager',
|
||||||
'Your theme could not be exported due to an error.'))
|
'Your theme could not be exported due to an error.'))
|
||||||
finally:
|
|
||||||
if theme_zip:
|
|
||||||
theme_zip.close()
|
|
||||||
self.application.set_normal_cursor()
|
self.application.set_normal_cursor()
|
||||||
|
|
||||||
|
def _export_theme(self, path, theme):
|
||||||
|
"""
|
||||||
|
Create the zipfile with the theme contents.
|
||||||
|
:param path: Location where the zip file will be placed
|
||||||
|
:param theme: The name of the theme to be exported
|
||||||
|
"""
|
||||||
|
theme_path = os.path.join(path, theme + '.otz')
|
||||||
|
try:
|
||||||
|
theme_zip = zipfile.ZipFile(theme_path, 'w')
|
||||||
|
source = os.path.join(self.path, theme)
|
||||||
|
for files in os.walk(source):
|
||||||
|
for name in files[2]:
|
||||||
|
theme_zip.write(os.path.join(source, name), os.path.join(theme, name))
|
||||||
|
except (IOError, OSError):
|
||||||
|
if theme_zip:
|
||||||
|
theme_zip.close()
|
||||||
|
shutil.rmtree(theme_path, True)
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
theme_zip.close()
|
||||||
|
|
||||||
def on_import_theme(self, field=None):
|
def on_import_theme(self, field=None):
|
||||||
"""
|
"""
|
||||||
Opens a file dialog to select the theme file(s) to import before attempting to extract OpenLP themes from
|
Opens a file dialog to select the theme file(s) to import before attempting to extract OpenLP themes from
|
||||||
@ -650,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))
|
||||||
|
@ -69,6 +69,14 @@ class ThemesTab(SettingsTab):
|
|||||||
self.default_list_view.setObjectName('default_list_view')
|
self.default_list_view.setObjectName('default_list_view')
|
||||||
self.global_group_box_layout.addWidget(self.default_list_view)
|
self.global_group_box_layout.addWidget(self.default_list_view)
|
||||||
self.left_layout.addWidget(self.global_group_box)
|
self.left_layout.addWidget(self.global_group_box)
|
||||||
|
self.universal_group_box = QtGui.QGroupBox(self.left_column)
|
||||||
|
self.universal_group_box.setObjectName('universal_group_box')
|
||||||
|
self.universal_group_box_layout = QtGui.QVBoxLayout(self.universal_group_box)
|
||||||
|
self.universal_group_box_layout.setObjectName('universal_group_box_layout')
|
||||||
|
self.wrap_footer_check_box = QtGui.QCheckBox(self.universal_group_box)
|
||||||
|
self.wrap_footer_check_box.setObjectName('wrap_footer_check_box')
|
||||||
|
self.universal_group_box_layout.addWidget(self.wrap_footer_check_box)
|
||||||
|
self.left_layout.addWidget(self.universal_group_box)
|
||||||
self.left_layout.addStretch()
|
self.left_layout.addStretch()
|
||||||
self.level_group_box = QtGui.QGroupBox(self.right_column)
|
self.level_group_box = QtGui.QGroupBox(self.right_column)
|
||||||
self.level_group_box.setObjectName('level_group_box')
|
self.level_group_box.setObjectName('level_group_box')
|
||||||
@ -112,6 +120,8 @@ class ThemesTab(SettingsTab):
|
|||||||
"""
|
"""
|
||||||
self.tab_title_visible = UiStrings().Themes
|
self.tab_title_visible = UiStrings().Themes
|
||||||
self.global_group_box.setTitle(translate('OpenLP.ThemesTab', 'Global Theme'))
|
self.global_group_box.setTitle(translate('OpenLP.ThemesTab', 'Global Theme'))
|
||||||
|
self.universal_group_box.setTitle(translate('OpenLP.ThemesTab', 'Universal Settings'))
|
||||||
|
self.wrap_footer_check_box.setText(translate('OpenLP.ThemesTab', '&Wrap footer text'))
|
||||||
self.level_group_box.setTitle(translate('OpenLP.ThemesTab', 'Theme Level'))
|
self.level_group_box.setTitle(translate('OpenLP.ThemesTab', 'Theme Level'))
|
||||||
self.song_level_radio_button.setText(translate('OpenLP.ThemesTab', 'S&ong Level'))
|
self.song_level_radio_button.setText(translate('OpenLP.ThemesTab', 'S&ong Level'))
|
||||||
self.song_level_label.setText(
|
self.song_level_label.setText(
|
||||||
@ -136,6 +146,7 @@ class ThemesTab(SettingsTab):
|
|||||||
settings.beginGroup(self.settings_section)
|
settings.beginGroup(self.settings_section)
|
||||||
self.theme_level = settings.value('theme level')
|
self.theme_level = settings.value('theme level')
|
||||||
self.global_theme = settings.value('global theme')
|
self.global_theme = settings.value('global theme')
|
||||||
|
self.wrap_footer_check_box.setChecked(settings.value('wrap footer'))
|
||||||
settings.endGroup()
|
settings.endGroup()
|
||||||
if self.theme_level == ThemeLevel.Global:
|
if self.theme_level == ThemeLevel.Global:
|
||||||
self.global_level_radio_button.setChecked(True)
|
self.global_level_radio_button.setChecked(True)
|
||||||
@ -152,6 +163,7 @@ class ThemesTab(SettingsTab):
|
|||||||
settings.beginGroup(self.settings_section)
|
settings.beginGroup(self.settings_section)
|
||||||
settings.setValue('theme level', self.theme_level)
|
settings.setValue('theme level', self.theme_level)
|
||||||
settings.setValue('global theme', self.global_theme)
|
settings.setValue('global theme', self.global_theme)
|
||||||
|
settings.setValue('wrap footer', self.wrap_footer_check_box.isChecked())
|
||||||
settings.endGroup()
|
settings.endGroup()
|
||||||
self.renderer.set_theme_level(self.theme_level)
|
self.renderer.set_theme_level(self.theme_level)
|
||||||
if self.tab_visited:
|
if self.tab_visited:
|
||||||
|
@ -374,7 +374,7 @@ def clean_song(manager, song):
|
|||||||
:param manager: The song database manager object.
|
:param manager: The song database manager object.
|
||||||
:param song: The song object.
|
:param song: The song object.
|
||||||
"""
|
"""
|
||||||
from .xml import SongXML
|
from .openlyricsxml import SongXML
|
||||||
|
|
||||||
if song.title:
|
if song.title:
|
||||||
song.title = clean_title(song.title)
|
song.title = clean_title(song.title)
|
||||||
|
@ -52,12 +52,11 @@ from .importers.zionworx import ZionWorxImport
|
|||||||
from .importers.propresenter import ProPresenterImport
|
from .importers.propresenter import ProPresenterImport
|
||||||
from .importers.worshipassistant import WorshipAssistantImport
|
from .importers.worshipassistant import WorshipAssistantImport
|
||||||
from .importers.powerpraise import PowerPraiseImport
|
from .importers.powerpraise import PowerPraiseImport
|
||||||
# Imports that might fail
|
from .importers.presentationmanager import PresentationManagerImport
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
# Imports that might fail
|
||||||
try:
|
try:
|
||||||
from .importers.songsoffellowship import SongsOfFellowshipImport
|
from .importers.songsoffellowship import SongsOfFellowshipImport
|
||||||
HAS_SOF = True
|
HAS_SOF = True
|
||||||
@ -163,16 +162,17 @@ class SongFormat(object):
|
|||||||
OpenSong = 10
|
OpenSong = 10
|
||||||
PowerPraise = 11
|
PowerPraise = 11
|
||||||
PowerSong = 12
|
PowerSong = 12
|
||||||
ProPresenter = 13
|
PresentationManager = 13
|
||||||
SongBeamer = 14
|
ProPresenter = 14
|
||||||
SongPro = 15
|
SongBeamer = 15
|
||||||
SongShowPlus = 16
|
SongPro = 16
|
||||||
SongsOfFellowship = 17
|
SongShowPlus = 17
|
||||||
SundayPlus = 18
|
SongsOfFellowship = 18
|
||||||
WordsOfWorship = 19
|
SundayPlus = 19
|
||||||
WorshipAssistant = 20
|
WordsOfWorship = 20
|
||||||
WorshipCenterPro = 21
|
WorshipAssistant = 21
|
||||||
ZionWorx = 22
|
WorshipCenterPro = 22
|
||||||
|
ZionWorx = 23
|
||||||
|
|
||||||
# Set optional attribute defaults
|
# Set optional attribute defaults
|
||||||
__defaults__ = {
|
__defaults__ = {
|
||||||
@ -282,11 +282,17 @@ class SongFormat(object):
|
|||||||
'invalidSourceMsg': translate('SongsPlugin.ImportWizardForm', 'You need to specify a valid PowerSong 1.0 '
|
'invalidSourceMsg': translate('SongsPlugin.ImportWizardForm', 'You need to specify a valid PowerSong 1.0 '
|
||||||
'database folder.')
|
'database folder.')
|
||||||
},
|
},
|
||||||
|
PresentationManager: {
|
||||||
|
'class': PresentationManagerImport,
|
||||||
|
'name': 'PresentationManager',
|
||||||
|
'prefix': 'presentationManager',
|
||||||
|
'filter': '%s (*.sng)' % translate('SongsPlugin.ImportWizardForm', 'PresentationManager Song Files')
|
||||||
|
},
|
||||||
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,
|
||||||
@ -384,6 +390,7 @@ class SongFormat(object):
|
|||||||
SongFormat.OpenSong,
|
SongFormat.OpenSong,
|
||||||
SongFormat.PowerPraise,
|
SongFormat.PowerPraise,
|
||||||
SongFormat.PowerSong,
|
SongFormat.PowerSong,
|
||||||
|
SongFormat.PresentationManager,
|
||||||
SongFormat.ProPresenter,
|
SongFormat.ProPresenter,
|
||||||
SongFormat.SongBeamer,
|
SongFormat.SongBeamer,
|
||||||
SongFormat.SongPro,
|
SongFormat.SongPro,
|
||||||
|
@ -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.
|
||||||
"""
|
"""
|
||||||
|
93
openlp/plugins/songs/lib/importers/presentationmanager.py
Normal file
93
openlp/plugins/songs/lib/importers/presentationmanager.py
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# OpenLP - Open Source Lyrics Projection #
|
||||||
|
# --------------------------------------------------------------------------- #
|
||||||
|
# Copyright (c) 2008-2013 Raoul Snyman #
|
||||||
|
# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan #
|
||||||
|
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
|
||||||
|
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
|
||||||
|
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
|
||||||
|
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||||
|
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
|
||||||
|
# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
|
||||||
|
# --------------------------------------------------------------------------- #
|
||||||
|
# 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 #
|
||||||
|
###############################################################################
|
||||||
|
"""
|
||||||
|
The :mod:`presentationmanager` module provides the functionality for importing
|
||||||
|
Presentationmanager song files into the current database.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
from lxml import objectify
|
||||||
|
|
||||||
|
from openlp.core.ui.wizard import WizardStrings
|
||||||
|
from .songimport import SongImport
|
||||||
|
|
||||||
|
|
||||||
|
class PresentationManagerImport(SongImport):
|
||||||
|
"""
|
||||||
|
The :class:`PresentationManagerImport` class provides OpenLP with the
|
||||||
|
ability to import Presentationmanager song files.
|
||||||
|
"""
|
||||||
|
def do_import(self):
|
||||||
|
self.import_wizard.progress_bar.setMaximum(len(self.import_source))
|
||||||
|
for file_path in self.import_source:
|
||||||
|
if self.stop_import_flag:
|
||||||
|
return
|
||||||
|
self.import_wizard.increment_progress_bar(WizardStrings.ImportingType % os.path.basename(file_path))
|
||||||
|
root = objectify.parse(open(file_path, 'rb')).getroot()
|
||||||
|
self.process_song(root)
|
||||||
|
|
||||||
|
def process_song(self, root):
|
||||||
|
self.set_defaults()
|
||||||
|
self.title = str(root.attributes.title)
|
||||||
|
self.add_author(str(root.attributes.author))
|
||||||
|
self.copyright = str(root.attributes.copyright)
|
||||||
|
self.ccli_number = str(root.attributes.ccli_number)
|
||||||
|
self.comments = str(root.attributes.comments)
|
||||||
|
verse_order_list = []
|
||||||
|
verse_count = {}
|
||||||
|
duplicates = []
|
||||||
|
for verse in root.verses.verse:
|
||||||
|
original_verse_def = verse.get('id')
|
||||||
|
# Presentation Manager stores duplicate verses instead of a verse order.
|
||||||
|
# We need to create the verse order from that.
|
||||||
|
is_duplicate = False
|
||||||
|
if original_verse_def in duplicates:
|
||||||
|
is_duplicate = True
|
||||||
|
else:
|
||||||
|
duplicates.append(original_verse_def)
|
||||||
|
if original_verse_def.startswith("Verse"):
|
||||||
|
verse_def = 'v'
|
||||||
|
elif original_verse_def.startswith("Chorus") or original_verse_def.startswith("Refrain"):
|
||||||
|
verse_def = 'c'
|
||||||
|
elif original_verse_def.startswith("Bridge"):
|
||||||
|
verse_def = 'b'
|
||||||
|
elif original_verse_def.startswith("End"):
|
||||||
|
verse_def = 'e'
|
||||||
|
else:
|
||||||
|
verse_def = 'o'
|
||||||
|
if not is_duplicate: # Only increment verse number if no duplicate
|
||||||
|
verse_count[verse_def] = verse_count.get(verse_def, 0) + 1
|
||||||
|
verse_def = '%s%d' % (verse_def, verse_count[verse_def])
|
||||||
|
if not is_duplicate: # Only add verse if no duplicate
|
||||||
|
self.add_verse(str(verse).strip(), verse_def)
|
||||||
|
verse_order_list.append(verse_def)
|
||||||
|
|
||||||
|
self.verse_order_list = verse_order_list
|
||||||
|
if not self.finish():
|
||||||
|
self.log_error(self.import_source)
|
@ -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())
|
||||||
|
@ -33,7 +33,6 @@ backend for the Songs plugin
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from sqlalchemy import Column, ForeignKey, types
|
from sqlalchemy import Column, ForeignKey, types
|
||||||
from sqlalchemy.exc import OperationalError
|
|
||||||
from sqlalchemy.sql.expression import func, false, null, text
|
from sqlalchemy.sql.expression import func, false, null, text
|
||||||
|
|
||||||
from openlp.core.lib.db import get_upgrade_op
|
from openlp.core.lib.db import get_upgrade_op
|
||||||
@ -57,16 +56,13 @@ def upgrade_1(session, metadata):
|
|||||||
:param session:
|
:param session:
|
||||||
:param metadata:
|
:param metadata:
|
||||||
"""
|
"""
|
||||||
try:
|
op = get_upgrade_op(session)
|
||||||
op = get_upgrade_op(session)
|
op.drop_table('media_files_songs')
|
||||||
op.drop_table('media_files_songs')
|
op.add_column('media_files', Column('song_id', types.Integer(), server_default=null()))
|
||||||
op.add_column('media_files', Column('song_id', types.Integer(), server_default=null()))
|
op.add_column('media_files', Column('weight', types.Integer(), server_default=text('0')))
|
||||||
op.add_column('media_files', Column('weight', types.Integer(), server_default=text('0')))
|
if metadata.bind.url.get_dialect().name != 'sqlite':
|
||||||
if metadata.bind.url.get_dialect().name != 'sqlite':
|
# SQLite doesn't support ALTER TABLE ADD CONSTRAINT
|
||||||
# SQLite doesn't support ALTER TABLE ADD CONSTRAINT
|
op.create_foreign_key('fk_media_files_song_id', 'media_files', 'songs', ['song_id', 'id'])
|
||||||
op.create_foreign_key('fk_media_files_song_id', 'media_files', 'songs', ['song_id', 'id'])
|
|
||||||
except OperationalError:
|
|
||||||
log.info('Upgrade 1 has already been run')
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade_2(session, metadata):
|
def upgrade_2(session, metadata):
|
||||||
@ -75,12 +71,9 @@ def upgrade_2(session, metadata):
|
|||||||
|
|
||||||
This upgrade adds a create_date and last_modified date to the songs table
|
This upgrade adds a create_date and last_modified date to the songs table
|
||||||
"""
|
"""
|
||||||
try:
|
op = get_upgrade_op(session)
|
||||||
op = get_upgrade_op(session)
|
op.add_column('songs', Column('create_date', types.DateTime(), default=func.now()))
|
||||||
op.add_column('songs', Column('create_date', types.DateTime(), default=func.now()))
|
op.add_column('songs', Column('last_modified', types.DateTime(), default=func.now()))
|
||||||
op.add_column('songs', Column('last_modified', types.DateTime(), default=func.now()))
|
|
||||||
except OperationalError:
|
|
||||||
log.info('Upgrade 2 has already been run')
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade_3(session, metadata):
|
def upgrade_3(session, metadata):
|
||||||
@ -89,14 +82,11 @@ def upgrade_3(session, metadata):
|
|||||||
|
|
||||||
This upgrade adds a temporary song flag to the songs table
|
This upgrade adds a temporary song flag to the songs table
|
||||||
"""
|
"""
|
||||||
try:
|
op = get_upgrade_op(session)
|
||||||
op = get_upgrade_op(session)
|
if metadata.bind.url.get_dialect().name == 'sqlite':
|
||||||
if metadata.bind.url.get_dialect().name == 'sqlite':
|
op.add_column('songs', Column('temporary', types.Boolean(create_constraint=False), server_default=false()))
|
||||||
op.add_column('songs', Column('temporary', types.Boolean(create_constraint=False), server_default=false()))
|
else:
|
||||||
else:
|
op.add_column('songs', Column('temporary', types.Boolean(), server_default=false()))
|
||||||
op.add_column('songs', Column('temporary', types.Boolean(), server_default=false()))
|
|
||||||
except OperationalError:
|
|
||||||
log.info('Upgrade 3 has already been run')
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade_4(session, metadata):
|
def upgrade_4(session, metadata):
|
||||||
@ -105,17 +95,14 @@ def upgrade_4(session, metadata):
|
|||||||
|
|
||||||
This upgrade adds a column for author type to the authors_songs table
|
This upgrade adds a column for author type to the authors_songs table
|
||||||
"""
|
"""
|
||||||
try:
|
# Since SQLite doesn't support changing the primary key of a table, we need to recreate the table
|
||||||
# Since SQLite doesn't support changing the primary key of a table, we need to recreate the table
|
# and copy the old values
|
||||||
# and copy the old values
|
op = get_upgrade_op(session)
|
||||||
op = get_upgrade_op(session)
|
op.create_table('authors_songs_tmp',
|
||||||
op.create_table('authors_songs_tmp',
|
Column('author_id', types.Integer(), ForeignKey('authors.id'), primary_key=True),
|
||||||
Column('author_id', types.Integer(), ForeignKey('authors.id'), primary_key=True),
|
Column('song_id', types.Integer(), ForeignKey('songs.id'), primary_key=True),
|
||||||
Column('song_id', types.Integer(), ForeignKey('songs.id'), primary_key=True),
|
Column('author_type', types.String(), primary_key=True,
|
||||||
Column('author_type', types.String(), primary_key=True,
|
nullable=False, server_default=text('""')))
|
||||||
nullable=False, server_default=text('""')))
|
op.execute('INSERT INTO authors_songs_tmp SELECT author_id, song_id, "" FROM authors_songs')
|
||||||
op.execute('INSERT INTO authors_songs_tmp SELECT author_id, song_id, "" FROM authors_songs')
|
op.drop_table('authors_songs')
|
||||||
op.drop_table('authors_songs')
|
op.rename_table('authors_songs_tmp', 'authors_songs')
|
||||||
op.rename_table('authors_songs_tmp', 'authors_songs')
|
|
||||||
except OperationalError:
|
|
||||||
log.info('Upgrade 4 has already been run')
|
|
||||||
|
@ -32,7 +32,6 @@ backend for the SongsUsage plugin
|
|||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from sqlalchemy.exc import OperationalError
|
|
||||||
from sqlalchemy import Column, types
|
from sqlalchemy import Column, types
|
||||||
|
|
||||||
from openlp.core.lib.db import get_upgrade_op
|
from openlp.core.lib.db import get_upgrade_op
|
||||||
@ -50,9 +49,6 @@ def upgrade_1(session, metadata):
|
|||||||
:param session: SQLAlchemy Session object
|
:param session: SQLAlchemy Session object
|
||||||
:param metadata: SQLAlchemy MetaData object
|
:param metadata: SQLAlchemy MetaData object
|
||||||
"""
|
"""
|
||||||
try:
|
op = get_upgrade_op(session)
|
||||||
op = get_upgrade_op(session)
|
op.add_column('songusage_data', Column('plugin_name', types.Unicode(20), server_default=''))
|
||||||
op.add_column('songusage_data', Column('plugin_name', types.Unicode(20), server_default=''))
|
op.add_column('songusage_data', Column('source', types.Unicode(10), server_default=''))
|
||||||
op.add_column('songusage_data', Column('source', types.Unicode(10), server_default=''))
|
|
||||||
except OperationalError:
|
|
||||||
log.info('Upgrade 1 has already taken place')
|
|
||||||
|
@ -62,11 +62,13 @@ class OpenLPJobs(object):
|
|||||||
Branch_Pull = 'Branch-01-Pull'
|
Branch_Pull = 'Branch-01-Pull'
|
||||||
Branch_Functional = 'Branch-02-Functional-Tests'
|
Branch_Functional = 'Branch-02-Functional-Tests'
|
||||||
Branch_Interface = 'Branch-03-Interface-Tests'
|
Branch_Interface = 'Branch-03-Interface-Tests'
|
||||||
Branch_Windows = 'Branch-04-Windows_Tests'
|
Branch_Windows_Functional = 'Branch-04a-Windows_Functional_Tests'
|
||||||
|
Branch_Windows_Interface = 'Branch-04b-Windows_Interface_Tests'
|
||||||
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, 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):
|
||||||
@ -114,7 +116,9 @@ class JenkinsTrigger(object):
|
|||||||
print('%s (revision %s)' % (get_repo_name(), revno))
|
print('%s (revision %s)' % (get_repo_name(), revno))
|
||||||
|
|
||||||
for job in OpenLPJobs.Jobs:
|
for job in OpenLPJobs.Jobs:
|
||||||
self.__print_build_info(job)
|
if not self.__print_build_info(job):
|
||||||
|
print('Stopping after failure')
|
||||||
|
break
|
||||||
|
|
||||||
def open_browser(self):
|
def open_browser(self):
|
||||||
"""
|
"""
|
||||||
@ -131,6 +135,7 @@ class JenkinsTrigger(object):
|
|||||||
:param job_name: The name of the job we want the information from. For example *Branch-01-Pull*. Use the class
|
:param job_name: The name of the job we want the information from. For example *Branch-01-Pull*. Use the class
|
||||||
variables from the :class:`OpenLPJobs` class.
|
variables from the :class:`OpenLPJobs` class.
|
||||||
"""
|
"""
|
||||||
|
is_success = False
|
||||||
job = self.jenkins_instance.job(job_name)
|
job = self.jenkins_instance.job(job_name)
|
||||||
while job.info['inQueue']:
|
while job.info['inQueue']:
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
@ -139,11 +144,13 @@ class JenkinsTrigger(object):
|
|||||||
if build.info['result'] == 'SUCCESS':
|
if build.info['result'] == 'SUCCESS':
|
||||||
# Make 'SUCCESS' green.
|
# Make 'SUCCESS' green.
|
||||||
result_string = '%s%s%s' % (Colour.GREEN_START, build.info['result'], Colour.GREEN_END)
|
result_string = '%s%s%s' % (Colour.GREEN_START, build.info['result'], Colour.GREEN_END)
|
||||||
|
is_success = True
|
||||||
else:
|
else:
|
||||||
# Make 'FAILURE' red.
|
# Make 'FAILURE' red.
|
||||||
result_string = '%s%s%s' % (Colour.RED_START, build.info['result'], Colour.RED_END)
|
result_string = '%s%s%s' % (Colour.RED_START, build.info['result'], Colour.RED_END)
|
||||||
url = build.info['url']
|
url = build.info['url']
|
||||||
print('[%s] %s' % (result_string, url))
|
print('[%s] %s' % (result_string, url))
|
||||||
|
return is_success
|
||||||
|
|
||||||
|
|
||||||
def get_repo_name():
|
def get_repo_name():
|
||||||
|
@ -6,11 +6,12 @@ from unittest import TestCase
|
|||||||
|
|
||||||
from PyQt4 import QtCore
|
from PyQt4 import QtCore
|
||||||
|
|
||||||
|
from openlp.core.common import Settings
|
||||||
from openlp.core.lib.htmlbuilder import build_html, build_background_css, build_lyrics_css, build_lyrics_outline_css, \
|
from openlp.core.lib.htmlbuilder import build_html, build_background_css, build_lyrics_css, build_lyrics_outline_css, \
|
||||||
build_lyrics_format_css, build_footer_css
|
build_lyrics_format_css, build_footer_css
|
||||||
from openlp.core.lib.theme import HorizontalType, VerticalType
|
from openlp.core.lib.theme import HorizontalType, VerticalType
|
||||||
from tests.functional import MagicMock, patch
|
from tests.functional import MagicMock, patch
|
||||||
|
from tests.helpers.testmixin import TestMixin
|
||||||
|
|
||||||
HTML = """
|
HTML = """
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
@ -184,7 +185,7 @@ LYRICS_OUTLINE_CSS = ' -webkit-text-stroke: 0.125em #000000; -webkit-text-fill-c
|
|||||||
LYRICS_FORMAT_CSS = ' word-wrap: break-word; text-align: justify; vertical-align: bottom; ' + \
|
LYRICS_FORMAT_CSS = ' word-wrap: break-word; text-align: justify; vertical-align: bottom; ' + \
|
||||||
'font-family: Arial; font-size: 40pt; color: #FFFFFF; line-height: 108%; margin: 0;padding: 0; ' + \
|
'font-family: Arial; font-size: 40pt; color: #FFFFFF; line-height: 108%; margin: 0;padding: 0; ' + \
|
||||||
'padding-bottom: 0.5em; padding-left: 2px; width: 1580px; height: 810px; font-style:italic; font-weight:bold; '
|
'padding-bottom: 0.5em; padding-left: 2px; width: 1580px; height: 810px; font-style:italic; font-weight:bold; '
|
||||||
FOOTER_CSS = """
|
FOOTER_CSS_BASE = """
|
||||||
left: 10px;
|
left: 10px;
|
||||||
bottom: 0px;
|
bottom: 0px;
|
||||||
width: 1260px;
|
width: 1260px;
|
||||||
@ -192,11 +193,28 @@ FOOTER_CSS = """
|
|||||||
font-size: 12pt;
|
font-size: 12pt;
|
||||||
color: #FFFFFF;
|
color: #FFFFFF;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
white-space: nowrap;
|
white-space: %s;
|
||||||
"""
|
"""
|
||||||
|
FOOTER_CSS = FOOTER_CSS_BASE % ('nowrap')
|
||||||
|
FOOTER_CSS_WRAP = FOOTER_CSS_BASE % ('normal')
|
||||||
|
|
||||||
|
|
||||||
class Htmbuilder(TestCase):
|
class Htmbuilder(TestCase, TestMixin):
|
||||||
|
"""
|
||||||
|
Test the functions in the Htmlbuilder module
|
||||||
|
"""
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Create the UI
|
||||||
|
"""
|
||||||
|
self.build_settings()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
"""
|
||||||
|
Delete all the C++ objects at the end so that we don't have a segfault
|
||||||
|
"""
|
||||||
|
self.destroy_settings()
|
||||||
|
|
||||||
def build_html_test(self):
|
def build_html_test(self):
|
||||||
"""
|
"""
|
||||||
Test the build_html() function
|
Test the build_html() function
|
||||||
@ -225,7 +243,7 @@ class Htmbuilder(TestCase):
|
|||||||
html = build_html(item, screen, is_live, background, plugins=plugins)
|
html = build_html(item, screen, is_live, background, plugins=plugins)
|
||||||
|
|
||||||
# THEN: The returned html should match.
|
# THEN: The returned html should match.
|
||||||
assert html == HTML
|
self.assertEqual(html, HTML, 'The returned html should match')
|
||||||
|
|
||||||
def build_background_css_radial_test(self):
|
def build_background_css_radial_test(self):
|
||||||
"""
|
"""
|
||||||
@ -241,7 +259,7 @@ class Htmbuilder(TestCase):
|
|||||||
css = build_background_css(item, width)
|
css = build_background_css(item, width)
|
||||||
|
|
||||||
# THEN: The returned css should match.
|
# THEN: The returned css should match.
|
||||||
assert BACKGROUND_CSS_RADIAL == css, 'The background css should be equal.'
|
self.assertEqual(BACKGROUND_CSS_RADIAL, css, 'The background css should be equal.')
|
||||||
|
|
||||||
def build_lyrics_css_test(self):
|
def build_lyrics_css_test(self):
|
||||||
"""
|
"""
|
||||||
@ -262,7 +280,7 @@ class Htmbuilder(TestCase):
|
|||||||
css = build_lyrics_css(item)
|
css = build_lyrics_css(item)
|
||||||
|
|
||||||
# THEN: The css should be equal.
|
# THEN: The css should be equal.
|
||||||
assert LYRICS_CSS == css, 'The lyrics css should be equal.'
|
self.assertEqual(LYRICS_CSS, css, 'The lyrics css should be equal.')
|
||||||
|
|
||||||
def build_lyrics_outline_css_test(self):
|
def build_lyrics_outline_css_test(self):
|
||||||
"""
|
"""
|
||||||
@ -279,7 +297,7 @@ class Htmbuilder(TestCase):
|
|||||||
css = build_lyrics_outline_css(theme_data)
|
css = build_lyrics_outline_css(theme_data)
|
||||||
|
|
||||||
# THEN: The css should be equal.
|
# THEN: The css should be equal.
|
||||||
assert LYRICS_OUTLINE_CSS == css, 'The outline css should be equal.'
|
self.assertEqual(LYRICS_OUTLINE_CSS, css, 'The outline css should be equal.')
|
||||||
|
|
||||||
def build_lyrics_format_css_test(self):
|
def build_lyrics_format_css_test(self):
|
||||||
"""
|
"""
|
||||||
@ -302,7 +320,7 @@ class Htmbuilder(TestCase):
|
|||||||
css = build_lyrics_format_css(theme_data, width, height)
|
css = build_lyrics_format_css(theme_data, width, height)
|
||||||
|
|
||||||
# THEN: They should be equal.
|
# THEN: They should be equal.
|
||||||
assert LYRICS_FORMAT_CSS == css, 'The lyrics format css should be equal.'
|
self.assertEqual(LYRICS_FORMAT_CSS, css, 'The lyrics format css should be equal.')
|
||||||
|
|
||||||
def build_footer_css_test(self):
|
def build_footer_css_test(self):
|
||||||
"""
|
"""
|
||||||
@ -316,8 +334,27 @@ class Htmbuilder(TestCase):
|
|||||||
item.theme_data.font_footer_color = '#FFFFFF'
|
item.theme_data.font_footer_color = '#FFFFFF'
|
||||||
height = 1024
|
height = 1024
|
||||||
|
|
||||||
# WHEN: create the css.
|
# WHEN: create the css with default settings.
|
||||||
css = build_footer_css(item, height)
|
css = build_footer_css(item, height)
|
||||||
|
|
||||||
# THEN: THE css should be the same.
|
# THEN: THE css should be the same.
|
||||||
assert FOOTER_CSS == css, 'The footer strings should be equal.'
|
self.assertEqual(FOOTER_CSS, css, 'The footer strings should be equal.')
|
||||||
|
|
||||||
|
def build_footer_css_wrap_test(self):
|
||||||
|
"""
|
||||||
|
Test the build_footer_css() function
|
||||||
|
"""
|
||||||
|
# GIVEN: Create a theme.
|
||||||
|
item = MagicMock()
|
||||||
|
item.footer = QtCore.QRect(10, 921, 1260, 103)
|
||||||
|
item.theme_data.font_footer_name = 'Arial'
|
||||||
|
item.theme_data.font_footer_size = 12
|
||||||
|
item.theme_data.font_footer_color = '#FFFFFF'
|
||||||
|
height = 1024
|
||||||
|
|
||||||
|
# WHEN: Settings say that footer should wrap
|
||||||
|
Settings().setValue('themes/wrap footer', True)
|
||||||
|
css = build_footer_css(item, height)
|
||||||
|
|
||||||
|
# THEN: Footer should wrap
|
||||||
|
self.assertEqual(FOOTER_CSS_WRAP, css, 'The footer strings should be equal.')
|
||||||
|
@ -31,7 +31,8 @@ Package to test the openlp.core.ui.slidecontroller package.
|
|||||||
"""
|
"""
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
|
|
||||||
from openlp.core.common import Registry
|
from openlp.core.common import Registry, ThemeLevel
|
||||||
|
from openlp.core.lib import ServiceItem, ServiceItemType, ItemCapabilities
|
||||||
from openlp.core.ui import ServiceManager
|
from openlp.core.ui import ServiceManager
|
||||||
|
|
||||||
from tests.interfaces import MagicMock, patch
|
from tests.interfaces import MagicMock, patch
|
||||||
@ -89,3 +90,466 @@ class TestServiceManager(TestCase):
|
|||||||
self.assertEqual('txt' in service_manager.suffixes, True, 'The suffix txt should be in the list')
|
self.assertEqual('txt' in service_manager.suffixes, True, 'The suffix txt should be in the list')
|
||||||
self.assertEqual('ppt' in service_manager.suffixes, True, 'The suffix ppt should be in the list')
|
self.assertEqual('ppt' in service_manager.suffixes, True, 'The suffix ppt should be in the list')
|
||||||
self.assertEqual('pptx' in service_manager.suffixes, True, 'The suffix pptx should be in the list')
|
self.assertEqual('pptx' in service_manager.suffixes, True, 'The suffix pptx should be in the list')
|
||||||
|
|
||||||
|
def build_context_menu_test(self):
|
||||||
|
"""
|
||||||
|
Test the creation of a context menu from a null service item.
|
||||||
|
"""
|
||||||
|
# GIVEN: A new service manager instance and a default service item.
|
||||||
|
service_manager = ServiceManager(None)
|
||||||
|
item = MagicMock()
|
||||||
|
item.parent.return_value = False
|
||||||
|
item.data.return_value = 0
|
||||||
|
service_manager.service_manager_list = MagicMock()
|
||||||
|
service_manager.service_manager_list.itemAt.return_value = item
|
||||||
|
service_item = ServiceItem(None)
|
||||||
|
service_manager.service_items.insert(1, {'service_item': service_item})
|
||||||
|
service_manager.edit_action = MagicMock()
|
||||||
|
service_manager.rename_action = MagicMock()
|
||||||
|
service_manager.create_custom_action = MagicMock()
|
||||||
|
service_manager.maintain_action = MagicMock()
|
||||||
|
service_manager.notes_action = MagicMock()
|
||||||
|
service_manager.time_action = MagicMock()
|
||||||
|
service_manager.auto_start_action = MagicMock()
|
||||||
|
service_manager.auto_play_slides_menu = MagicMock()
|
||||||
|
service_manager.auto_play_slides_once = MagicMock()
|
||||||
|
service_manager.auto_play_slides_loop = MagicMock()
|
||||||
|
service_manager.timed_slide_interval = MagicMock()
|
||||||
|
service_manager.theme_menu = MagicMock()
|
||||||
|
service_manager.menu = MagicMock()
|
||||||
|
# WHEN I define a context menu
|
||||||
|
service_manager.context_menu(1)
|
||||||
|
# THEN the following calls should have occurred.
|
||||||
|
self.assertEquals(service_manager.edit_action.setVisible.call_count, 1, 'Should have been called once')
|
||||||
|
self.assertEquals(service_manager.rename_action.setVisible.call_count, 1, 'Should have been called once')
|
||||||
|
self.assertEquals(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have been called once')
|
||||||
|
self.assertEquals(service_manager.maintain_action.setVisible.call_count, 1, 'Should have been called once')
|
||||||
|
self.assertEquals(service_manager.notes_action.setVisible.call_count, 1, 'Should have been called once')
|
||||||
|
self.assertEquals(service_manager.time_action.setVisible.call_count, 1, 'Should have been called once')
|
||||||
|
self.assertEquals(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have been called once')
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1,
|
||||||
|
'Should have been called once')
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called')
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called')
|
||||||
|
self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called')
|
||||||
|
self.assertEquals(service_manager.theme_menu.menuAction().setVisible.call_count, 1,
|
||||||
|
'Should have been called once')
|
||||||
|
|
||||||
|
def build_song_context_menu_test(self):
|
||||||
|
"""
|
||||||
|
Test the creation of a context menu from service item of type text from Songs.
|
||||||
|
"""
|
||||||
|
# GIVEN: A new service manager instance and a default service item.
|
||||||
|
mocked_renderer = MagicMock()
|
||||||
|
mocked_renderer.theme_level = ThemeLevel.Song
|
||||||
|
Registry().register('plugin_manager', MagicMock())
|
||||||
|
Registry().register('renderer', mocked_renderer)
|
||||||
|
service_manager = ServiceManager(None)
|
||||||
|
item = MagicMock()
|
||||||
|
item.parent.return_value = False
|
||||||
|
item.data.return_value = 0
|
||||||
|
service_manager.service_manager_list = MagicMock()
|
||||||
|
service_manager.service_manager_list.itemAt.return_value = item
|
||||||
|
service_item = ServiceItem(None)
|
||||||
|
service_item.add_capability(ItemCapabilities.CanEdit)
|
||||||
|
service_item.add_capability(ItemCapabilities.CanPreview)
|
||||||
|
service_item.add_capability(ItemCapabilities.CanLoop)
|
||||||
|
service_item.add_capability(ItemCapabilities.OnLoadUpdate)
|
||||||
|
service_item.add_capability(ItemCapabilities.AddIfNewItem)
|
||||||
|
service_item.add_capability(ItemCapabilities.CanSoftBreak)
|
||||||
|
service_item.service_item_type = ServiceItemType.Text
|
||||||
|
service_item.edit_id = 1
|
||||||
|
service_item._display_frames.append(MagicMock())
|
||||||
|
service_manager.service_items.insert(1, {'service_item': service_item})
|
||||||
|
service_manager.edit_action = MagicMock()
|
||||||
|
service_manager.rename_action = MagicMock()
|
||||||
|
service_manager.create_custom_action = MagicMock()
|
||||||
|
service_manager.maintain_action = MagicMock()
|
||||||
|
service_manager.notes_action = MagicMock()
|
||||||
|
service_manager.time_action = MagicMock()
|
||||||
|
service_manager.auto_start_action = MagicMock()
|
||||||
|
service_manager.auto_play_slides_menu = MagicMock()
|
||||||
|
service_manager.auto_play_slides_once = MagicMock()
|
||||||
|
service_manager.auto_play_slides_loop = MagicMock()
|
||||||
|
service_manager.timed_slide_interval = MagicMock()
|
||||||
|
service_manager.theme_menu = MagicMock()
|
||||||
|
service_manager.menu = MagicMock()
|
||||||
|
# WHEN I define a context menu
|
||||||
|
service_manager.context_menu(1)
|
||||||
|
# THEN the following calls should have occurred.
|
||||||
|
self.assertEquals(service_manager.edit_action.setVisible.call_count, 2, 'Should have be called twice')
|
||||||
|
self.assertEquals(service_manager.rename_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.maintain_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1,
|
||||||
|
'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called')
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called')
|
||||||
|
self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called')
|
||||||
|
self.assertEquals(service_manager.theme_menu.menuAction().setVisible.call_count, 2,
|
||||||
|
'Should have be called twice')
|
||||||
|
# THEN we add a 2nd display frame
|
||||||
|
service_item._display_frames.append(MagicMock())
|
||||||
|
service_manager.context_menu(1)
|
||||||
|
# THEN the following additional calls should have occurred.
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 2,
|
||||||
|
'Should have be called twice')
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 1, 'Should have be called once')
|
||||||
|
|
||||||
|
def build_bible_context_menu_test(self):
|
||||||
|
"""
|
||||||
|
Test the creation of a context menu from service item of type text from Bibles.
|
||||||
|
"""
|
||||||
|
# GIVEN: A new service manager instance and a default service item.
|
||||||
|
mocked_renderer = MagicMock()
|
||||||
|
mocked_renderer.theme_level = ThemeLevel.Song
|
||||||
|
Registry().register('plugin_manager', MagicMock())
|
||||||
|
Registry().register('renderer', mocked_renderer)
|
||||||
|
service_manager = ServiceManager(None)
|
||||||
|
item = MagicMock()
|
||||||
|
item.parent.return_value = False
|
||||||
|
item.data.return_value = 0
|
||||||
|
service_manager.service_manager_list = MagicMock()
|
||||||
|
service_manager.service_manager_list.itemAt.return_value = item
|
||||||
|
service_item = ServiceItem(None)
|
||||||
|
service_item.add_capability(ItemCapabilities.NoLineBreaks)
|
||||||
|
service_item.add_capability(ItemCapabilities.CanPreview)
|
||||||
|
service_item.add_capability(ItemCapabilities.CanLoop)
|
||||||
|
service_item.add_capability(ItemCapabilities.CanWordSplit)
|
||||||
|
service_item.add_capability(ItemCapabilities.CanEditTitle)
|
||||||
|
service_item.service_item_type = ServiceItemType.Text
|
||||||
|
service_item.edit_id = 1
|
||||||
|
service_item._display_frames.append(MagicMock())
|
||||||
|
service_manager.service_items.insert(1, {'service_item': service_item})
|
||||||
|
service_manager.edit_action = MagicMock()
|
||||||
|
service_manager.rename_action = MagicMock()
|
||||||
|
service_manager.create_custom_action = MagicMock()
|
||||||
|
service_manager.maintain_action = MagicMock()
|
||||||
|
service_manager.notes_action = MagicMock()
|
||||||
|
service_manager.time_action = MagicMock()
|
||||||
|
service_manager.auto_start_action = MagicMock()
|
||||||
|
service_manager.auto_play_slides_menu = MagicMock()
|
||||||
|
service_manager.auto_play_slides_once = MagicMock()
|
||||||
|
service_manager.auto_play_slides_loop = MagicMock()
|
||||||
|
service_manager.timed_slide_interval = MagicMock()
|
||||||
|
service_manager.theme_menu = MagicMock()
|
||||||
|
service_manager.menu = MagicMock()
|
||||||
|
# WHEN I define a context menu
|
||||||
|
service_manager.context_menu(1)
|
||||||
|
# THEN the following calls should have occurred.
|
||||||
|
self.assertEquals(service_manager.edit_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.rename_action.setVisible.call_count, 2, 'Should have be called twice')
|
||||||
|
self.assertEquals(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.maintain_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1,
|
||||||
|
'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called')
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called')
|
||||||
|
self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called')
|
||||||
|
self.assertEquals(service_manager.theme_menu.menuAction().setVisible.call_count, 2,
|
||||||
|
'Should have be called twice')
|
||||||
|
# THEN we add a 2nd display frame
|
||||||
|
service_item._display_frames.append(MagicMock())
|
||||||
|
service_manager.context_menu(1)
|
||||||
|
# THEN the following additional calls should have occurred.
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 2,
|
||||||
|
'Should have be called twice')
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 1, 'Should have be called once')
|
||||||
|
|
||||||
|
def build_custom_context_menu_test(self):
|
||||||
|
"""
|
||||||
|
Test the creation of a context menu from service item of type text from Custom.
|
||||||
|
"""
|
||||||
|
# GIVEN: A new service manager instance and a default service item.
|
||||||
|
mocked_renderer = MagicMock()
|
||||||
|
mocked_renderer.theme_level = ThemeLevel.Song
|
||||||
|
Registry().register('plugin_manager', MagicMock())
|
||||||
|
Registry().register('renderer', mocked_renderer)
|
||||||
|
service_manager = ServiceManager(None)
|
||||||
|
item = MagicMock()
|
||||||
|
item.parent.return_value = False
|
||||||
|
item.data.return_value = 0
|
||||||
|
service_manager.service_manager_list = MagicMock()
|
||||||
|
service_manager.service_manager_list.itemAt.return_value = item
|
||||||
|
service_item = ServiceItem(None)
|
||||||
|
service_item.add_capability(ItemCapabilities.CanEdit)
|
||||||
|
service_item.add_capability(ItemCapabilities.CanPreview)
|
||||||
|
service_item.add_capability(ItemCapabilities.CanLoop)
|
||||||
|
service_item.add_capability(ItemCapabilities.CanSoftBreak)
|
||||||
|
service_item.add_capability(ItemCapabilities.OnLoadUpdate)
|
||||||
|
service_item.service_item_type = ServiceItemType.Text
|
||||||
|
service_item.edit_id = 1
|
||||||
|
service_item._display_frames.append(MagicMock())
|
||||||
|
service_manager.service_items.insert(1, {'service_item': service_item})
|
||||||
|
service_manager.edit_action = MagicMock()
|
||||||
|
service_manager.rename_action = MagicMock()
|
||||||
|
service_manager.create_custom_action = MagicMock()
|
||||||
|
service_manager.maintain_action = MagicMock()
|
||||||
|
service_manager.notes_action = MagicMock()
|
||||||
|
service_manager.time_action = MagicMock()
|
||||||
|
service_manager.auto_start_action = MagicMock()
|
||||||
|
service_manager.auto_play_slides_menu = MagicMock()
|
||||||
|
service_manager.auto_play_slides_once = MagicMock()
|
||||||
|
service_manager.auto_play_slides_loop = MagicMock()
|
||||||
|
service_manager.timed_slide_interval = MagicMock()
|
||||||
|
service_manager.theme_menu = MagicMock()
|
||||||
|
service_manager.menu = MagicMock()
|
||||||
|
# WHEN I define a context menu
|
||||||
|
service_manager.context_menu(1)
|
||||||
|
# THEN the following calls should have occurred.
|
||||||
|
self.assertEquals(service_manager.edit_action.setVisible.call_count, 2, 'Should have be called twice')
|
||||||
|
self.assertEquals(service_manager.rename_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.maintain_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1,
|
||||||
|
'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called')
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called')
|
||||||
|
self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called')
|
||||||
|
self.assertEquals(service_manager.theme_menu.menuAction().setVisible.call_count, 2,
|
||||||
|
'Should have be called twice')
|
||||||
|
# THEN we add a 2nd display frame
|
||||||
|
service_item._display_frames.append(MagicMock())
|
||||||
|
service_manager.context_menu(1)
|
||||||
|
# THEN the following additional calls should have occurred.
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 2,
|
||||||
|
'Should have be called twice')
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 1, 'Should have be called once')
|
||||||
|
|
||||||
|
def build_image_context_menu_test(self):
|
||||||
|
"""
|
||||||
|
Test the creation of a context menu from service item of type Image from Image.
|
||||||
|
"""
|
||||||
|
# GIVEN: A new service manager instance and a default service item.
|
||||||
|
Registry().register('plugin_manager', MagicMock())
|
||||||
|
Registry().register('renderer', MagicMock())
|
||||||
|
service_manager = ServiceManager(None)
|
||||||
|
item = MagicMock()
|
||||||
|
item.parent.return_value = False
|
||||||
|
item.data.return_value = 0
|
||||||
|
service_manager.service_manager_list = MagicMock()
|
||||||
|
service_manager.service_manager_list.itemAt.return_value = item
|
||||||
|
service_item = ServiceItem(None)
|
||||||
|
service_item.add_capability(ItemCapabilities.CanMaintain)
|
||||||
|
service_item.add_capability(ItemCapabilities.CanPreview)
|
||||||
|
service_item.add_capability(ItemCapabilities.CanLoop)
|
||||||
|
service_item.add_capability(ItemCapabilities.CanAppend)
|
||||||
|
service_item.add_capability(ItemCapabilities.CanEditTitle)
|
||||||
|
service_item.service_item_type = ServiceItemType.Image
|
||||||
|
service_item.edit_id = 1
|
||||||
|
service_item._raw_frames.append(MagicMock())
|
||||||
|
service_manager.service_items.insert(1, {'service_item': service_item})
|
||||||
|
service_manager.edit_action = MagicMock()
|
||||||
|
service_manager.rename_action = MagicMock()
|
||||||
|
service_manager.create_custom_action = MagicMock()
|
||||||
|
service_manager.maintain_action = MagicMock()
|
||||||
|
service_manager.notes_action = MagicMock()
|
||||||
|
service_manager.time_action = MagicMock()
|
||||||
|
service_manager.auto_start_action = MagicMock()
|
||||||
|
service_manager.auto_play_slides_menu = MagicMock()
|
||||||
|
service_manager.auto_play_slides_once = MagicMock()
|
||||||
|
service_manager.auto_play_slides_loop = MagicMock()
|
||||||
|
service_manager.timed_slide_interval = MagicMock()
|
||||||
|
service_manager.theme_menu = MagicMock()
|
||||||
|
service_manager.menu = MagicMock()
|
||||||
|
# WHEN I define a context menu
|
||||||
|
service_manager.context_menu(1)
|
||||||
|
# THEN the following calls should have occurred.
|
||||||
|
self.assertEquals(service_manager.edit_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.rename_action.setVisible.call_count, 2, 'Should have be called twice')
|
||||||
|
self.assertEquals(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.maintain_action.setVisible.call_count, 2, 'Should have be called twice')
|
||||||
|
self.assertEquals(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1,
|
||||||
|
'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called')
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called')
|
||||||
|
self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called')
|
||||||
|
self.assertEquals(service_manager.theme_menu.menuAction().setVisible.call_count, 1,
|
||||||
|
'Should have be called once')
|
||||||
|
# THEN we add a 2nd display frame and regenerate the menu.
|
||||||
|
service_item._raw_frames.append(MagicMock())
|
||||||
|
service_manager.context_menu(1)
|
||||||
|
# THEN the following additional calls should have occurred.
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 2,
|
||||||
|
'Should have be called twice')
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 1, 'Should have be called once')
|
||||||
|
|
||||||
|
def build_media_context_menu_test(self):
|
||||||
|
"""
|
||||||
|
Test the creation of a context menu from service item of type Command from Media.
|
||||||
|
"""
|
||||||
|
# GIVEN: A new service manager instance and a default service item.
|
||||||
|
Registry().register('plugin_manager', MagicMock())
|
||||||
|
Registry().register('renderer', MagicMock())
|
||||||
|
service_manager = ServiceManager(None)
|
||||||
|
item = MagicMock()
|
||||||
|
item.parent.return_value = False
|
||||||
|
item.data.return_value = 0
|
||||||
|
service_manager.service_manager_list = MagicMock()
|
||||||
|
service_manager.service_manager_list.itemAt.return_value = item
|
||||||
|
service_item = ServiceItem(None)
|
||||||
|
service_item.add_capability(ItemCapabilities.CanAutoStartForLive)
|
||||||
|
service_item.add_capability(ItemCapabilities.CanEditTitle)
|
||||||
|
service_item.add_capability(ItemCapabilities.RequiresMedia)
|
||||||
|
service_item.service_item_type = ServiceItemType.Command
|
||||||
|
service_item.edit_id = 1
|
||||||
|
service_item._raw_frames.append(MagicMock())
|
||||||
|
service_manager.service_items.insert(1, {'service_item': service_item})
|
||||||
|
service_manager.edit_action = MagicMock()
|
||||||
|
service_manager.rename_action = MagicMock()
|
||||||
|
service_manager.create_custom_action = MagicMock()
|
||||||
|
service_manager.maintain_action = MagicMock()
|
||||||
|
service_manager.notes_action = MagicMock()
|
||||||
|
service_manager.time_action = MagicMock()
|
||||||
|
service_manager.auto_start_action = MagicMock()
|
||||||
|
service_manager.auto_play_slides_menu = MagicMock()
|
||||||
|
service_manager.auto_play_slides_once = MagicMock()
|
||||||
|
service_manager.auto_play_slides_loop = MagicMock()
|
||||||
|
service_manager.timed_slide_interval = MagicMock()
|
||||||
|
service_manager.theme_menu = MagicMock()
|
||||||
|
service_manager.menu = MagicMock()
|
||||||
|
# WHEN I define a context menu
|
||||||
|
service_manager.context_menu(1)
|
||||||
|
# THEN the following calls should have occurred.
|
||||||
|
self.assertEquals(service_manager.edit_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.rename_action.setVisible.call_count, 2, 'Should have be called twice')
|
||||||
|
self.assertEquals(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.maintain_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.auto_start_action.setVisible.call_count, 2, 'Should have be called twice')
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1,
|
||||||
|
'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called')
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called')
|
||||||
|
self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called')
|
||||||
|
self.assertEquals(service_manager.theme_menu.menuAction().setVisible.call_count, 1,
|
||||||
|
'Should have be called once')
|
||||||
|
# THEN I change the length of the media and regenerate the menu.
|
||||||
|
service_item.set_media_length(5)
|
||||||
|
service_manager.context_menu(1)
|
||||||
|
# THEN the following additional calls should have occurred.
|
||||||
|
self.assertEquals(service_manager.time_action.setVisible.call_count, 3, 'Should have be called three times')
|
||||||
|
|
||||||
|
def build_presentation_pdf_context_menu_test(self):
|
||||||
|
"""
|
||||||
|
Test the creation of a context menu from service item of type Command with PDF from Presentation.
|
||||||
|
"""
|
||||||
|
# GIVEN: A new service manager instance and a default service item.
|
||||||
|
Registry().register('plugin_manager', MagicMock())
|
||||||
|
Registry().register('renderer', MagicMock())
|
||||||
|
service_manager = ServiceManager(None)
|
||||||
|
item = MagicMock()
|
||||||
|
item.parent.return_value = False
|
||||||
|
item.data.return_value = 0
|
||||||
|
service_manager.service_manager_list = MagicMock()
|
||||||
|
service_manager.service_manager_list.itemAt.return_value = item
|
||||||
|
service_item = ServiceItem(None)
|
||||||
|
service_item.add_capability(ItemCapabilities.CanMaintain)
|
||||||
|
service_item.add_capability(ItemCapabilities.CanPreview)
|
||||||
|
service_item.add_capability(ItemCapabilities.CanLoop)
|
||||||
|
service_item.add_capability(ItemCapabilities.CanAppend)
|
||||||
|
service_item.service_item_type = ServiceItemType.Command
|
||||||
|
service_item.edit_id = 1
|
||||||
|
service_item._raw_frames.append(MagicMock())
|
||||||
|
service_manager.service_items.insert(1, {'service_item': service_item})
|
||||||
|
service_manager.edit_action = MagicMock()
|
||||||
|
service_manager.rename_action = MagicMock()
|
||||||
|
service_manager.create_custom_action = MagicMock()
|
||||||
|
service_manager.maintain_action = MagicMock()
|
||||||
|
service_manager.notes_action = MagicMock()
|
||||||
|
service_manager.time_action = MagicMock()
|
||||||
|
service_manager.auto_start_action = MagicMock()
|
||||||
|
service_manager.auto_play_slides_menu = MagicMock()
|
||||||
|
service_manager.auto_play_slides_once = MagicMock()
|
||||||
|
service_manager.auto_play_slides_loop = MagicMock()
|
||||||
|
service_manager.timed_slide_interval = MagicMock()
|
||||||
|
service_manager.theme_menu = MagicMock()
|
||||||
|
service_manager.menu = MagicMock()
|
||||||
|
# WHEN I define a context menu
|
||||||
|
service_manager.context_menu(1)
|
||||||
|
# THEN the following calls should have occurred.
|
||||||
|
self.assertEquals(service_manager.edit_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.rename_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.maintain_action.setVisible.call_count, 2, 'Should have be called twice')
|
||||||
|
self.assertEquals(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1,
|
||||||
|
'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called')
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called')
|
||||||
|
self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called')
|
||||||
|
self.assertEquals(service_manager.theme_menu.menuAction().setVisible.call_count, 1,
|
||||||
|
'Should have be called once')
|
||||||
|
|
||||||
|
def build_presentation_non_pdf_context_menu_test(self):
|
||||||
|
"""
|
||||||
|
Test the creation of a context menu from service item of type Command with Impress from Presentation.
|
||||||
|
"""
|
||||||
|
# GIVEN: A new service manager instance and a default service item.
|
||||||
|
Registry().register('plugin_manager', MagicMock())
|
||||||
|
Registry().register('renderer', MagicMock())
|
||||||
|
service_manager = ServiceManager(None)
|
||||||
|
item = MagicMock()
|
||||||
|
item.parent.return_value = False
|
||||||
|
item.data.return_value = 0
|
||||||
|
service_manager.service_manager_list = MagicMock()
|
||||||
|
service_manager.service_manager_list.itemAt.return_value = item
|
||||||
|
service_item = ServiceItem(None)
|
||||||
|
service_item.add_capability(ItemCapabilities.ProvidesOwnDisplay)
|
||||||
|
service_item.service_item_type = ServiceItemType.Command
|
||||||
|
service_item.edit_id = 1
|
||||||
|
service_item._raw_frames.append(MagicMock())
|
||||||
|
service_manager.service_items.insert(1, {'service_item': service_item})
|
||||||
|
service_manager.edit_action = MagicMock()
|
||||||
|
service_manager.rename_action = MagicMock()
|
||||||
|
service_manager.create_custom_action = MagicMock()
|
||||||
|
service_manager.maintain_action = MagicMock()
|
||||||
|
service_manager.notes_action = MagicMock()
|
||||||
|
service_manager.time_action = MagicMock()
|
||||||
|
service_manager.auto_start_action = MagicMock()
|
||||||
|
service_manager.auto_play_slides_menu = MagicMock()
|
||||||
|
service_manager.auto_play_slides_once = MagicMock()
|
||||||
|
service_manager.auto_play_slides_loop = MagicMock()
|
||||||
|
service_manager.timed_slide_interval = MagicMock()
|
||||||
|
service_manager.theme_menu = MagicMock()
|
||||||
|
service_manager.menu = MagicMock()
|
||||||
|
# WHEN I define a context menu
|
||||||
|
service_manager.context_menu(1)
|
||||||
|
# THEN the following calls should have occurred.
|
||||||
|
self.assertEquals(service_manager.edit_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.rename_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.maintain_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1,
|
||||||
|
'Should have be called once')
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called')
|
||||||
|
self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called')
|
||||||
|
self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called')
|
||||||
|
self.assertEquals(service_manager.theme_menu.menuAction().setVisible.call_count, 1,
|
||||||
|
'Should have be called once')
|
||||||
|
@ -504,21 +504,20 @@ class TestSlideController(TestCase):
|
|||||||
mocked_item = MagicMock()
|
mocked_item = MagicMock()
|
||||||
mocked_item.is_command.return_value = True
|
mocked_item.is_command.return_value = True
|
||||||
mocked_item.name = 'Mocked Item'
|
mocked_item.name = 'Mocked Item'
|
||||||
mocked_execute = MagicMock()
|
|
||||||
mocked_update_preview = MagicMock()
|
mocked_update_preview = MagicMock()
|
||||||
mocked_preview_widget = MagicMock()
|
mocked_preview_widget = MagicMock()
|
||||||
mocked_slide_selected = MagicMock()
|
mocked_slide_selected = MagicMock()
|
||||||
Registry.execute = mocked_execute
|
with patch.object(Registry, 'execute') as mocked_execute:
|
||||||
Registry.create()
|
Registry.create()
|
||||||
slide_controller = SlideController(None)
|
slide_controller = SlideController(None)
|
||||||
slide_controller.service_item = mocked_item
|
slide_controller.service_item = mocked_item
|
||||||
slide_controller.update_preview = mocked_update_preview
|
slide_controller.update_preview = mocked_update_preview
|
||||||
slide_controller.preview_widget = mocked_preview_widget
|
slide_controller.preview_widget = mocked_preview_widget
|
||||||
slide_controller.slide_selected = mocked_slide_selected
|
slide_controller.slide_selected = mocked_slide_selected
|
||||||
slide_controller.is_live = True
|
slide_controller.is_live = True
|
||||||
|
|
||||||
# WHEN: The method is called
|
# WHEN: The method is called
|
||||||
slide_controller.on_slide_selected_index([9])
|
slide_controller.on_slide_selected_index([9])
|
||||||
|
|
||||||
# THEN: It should have sent a notification
|
# THEN: It should have sent a notification
|
||||||
mocked_item.is_command.assert_called_once_with()
|
mocked_item.is_command.assert_called_once_with()
|
||||||
@ -535,20 +534,19 @@ class TestSlideController(TestCase):
|
|||||||
mocked_item = MagicMock()
|
mocked_item = MagicMock()
|
||||||
mocked_item.is_command.return_value = False
|
mocked_item.is_command.return_value = False
|
||||||
mocked_item.name = 'Mocked Item'
|
mocked_item.name = 'Mocked Item'
|
||||||
mocked_execute = MagicMock()
|
|
||||||
mocked_update_preview = MagicMock()
|
mocked_update_preview = MagicMock()
|
||||||
mocked_preview_widget = MagicMock()
|
mocked_preview_widget = MagicMock()
|
||||||
mocked_slide_selected = MagicMock()
|
mocked_slide_selected = MagicMock()
|
||||||
Registry.execute = mocked_execute
|
with patch.object(Registry, 'execute') as mocked_execute:
|
||||||
Registry.create()
|
Registry.create()
|
||||||
slide_controller = SlideController(None)
|
slide_controller = SlideController(None)
|
||||||
slide_controller.service_item = mocked_item
|
slide_controller.service_item = mocked_item
|
||||||
slide_controller.update_preview = mocked_update_preview
|
slide_controller.update_preview = mocked_update_preview
|
||||||
slide_controller.preview_widget = mocked_preview_widget
|
slide_controller.preview_widget = mocked_preview_widget
|
||||||
slide_controller.slide_selected = mocked_slide_selected
|
slide_controller.slide_selected = mocked_slide_selected
|
||||||
|
|
||||||
# WHEN: The method is called
|
# WHEN: The method is called
|
||||||
slide_controller.on_slide_selected_index([7])
|
slide_controller.on_slide_selected_index([7])
|
||||||
|
|
||||||
# THEN: It should have sent a notification
|
# THEN: It should have sent a notification
|
||||||
mocked_item.is_command.assert_called_once_with()
|
mocked_item.is_command.assert_called_once_with()
|
||||||
|
136
tests/functional/openlp_core_ui/test_thememanager.py
Normal file
136
tests/functional/openlp_core_ui/test_thememanager.py
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# OpenLP - Open Source Lyrics Projection #
|
||||||
|
# --------------------------------------------------------------------------- #
|
||||||
|
# Copyright (c) 2008-2014 Raoul Snyman #
|
||||||
|
# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan #
|
||||||
|
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
|
||||||
|
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
|
||||||
|
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
|
||||||
|
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||||
|
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
|
||||||
|
# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
|
||||||
|
# --------------------------------------------------------------------------- #
|
||||||
|
# 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 #
|
||||||
|
###############################################################################
|
||||||
|
"""
|
||||||
|
Package to test the openlp.core.ui.thememanager package.
|
||||||
|
"""
|
||||||
|
import zipfile
|
||||||
|
import os
|
||||||
|
|
||||||
|
from unittest import TestCase
|
||||||
|
from tests.interfaces import MagicMock
|
||||||
|
|
||||||
|
from openlp.core.ui import ThemeManager
|
||||||
|
from openlp.core.common import Registry
|
||||||
|
|
||||||
|
from tests.utils.constants import TEST_RESOURCES_PATH
|
||||||
|
from tests.interfaces import MagicMock, patch
|
||||||
|
|
||||||
|
|
||||||
|
class TestThemeManager(TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Set up the tests
|
||||||
|
"""
|
||||||
|
Registry.create()
|
||||||
|
|
||||||
|
def export_theme_test(self):
|
||||||
|
"""
|
||||||
|
Test exporting a theme .
|
||||||
|
"""
|
||||||
|
# GIVEN: A new ThemeManager instance.
|
||||||
|
theme_manager = ThemeManager()
|
||||||
|
theme_manager.path = os.path.join(TEST_RESOURCES_PATH, 'themes')
|
||||||
|
zipfile.ZipFile.__init__ = MagicMock()
|
||||||
|
zipfile.ZipFile.__init__.return_value = None
|
||||||
|
zipfile.ZipFile.write = MagicMock()
|
||||||
|
|
||||||
|
# WHEN: The theme is exported
|
||||||
|
theme_manager._export_theme(os.path.join('some', 'path'), 'Default')
|
||||||
|
|
||||||
|
# THEN: The zipfile should be created at the given path
|
||||||
|
zipfile.ZipFile.__init__.assert_called_with(os.path.join('some', 'path', 'Default.otz'), 'w')
|
||||||
|
zipfile.ZipFile.write.assert_called_with(os.path.join(TEST_RESOURCES_PATH, 'themes', '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')
|
@ -125,3 +125,31 @@ class TestDB(TestCase):
|
|||||||
|
|
||||||
# THEN: The type should be correct
|
# THEN: The type should be correct
|
||||||
self.assertEqual(author_type, AuthorType.Words)
|
self.assertEqual(author_type, AuthorType.Words)
|
||||||
|
|
||||||
|
def test_author_get_display_name(self):
|
||||||
|
"""
|
||||||
|
Test that the display name of an author is correct
|
||||||
|
"""
|
||||||
|
# GIVEN: An author
|
||||||
|
author = Author()
|
||||||
|
author.display_name = "John Doe"
|
||||||
|
|
||||||
|
# WHEN: We call the get_display_name() function
|
||||||
|
display_name = author.get_display_name()
|
||||||
|
|
||||||
|
# THEN: It should return only the name
|
||||||
|
self.assertEqual("John Doe", display_name)
|
||||||
|
|
||||||
|
def test_author_get_display_name_with_type(self):
|
||||||
|
"""
|
||||||
|
Test that the display name of an author with a type is correct
|
||||||
|
"""
|
||||||
|
# GIVEN: An author
|
||||||
|
author = Author()
|
||||||
|
author.display_name = "John Doe"
|
||||||
|
|
||||||
|
# WHEN: We call the get_display_name() function
|
||||||
|
display_name = author.get_display_name(AuthorType.Words)
|
||||||
|
|
||||||
|
# THEN: It should return the name with the type in brackets
|
||||||
|
self.assertEqual("John Doe (Words)", display_name)
|
||||||
|
@ -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')))
|
||||||
|
@ -0,0 +1,53 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# OpenLP - Open Source Lyrics Projection #
|
||||||
|
# --------------------------------------------------------------------------- #
|
||||||
|
# Copyright (c) 2008-2014 Raoul Snyman #
|
||||||
|
# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan #
|
||||||
|
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
|
||||||
|
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
|
||||||
|
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
|
||||||
|
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||||
|
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
|
||||||
|
# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
|
||||||
|
# --------------------------------------------------------------------------- #
|
||||||
|
# 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 PresentationManager song importer.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from tests.helpers.songfileimport import SongImportTestHelper
|
||||||
|
|
||||||
|
TEST_PATH = os.path.abspath(
|
||||||
|
os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'presentationmanagersongs'))
|
||||||
|
|
||||||
|
|
||||||
|
class TestSongShowPlusFileImport(SongImportTestHelper):
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
self.importer_class_name = 'PresentationManagerImport'
|
||||||
|
self.importer_module_name = 'presentationmanager'
|
||||||
|
super(TestSongShowPlusFileImport, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def test_song_import(self):
|
||||||
|
"""
|
||||||
|
Test that loading a PresentationManager file works correctly
|
||||||
|
"""
|
||||||
|
self.file_import([os.path.join(TEST_PATH, 'Great Is Thy Faithfulness.sng')],
|
||||||
|
self.load_external_result_data(os.path.join(TEST_PATH, 'Great Is Thy Faithfulness.json')))
|
@ -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')))
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"title": "Great Is Thy Faithfulness",
|
||||||
|
"authors": [
|
||||||
|
"Thomas O. Chisholm (1866-1960)"
|
||||||
|
],
|
||||||
|
"verse_order_list": ["v1", "c1", "v2", "c1", "v3", "c1"],
|
||||||
|
"verses": [
|
||||||
|
[
|
||||||
|
"\"Great is Thy faithfulness\", O God my Father.\nThere is no shadow of turning with Thee;\nThou changest not, Thy compassions they fail not,\nAs Thou hast been Thou forever shall be.",
|
||||||
|
"v1"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Great is Thy faithfulness!\nGreat is Thy faithfulness!\nMorning by morning new mercies I see!\nAll I have needed Thy hand hath provided -\n\"Great is Thy faithfulness\", Lord, unto me!",
|
||||||
|
"c1"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Summer and winter, and springtime and harvest,\nSun, moon, and stars in their courses above,\nJoin with all nature in manifold witness,\nTo Thy great faithfulness, mercy and love.",
|
||||||
|
"v2"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Pardon for sin and a peace that endureth,\nThine own dear presence to cheer and to guide,\nStrength for today and bright hope for tomorrow,\nBlessings all mine, with ten thousand beside!",
|
||||||
|
"v3"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<song xmlns="creativelifestyles/song">
|
||||||
|
<attributes>
|
||||||
|
<title>Great Is Thy Faithfulness</title>
|
||||||
|
<author>Thomas O. Chisholm (1866-1960)</author>
|
||||||
|
<copyright></copyright>
|
||||||
|
<ccli_number></ccli_number>
|
||||||
|
<comments></comments>
|
||||||
|
</attributes>
|
||||||
|
<verses>
|
||||||
|
<verse id="Verse 1">
|
||||||
|
"Great is Thy faithfulness", O God my Father.
|
||||||
|
There is no shadow of turning with Thee;
|
||||||
|
Thou changest not, Thy compassions they fail not,
|
||||||
|
As Thou hast been Thou forever shall be.
|
||||||
|
</verse>
|
||||||
|
<verse id="Chorus">
|
||||||
|
Great is Thy faithfulness!
|
||||||
|
Great is Thy faithfulness!
|
||||||
|
Morning by morning new mercies I see!
|
||||||
|
All I have needed Thy hand hath provided -
|
||||||
|
"Great is Thy faithfulness", Lord, unto me!
|
||||||
|
</verse>
|
||||||
|
<verse id="Verse 2">
|
||||||
|
Summer and winter, and springtime and harvest,
|
||||||
|
Sun, moon, and stars in their courses above,
|
||||||
|
Join with all nature in manifold witness,
|
||||||
|
To Thy great faithfulness, mercy and love.
|
||||||
|
</verse>
|
||||||
|
<verse id="Chorus">
|
||||||
|
Great is Thy faithfulness!
|
||||||
|
Great is Thy faithfulness!
|
||||||
|
Morning by morning new mercies I see!
|
||||||
|
All I have needed Thy hand hath provided -
|
||||||
|
"Great is Thy faithfulness", Lord, unto me!
|
||||||
|
</verse>
|
||||||
|
<verse id="Verse 3">
|
||||||
|
Pardon for sin and a peace that endureth,
|
||||||
|
Thine own dear presence to cheer and to guide,
|
||||||
|
Strength for today and bright hope for tomorrow,
|
||||||
|
Blessings all mine, with ten thousand beside!
|
||||||
|
</verse>
|
||||||
|
<verse id="Chorus">
|
||||||
|
Great is Thy faithfulness!
|
||||||
|
Great is Thy faithfulness!
|
||||||
|
Morning by morning new mercies I see!
|
||||||
|
All I have needed Thy hand hath provided -
|
||||||
|
"Great is Thy faithfulness", Lord, unto me!
|
||||||
|
</verse>
|
||||||
|
</verses>
|
||||||
|
</song>
|
34
tests/resources/propresentersongs/Vaste Grond.json
Normal file
34
tests/resources/propresentersongs/Vaste Grond.json
Normal 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"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
1
tests/resources/propresentersongs/Vaste Grond.pro4
Normal file
1
tests/resources/propresentersongs/Vaste Grond.pro4
Normal file
File diff suppressed because one or more lines are too long
34
tests/resources/themes/Default/Default.xml
Normal file
34
tests/resources/themes/Default/Default.xml
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<theme version="2.0">
|
||||||
|
<name>Default</name>
|
||||||
|
<background type="solid">
|
||||||
|
<color>#000000</color>
|
||||||
|
</background>
|
||||||
|
<font type="main">
|
||||||
|
<name>Arial</name>
|
||||||
|
<color>#FFFFFF</color>
|
||||||
|
<size>40</size>
|
||||||
|
<bold>False</bold>
|
||||||
|
<italics>False</italics>
|
||||||
|
<line_adjustment>0</line_adjustment>
|
||||||
|
<location height="690" override="False" width="1004" x="10" y="10"/>
|
||||||
|
<shadow shadowColor="#000000" shadowSize="5">True</shadow>
|
||||||
|
<outline outlineColor="#000000" outlineSize="2">False</outline>
|
||||||
|
</font>
|
||||||
|
<font type="footer">
|
||||||
|
<name>Arial</name>
|
||||||
|
<color>#FFFFFF</color>
|
||||||
|
<size>12</size>
|
||||||
|
<bold>False</bold>
|
||||||
|
<italics>False</italics>
|
||||||
|
<line_adjustment>0</line_adjustment>
|
||||||
|
<location height="78" override="False" width="1004" x="10" y="690"/>
|
||||||
|
<shadow shadowColor="#000000" shadowSize="5">True</shadow>
|
||||||
|
<outline outlineColor="#000000" outlineSize="2">False</outline>
|
||||||
|
</font>
|
||||||
|
<display>
|
||||||
|
<horizontalAlign>0</horizontalAlign>
|
||||||
|
<verticalAlign>0</verticalAlign>
|
||||||
|
<slideTransition>False</slideTransition>
|
||||||
|
</display>
|
||||||
|
</theme>
|
Loading…
Reference in New Issue
Block a user