forked from openlp/openlp
made use of pystache for footer generation being configurable in song settings
- removed now obsolete and via template better configurable options to display "songbook", "written by" and "copyright" information in footer - added explanation box for so far used settings as pystache placeholders - added songs configuration setting for template including reset button - added default template replacing currently existing configuration as best as possible (should be backwards compatible or at least be adaptable to correspond to former settings) - adjusted tests to new and removed functionality Fixes: https://launchpad.net/bugs/1695620
This commit is contained in:
parent
81492013ed
commit
66c9f8eb82
@ -163,7 +163,8 @@ class ServiceItem(RegistryProperties):
|
||||
self.items = []
|
||||
self.iconic_representation = None
|
||||
self.raw_footer = []
|
||||
self.foot_text = ''
|
||||
# Plugins can set footer_html themselves. If they don't, it will be generated from raw_footer.
|
||||
self.footer_html = ''
|
||||
self.theme = None
|
||||
self.service_item_type = None
|
||||
self._raw_frames = []
|
||||
@ -276,12 +277,9 @@ class ServiceItem(RegistryProperties):
|
||||
else:
|
||||
log.error('Invalid value renderer: {item}'.format(item=self.service_item_type))
|
||||
self.title = clean_tags(self.title)
|
||||
# The footer should never be None, but to be compatible with a few
|
||||
# nightly builds between 1.9.4 and 1.9.5, we have to correct this to
|
||||
# avoid tracebacks.
|
||||
if self.raw_footer is None:
|
||||
self.raw_footer = []
|
||||
self.foot_text = '<br>'.join([_f for _f in self.raw_footer if _f])
|
||||
|
||||
if not self.footer_html:
|
||||
self.footer_html = '<br>'.join([_f for _f in self.raw_footer if _f])
|
||||
|
||||
def add_from_image(self, path, title, background=None, thumbnail=None):
|
||||
"""
|
||||
|
@ -471,8 +471,8 @@ class MainDisplay(OpenLPMixin, Display, RegistryProperties):
|
||||
created_html = build_html(self.service_item, self.screen, self.is_live, background, image_bytes,
|
||||
plugins=self.plugin_manager.plugins)
|
||||
self.web_view.setHtml(created_html)
|
||||
if service_item.foot_text:
|
||||
self.footer(service_item.foot_text)
|
||||
if service_item.footer_html:
|
||||
self.footer(service_item.footer_html)
|
||||
# if was hidden keep it hidden
|
||||
if self.hide_mode and self.is_live and not service_item.is_media():
|
||||
if Settings().value('core/auto unblank'):
|
||||
|
@ -231,11 +231,11 @@ class PrintServiceForm(QtWidgets.QDialog, Ui_PrintServiceDialog, RegistryPropert
|
||||
for slide in range(len(item.get_frames())):
|
||||
self._add_element('li', item.get_frame_title(slide), ol)
|
||||
# add footer
|
||||
foot_text = item.foot_text
|
||||
foot_text = foot_text.partition('<br>')[2]
|
||||
if foot_text:
|
||||
foot_text = html.escape(foot_text.replace('<br>', '\n'))
|
||||
self._add_element('div', foot_text.replace('\n', '<br>'), parent=div, classId='itemFooter')
|
||||
footer_html = item.footer_html
|
||||
footer_html = footer_html.partition('<br>')[2]
|
||||
if footer_html:
|
||||
footer_html = html.escape(footer_html.replace('<br>', '\n'))
|
||||
self._add_element('div', footer_html.replace('\n', '<br>'), parent=div, classId='itemFooter')
|
||||
# Add service items' notes.
|
||||
if self.notes_check_box.isChecked():
|
||||
if item.notes:
|
||||
|
@ -664,3 +664,17 @@ def transpose_chord(chord, transpose_value, notation):
|
||||
else:
|
||||
transposed_chord += note + rest
|
||||
return transposed_chord
|
||||
|
||||
|
||||
def make_list(array):
|
||||
if len(array) > 0:
|
||||
result = []
|
||||
for i in range(len(array)):
|
||||
result.append({'entry': array[i]})
|
||||
if i == 0:
|
||||
result[i]['first'] = True
|
||||
if i == len(array) - 1:
|
||||
result[i]['last'] = True
|
||||
return result
|
||||
else:
|
||||
return False
|
||||
|
@ -23,6 +23,7 @@
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import pystache
|
||||
|
||||
from PyQt5 import QtCore, QtWidgets
|
||||
from sqlalchemy.sql import and_, or_
|
||||
@ -36,7 +37,7 @@ from openlp.plugins.songs.forms.editsongform import EditSongForm
|
||||
from openlp.plugins.songs.forms.songmaintenanceform import SongMaintenanceForm
|
||||
from openlp.plugins.songs.forms.songimportform import SongImportForm
|
||||
from openlp.plugins.songs.forms.songexportform import SongExportForm
|
||||
from openlp.plugins.songs.lib import VerseType, clean_string, delete_song
|
||||
from openlp.plugins.songs.lib import VerseType, clean_string, delete_song, make_list
|
||||
from openlp.plugins.songs.lib.db import Author, AuthorType, Song, Book, MediaFile, SongBookEntry, Topic
|
||||
from openlp.plugins.songs.lib.ui import SongStrings
|
||||
from openlp.plugins.songs.lib.openlyricsxml import OpenLyrics, SongXML
|
||||
@ -125,9 +126,6 @@ class SongMediaItem(MediaManagerItem):
|
||||
self.is_search_as_you_type_enabled = Settings().value('advanced/search as type')
|
||||
self.update_service_on_edit = Settings().value(self.settings_section + '/update service on edit')
|
||||
self.add_song_from_service = Settings().value(self.settings_section + '/add song from service')
|
||||
self.display_songbook = Settings().value(self.settings_section + '/display songbook')
|
||||
self.display_written_by_text = Settings().value(self.settings_section + '/display written by')
|
||||
self.display_copyright_symbol = Settings().value(self.settings_section + '/display copyright symbol')
|
||||
|
||||
def retranslateUi(self):
|
||||
self.search_text_label.setText('{text}:'.format(text=UiStrings().Search))
|
||||
@ -641,12 +639,8 @@ class SongMediaItem(MediaManagerItem):
|
||||
item.raw_footer = []
|
||||
item.raw_footer.append(song.title)
|
||||
if authors_none:
|
||||
# If the setting for showing "Written by:" is enabled, show it before unspecified authors.
|
||||
if Settings().value('songs/display written by'):
|
||||
item.raw_footer.append("{text}: {authors}".format(text=translate('OpenLP.Ui', 'Written by'),
|
||||
authors=create_separated_list(authors_none)))
|
||||
else:
|
||||
item.raw_footer.append("{authors}".format(authors=create_separated_list(authors_none)))
|
||||
item.raw_footer.append("{text}: {authors}".format(text=translate('OpenLP.Ui', 'Written by'),
|
||||
authors=create_separated_list(authors_none)))
|
||||
if authors_words_music:
|
||||
item.raw_footer.append("{text}: {authors}".format(text=AuthorType.Types[AuthorType.WordsAndMusic],
|
||||
authors=create_separated_list(authors_words_music)))
|
||||
@ -660,17 +654,35 @@ class SongMediaItem(MediaManagerItem):
|
||||
item.raw_footer.append("{text}: {authors}".format(text=AuthorType.Types[AuthorType.Translation],
|
||||
authors=create_separated_list(authors_translation)))
|
||||
if song.copyright:
|
||||
if self.display_copyright_symbol:
|
||||
item.raw_footer.append("{symbol} {song}".format(symbol=SongStrings.CopyrightSymbol,
|
||||
song=song.copyright))
|
||||
else:
|
||||
item.raw_footer.append(song.copyright)
|
||||
if self.display_songbook and song.songbook_entries:
|
||||
songbooks = [str(songbook_entry) for songbook_entry in song.songbook_entries]
|
||||
item.raw_footer.append("{symbol} {song}".format(symbol=SongStrings.CopyrightSymbol,
|
||||
song=song.copyright))
|
||||
songbooks = [str(songbook_entry) for songbook_entry in song.songbook_entries]
|
||||
if song.songbook_entries:
|
||||
item.raw_footer.append(", ".join(songbooks))
|
||||
if Settings().value('core/ccli number'):
|
||||
item.raw_footer.append(translate('SongsPlugin.MediaItem',
|
||||
'CCLI License: ') + Settings().value('core/ccli number'))
|
||||
item.raw_footer.append(translate('SongsPlugin.MediaItem', 'CCLI License: ') +
|
||||
Settings().value('core/ccli number'))
|
||||
|
||||
footer_template = Settings().value('songs/footer template').replace('\n', '').replace(' ', '')
|
||||
# Keep this in sync with the list in songstab.py
|
||||
item.footer_html = pystache.render(footer_template, {
|
||||
'title': song.title,
|
||||
'authors_none_label': translate('OpenLP.Ui', 'Written by'),
|
||||
'authors_none': make_list(authors_none),
|
||||
'authors_words_label': AuthorType.Types[AuthorType.Words],
|
||||
'authors_words': make_list(authors_words),
|
||||
'authors_music_label': AuthorType.Types[AuthorType.Music],
|
||||
'authors_music': make_list(authors_music),
|
||||
'authors_words_music_label': AuthorType.Types[AuthorType.WordsAndMusic],
|
||||
'authors_words_music': make_list(authors_words_music),
|
||||
'authors_translation_label': AuthorType.Types[AuthorType.Translation],
|
||||
'authors_translation': make_list(authors_translation),
|
||||
'copyright': song.copyright,
|
||||
'songbook_entries': make_list(songbooks),
|
||||
'ccli_license': Settings().value('core/ccli number'),
|
||||
'ccli_license_label': translate('SongsPlugin.MediaItem', 'CCLI License')
|
||||
})
|
||||
|
||||
return authors_all
|
||||
|
||||
def service_load(self, item):
|
||||
|
@ -24,7 +24,7 @@ from PyQt5 import QtCore, QtWidgets
|
||||
|
||||
from openlp.core.common import Settings, translate
|
||||
from openlp.core.lib import SettingsTab
|
||||
from openlp.plugins.songs.lib.ui import SongStrings
|
||||
from openlp.plugins.songs.lib.db import AuthorType
|
||||
|
||||
|
||||
class SongsTab(SettingsTab):
|
||||
@ -50,15 +50,6 @@ class SongsTab(SettingsTab):
|
||||
self.add_from_service_check_box = QtWidgets.QCheckBox(self.mode_group_box)
|
||||
self.add_from_service_check_box.setObjectName('add_from_service_check_box')
|
||||
self.mode_layout.addWidget(self.add_from_service_check_box)
|
||||
self.display_songbook_check_box = QtWidgets.QCheckBox(self.mode_group_box)
|
||||
self.display_songbook_check_box.setObjectName('songbook_check_box')
|
||||
self.mode_layout.addWidget(self.display_songbook_check_box)
|
||||
self.display_written_by_check_box = QtWidgets.QCheckBox(self.mode_group_box)
|
||||
self.display_written_by_check_box.setObjectName('written_by_check_box')
|
||||
self.mode_layout.addWidget(self.display_written_by_check_box)
|
||||
self.display_copyright_check_box = QtWidgets.QCheckBox(self.mode_group_box)
|
||||
self.display_copyright_check_box.setObjectName('copyright_check_box')
|
||||
self.mode_layout.addWidget(self.display_copyright_check_box)
|
||||
self.left_layout.addWidget(self.mode_group_box)
|
||||
# Chords group box
|
||||
self.chords_group_box = QtWidgets.QGroupBox(self.left_column)
|
||||
@ -89,19 +80,36 @@ class SongsTab(SettingsTab):
|
||||
self.neolatin_notation_radio_button.setObjectName('neolatin_notation_radio_button')
|
||||
self.chords_layout.addWidget(self.neolatin_notation_radio_button)
|
||||
self.left_layout.addWidget(self.chords_group_box)
|
||||
|
||||
# Footer group box
|
||||
self.footer_group_box = QtWidgets.QGroupBox(self.left_column)
|
||||
self.footer_group_box.setObjectName('footer_group_box')
|
||||
self.footer_layout = QtWidgets.QVBoxLayout(self.footer_group_box)
|
||||
self.footer_layout.setObjectName('chords_layout')
|
||||
self.footer_info_label = QtWidgets.QLabel(self.footer_group_box)
|
||||
self.footer_layout.addWidget(self.footer_info_label)
|
||||
self.footer_placeholder_info = QtWidgets.QTextEdit(self.footer_group_box)
|
||||
self.footer_layout.addWidget(self.footer_placeholder_info)
|
||||
self.footer_desc_label = QtWidgets.QLabel(self.footer_group_box)
|
||||
self.footer_layout.addWidget(self.footer_desc_label)
|
||||
self.footer_edit_box = QtWidgets.QTextEdit(self.footer_group_box)
|
||||
self.footer_layout.addWidget(self.footer_edit_box)
|
||||
self.footer_reset_button = QtWidgets.QPushButton(self.footer_group_box)
|
||||
self.footer_layout.addWidget(self.footer_reset_button, alignment=QtCore.Qt.AlignRight)
|
||||
self.right_layout.addWidget(self.footer_group_box)
|
||||
|
||||
|
||||
self.left_layout.addStretch()
|
||||
self.right_layout.addStretch()
|
||||
self.tool_bar_active_check_box.stateChanged.connect(self.on_tool_bar_active_check_box_changed)
|
||||
self.update_on_edit_check_box.stateChanged.connect(self.on_update_on_edit_check_box_changed)
|
||||
self.add_from_service_check_box.stateChanged.connect(self.on_add_from_service_check_box_changed)
|
||||
self.display_songbook_check_box.stateChanged.connect(self.on_songbook_check_box_changed)
|
||||
self.display_written_by_check_box.stateChanged.connect(self.on_written_by_check_box_changed)
|
||||
self.display_copyright_check_box.stateChanged.connect(self.on_copyright_check_box_changed)
|
||||
self.mainview_chords_check_box.stateChanged.connect(self.on_mainview_chords_check_box_changed)
|
||||
self.disable_chords_import_check_box.stateChanged.connect(self.on_disable_chords_import_check_box_changed)
|
||||
self.english_notation_radio_button.clicked.connect(self.on_english_notation_button_clicked)
|
||||
self.german_notation_radio_button.clicked.connect(self.on_german_notation_button_clicked)
|
||||
self.neolatin_notation_radio_button.clicked.connect(self.on_neolatin_notation_button_clicked)
|
||||
self.footer_reset_button.clicked.connect(self.on_footer_reset_button_clicked)
|
||||
|
||||
def retranslateUi(self):
|
||||
self.mode_group_box.setTitle(translate('SongsPlugin.SongsTab', 'Song related settings'))
|
||||
@ -110,12 +118,6 @@ class SongsTab(SettingsTab):
|
||||
self.update_on_edit_check_box.setText(translate('SongsPlugin.SongsTab', 'Update service from song edit'))
|
||||
self.add_from_service_check_box.setText(translate('SongsPlugin.SongsTab',
|
||||
'Import missing songs from Service files'))
|
||||
self.display_songbook_check_box.setText(translate('SongsPlugin.SongsTab', 'Display songbook in footer'))
|
||||
self.display_written_by_check_box.setText(translate(
|
||||
'SongsPlugin.SongsTab', 'Show "Written by:" in footer for unspecified authors'))
|
||||
self.display_copyright_check_box.setText(translate('SongsPlugin.SongsTab',
|
||||
'Display "{symbol}" symbol before copyright '
|
||||
'info').format(symbol=SongStrings.CopyrightSymbol))
|
||||
self.chords_info_label.setText(translate('SongsPlugin.SongsTab', 'If enabled all text between "[" and "]" will '
|
||||
'be regarded as chords.'))
|
||||
self.chords_group_box.setTitle(translate('SongsPlugin.SongsTab', 'Chords'))
|
||||
@ -127,6 +129,49 @@ class SongsTab(SettingsTab):
|
||||
self.german_notation_radio_button.setText(translate('SongsPlugin.SongsTab', 'German') + ' (C-D-E-F-G-A-H)')
|
||||
self.neolatin_notation_radio_button.setText(
|
||||
translate('SongsPlugin.SongsTab', 'Neo-Latin') + ' (Do-Re-Mi-Fa-Sol-La-Si)')
|
||||
self.footer_group_box.setTitle(translate('SongsPlugin.SongsTab', 'Footer'))
|
||||
|
||||
# Keep this in sync with the list in mediaitem.py
|
||||
const = '<code>"{}"</code>'
|
||||
placeholders = [
|
||||
['title', translate('SongsPlugin.SongsTab', 'Song Title'), False, False],
|
||||
['written_by', const.format(translate('SongsPlugin.SongsTab', 'Written By')), True, False],
|
||||
['authors_none', translate('SongsPlugin.SongsTab', 'Authors when type is not set'), True, True],
|
||||
['authors_words_label', const.format(AuthorType.Types[AuthorType.Words]), False, False],
|
||||
['authors_words', translate('SongsPlugin.SongsTab', 'Authors (Type Words)'), True, True],
|
||||
['authors_music_label', const.format(AuthorType.Types[AuthorType.Music]), False, False],
|
||||
['authors_music', translate('SongsPlugin.SongsTab', 'Authors (Type Music)'), True, True],
|
||||
['authors_words_music_label', const.format(AuthorType.Types[AuthorType.WordsAndMusic]), False, False],
|
||||
['authors_words_music', translate('SongsPlugin.SongsTab', 'Authors (Type Words and Music)'), True, True],
|
||||
['authors_translation_label', const.format(AuthorType.Types[AuthorType.Translation]), False, False],
|
||||
['authors_translation', translate('SongsPlugin.SongsTab', 'Authors (Type Translation)'), True, True],
|
||||
['copyright', translate('SongsPlugin.SongsTab', 'Copyright information'), True, False],
|
||||
['songbook_entries', translate('SongsPlugin.SongsTab', 'Songbook Entries'), True, True],
|
||||
['ccli_license', translate('SongsPlugin.SongsTab', 'CCLI License'), True, False],
|
||||
['ccli_license_label', const.format(translate('SongsPlugin.SongsTab', 'CCLI License')), False, False],
|
||||
]
|
||||
|
||||
placeholder_info = '<table style="background: #eee">\n<tr><th><b>{ph}</b></th><th><b>{desc}</b></th></tr>\n'\
|
||||
.format(ph=translate('SongsPlugin.SongsTab', 'Placeholder'),
|
||||
desc=translate('SongsPlugin.SongsTab', 'Description'))
|
||||
for placeholder in placeholders:
|
||||
placeholder_info += '<tr><td>{{{pl}}}</td><td>{des}{opt}</td></tr>\n'\
|
||||
.format(pl=placeholder[0], des=placeholder[1],
|
||||
opt=(' ¹' if placeholder[2] else '') + (' ²' if placeholder[3] else ''))
|
||||
placeholder_info += '</table>'
|
||||
placeholder_info += '\n<br/>¹ {}'.format(translate('SongsPlugin.SongsTab', 'can be empty'))
|
||||
placeholder_info += '\n<br/>² {}:<pre>{{#first}} <i>True</i> {}<br/>{{entry}} {}<br/>' \
|
||||
'{{#last}} <i>True</i> {}</pre>'\
|
||||
.format(translate('SongsPlugin.SongsTab', 'list of entries'),
|
||||
translate('SongsPlugin.SongsTab', 'for first element of list'),
|
||||
translate('SongsPlugin.SongsTab', 'iterates over all entries'),
|
||||
translate('SongsPlugin.SongsTab', 'for last element'))
|
||||
self.footer_placeholder_info.setHtml(placeholder_info)
|
||||
self.footer_placeholder_info.setReadOnly(True)
|
||||
|
||||
self.footer_info_label.setText(translate('SongsPlugin.SongsTab', 'How to use Footers:'))
|
||||
self.footer_desc_label.setText(translate('SongsPlugin.SongsTab', 'Footer Template (Mustache Syntax):'))
|
||||
self.footer_reset_button.setText(translate('SongsPlugin.SongsTab', 'Reset Template'))
|
||||
|
||||
def on_search_as_type_check_box_changed(self, check_state):
|
||||
self.song_search = (check_state == QtCore.Qt.Checked)
|
||||
@ -140,15 +185,6 @@ class SongsTab(SettingsTab):
|
||||
def on_add_from_service_check_box_changed(self, check_state):
|
||||
self.update_load = (check_state == QtCore.Qt.Checked)
|
||||
|
||||
def on_songbook_check_box_changed(self, check_state):
|
||||
self.display_songbook = (check_state == QtCore.Qt.Checked)
|
||||
|
||||
def on_written_by_check_box_changed(self, check_state):
|
||||
self.display_written_by = (check_state == QtCore.Qt.Checked)
|
||||
|
||||
def on_copyright_check_box_changed(self, check_state):
|
||||
self.display_copyright_symbol = (check_state == QtCore.Qt.Checked)
|
||||
|
||||
def on_mainview_chords_check_box_changed(self, check_state):
|
||||
self.mainview_chords = (check_state == QtCore.Qt.Checked)
|
||||
|
||||
@ -164,15 +200,15 @@ class SongsTab(SettingsTab):
|
||||
def on_neolatin_notation_button_clicked(self):
|
||||
self.chord_notation = 'neo-latin'
|
||||
|
||||
def on_footer_reset_button_clicked(self):
|
||||
self.footer_edit_box.setPlainText(Settings().get_default_value('songs/footer template'));
|
||||
|
||||
def load(self):
|
||||
settings = Settings()
|
||||
settings.beginGroup(self.settings_section)
|
||||
self.tool_bar = settings.value('display songbar')
|
||||
self.update_edit = settings.value('update service on edit')
|
||||
self.update_load = settings.value('add song from service')
|
||||
self.display_songbook = settings.value('display songbook')
|
||||
self.display_written_by = settings.value('display written by')
|
||||
self.display_copyright_symbol = settings.value('display copyright symbol')
|
||||
self.enable_chords = settings.value('enable chords')
|
||||
self.chord_notation = settings.value('chord notation')
|
||||
self.mainview_chords = settings.value('mainview chords')
|
||||
@ -180,9 +216,6 @@ class SongsTab(SettingsTab):
|
||||
self.tool_bar_active_check_box.setChecked(self.tool_bar)
|
||||
self.update_on_edit_check_box.setChecked(self.update_edit)
|
||||
self.add_from_service_check_box.setChecked(self.update_load)
|
||||
self.display_songbook_check_box.setChecked(self.display_songbook)
|
||||
self.display_written_by_check_box.setChecked(self.display_written_by)
|
||||
self.display_copyright_check_box.setChecked(self.display_copyright_symbol)
|
||||
self.chords_group_box.setChecked(self.enable_chords)
|
||||
self.mainview_chords_check_box.setChecked(self.mainview_chords)
|
||||
self.disable_chords_import_check_box.setChecked(self.disable_chords_import)
|
||||
@ -192,6 +225,7 @@ class SongsTab(SettingsTab):
|
||||
self.neolatin_notation_radio_button.setChecked(True)
|
||||
else:
|
||||
self.english_notation_radio_button.setChecked(True)
|
||||
self.footer_edit_box.setPlainText(settings.value('footer template'))
|
||||
settings.endGroup()
|
||||
|
||||
def save(self):
|
||||
@ -200,13 +234,11 @@ class SongsTab(SettingsTab):
|
||||
settings.setValue('display songbar', self.tool_bar)
|
||||
settings.setValue('update service on edit', self.update_edit)
|
||||
settings.setValue('add song from service', self.update_load)
|
||||
settings.setValue('display songbook', self.display_songbook)
|
||||
settings.setValue('display written by', self.display_written_by)
|
||||
settings.setValue('display copyright symbol', self.display_copyright_symbol)
|
||||
settings.setValue('enable chords', self.chords_group_box.isChecked())
|
||||
settings.setValue('mainview chords', self.mainview_chords)
|
||||
settings.setValue('disable chords import', self.disable_chords_import)
|
||||
settings.setValue('chord notation', self.chord_notation)
|
||||
settings.setValue('footer template', self.footer_edit_box.toPlainText())
|
||||
settings.endGroup()
|
||||
if self.tab_visited:
|
||||
self.settings_form.register_post_process('songs_config_updated')
|
||||
|
@ -59,9 +59,6 @@ __default_settings__ = {
|
||||
'songs/update service on edit': False,
|
||||
'songs/add song from service': True,
|
||||
'songs/display songbar': True,
|
||||
'songs/display songbook': False,
|
||||
'songs/display written by': True,
|
||||
'songs/display copyright symbol': False,
|
||||
'songs/last directory import': '',
|
||||
'songs/last directory export': '',
|
||||
'songs/songselect username': '',
|
||||
@ -71,6 +68,46 @@ __default_settings__ = {
|
||||
'songs/chord notation': 'english', # Can be english, german or neo-latin
|
||||
'songs/mainview chords': False,
|
||||
'songs/disable chords import': False,
|
||||
'songs/footer template': """{{title}}<br/>
|
||||
|
||||
{{#authors_none}}
|
||||
{{#first}}{{authors_none_label}}: {{/first}}
|
||||
{{entry}}{{^last}}, {{/last}}
|
||||
{{#last}}<br/>{{/last}}
|
||||
{{/authors_none}}
|
||||
{{#authors_words_music}}
|
||||
{{#first}}{{authors_words_music_label}}: {{/first}}
|
||||
{{entry}}{{^last}}, {{/last}}
|
||||
{{#last}}<br/>{{/last}}
|
||||
{{/authors_words_music}}
|
||||
{{#authors_words}}
|
||||
{{#first}}{{authors_words_label}}: {{/first}}
|
||||
{{entry}}{{^last}}, {{/last}}
|
||||
{{#last}}<br/>{{/last}}
|
||||
{{/authors_words}}
|
||||
{{#authors_music}}
|
||||
{{#first}}{{authors_music_label}}: {{/first}}
|
||||
{{entry}}{{^last}}, {{/last}}
|
||||
{{#last}}<br/>{{/last}}
|
||||
{{/authors_music}}
|
||||
{{#authors_translation}}
|
||||
{{#first}}{{authors_translation_label}}: {{/first}}
|
||||
{{entry}}{{^last}}, {{/last}}
|
||||
{{#last}}<br/>{{/last}}
|
||||
{{/authors_translation}}
|
||||
|
||||
{{#copyright}}
|
||||
© {{copyright}}<br/>
|
||||
{{/copyright}}
|
||||
|
||||
{{#songbook_entries}}
|
||||
{{entry}}{{^last}}, {{/last}}
|
||||
{{#last}}<br/>{{/last}}
|
||||
{{/songbook_entries}}
|
||||
|
||||
{{#ccli_license}}
|
||||
{{ccli_license_label}}: {{ccli_license}}<br/>
|
||||
{{/ccli_license}}""",
|
||||
}
|
||||
|
||||
|
||||
|
@ -34,6 +34,49 @@ from openlp.plugins.songs.lib.mediaitem import SongMediaItem
|
||||
|
||||
from tests.helpers.testmixin import TestMixin
|
||||
|
||||
__default_settings__ = {
|
||||
'songs/footer template': """{{title}}<br/>
|
||||
|
||||
{{#authors_none}}
|
||||
{{#first}}{{authors_none_label}}: {{/first}}
|
||||
{{entry}}{{^last}}, {{/last}}
|
||||
{{#last}}<br/>{{/last}}
|
||||
{{/authors_none}}
|
||||
{{#authors_words_music}}
|
||||
{{#first}}{{authors_words_music_label}}: {{/first}}
|
||||
{{entry}}{{^last}}, {{/last}}
|
||||
{{#last}}<br/>{{/last}}
|
||||
{{/authors_words_music}}
|
||||
{{#authors_words}}
|
||||
{{#first}}{{authors_words_label}}: {{/first}}
|
||||
{{entry}}{{^last}}, {{/last}}
|
||||
{{#last}}<br/>{{/last}}
|
||||
{{/authors_words}}
|
||||
{{#authors_music}}
|
||||
{{#first}}{{authors_music_label}}: {{/first}}
|
||||
{{entry}}{{^last}}, {{/last}}
|
||||
{{#last}}<br/>{{/last}}
|
||||
{{/authors_music}}
|
||||
{{#authors_translation}}
|
||||
{{#first}}{{authors_translation_label}}: {{/first}}
|
||||
{{entry}}{{^last}}, {{/last}}
|
||||
{{#last}}<br/>{{/last}}
|
||||
{{/authors_translation}}
|
||||
|
||||
{{#copyright}}
|
||||
© {{copyright}}<br/>
|
||||
{{/copyright}}
|
||||
|
||||
{{#songbook_entries}}
|
||||
{{entry}}{{^last}}, {{/last}}
|
||||
{{#last}}<br/>{{/last}}
|
||||
{{/songbook_entries}}
|
||||
|
||||
{{#ccli_license}}
|
||||
{{ccli_license_label}}: {{ccli_license}}<br/>
|
||||
{{/ccli_license}}"""
|
||||
}
|
||||
|
||||
|
||||
class TestMediaItem(TestCase, TestMixin):
|
||||
"""
|
||||
@ -60,6 +103,7 @@ class TestMediaItem(TestCase, TestMixin):
|
||||
self.media_item.display_copyright_symbol = False
|
||||
self.setup_application()
|
||||
self.build_settings()
|
||||
Settings().extend_default_settings(__default_settings__)
|
||||
QtCore.QLocale.setDefault(QtCore.QLocale('en_GB'))
|
||||
|
||||
def tearDown(self):
|
||||
@ -304,61 +348,43 @@ class TestMediaItem(TestCase, TestMixin):
|
||||
# and False for 'core/ccli number' (ccli will cause traceback if true)
|
||||
|
||||
mocked_settings = MagicMock()
|
||||
mocked_settings.value.side_effect = [True, False]
|
||||
mocked_settings.value.side_effect = [False, "", "0"]
|
||||
MockedSettings.return_value = mocked_settings
|
||||
|
||||
mock_song = MagicMock()
|
||||
mock_song.title = 'My Song'
|
||||
mock_song.authors_songs = []
|
||||
mock_author = MagicMock()
|
||||
mock_author.display_name = 'my author'
|
||||
mock_author_song = MagicMock()
|
||||
mock_author_song.author = mock_author
|
||||
mock_song.authors_songs.append(mock_author_song)
|
||||
mock_song.copyright = 'My copyright'
|
||||
service_item = ServiceItem(None)
|
||||
with patch('pystache.Renderer.render') as MockedRenderer:
|
||||
mock_song = MagicMock()
|
||||
mock_song.title = 'My Song'
|
||||
mock_song.authors_songs = []
|
||||
mock_author = MagicMock()
|
||||
mock_author.display_name = 'my author'
|
||||
mock_author_song = MagicMock()
|
||||
mock_author_song.author = mock_author
|
||||
mock_song.authors_songs.append(mock_author_song)
|
||||
mock_song.copyright = 'My copyright'
|
||||
mock_song.songbook_entries = []
|
||||
service_item = ServiceItem(None)
|
||||
MockedRenderer.return_value = ""
|
||||
|
||||
# WHEN: I generate the Footer with default settings
|
||||
author_list = self.media_item.generate_footer(service_item, mock_song)
|
||||
# WHEN: I generate the Footer with default settings
|
||||
author_list = self.media_item.generate_footer(service_item, mock_song)
|
||||
|
||||
# THEN: I get the following Array returned
|
||||
self.assertEqual(service_item.raw_footer, ['My Song', 'Written by: my author', 'My copyright'],
|
||||
'The array should be returned correctly with a song, one author and copyright')
|
||||
self.assertEqual(author_list, ['my author'],
|
||||
'The author list should be returned correctly with one author')
|
||||
# THEN: I get nothing real returned
|
||||
self.assertEqual(service_item.footer_html, "", 'pystache isnt in scope')
|
||||
|
||||
@patch(u'openlp.plugins.songs.lib.mediaitem.Settings')
|
||||
def test_build_song_footer_one_author_hide_written_by(self, MockedSettings):
|
||||
"""
|
||||
Test build songs footer with basic song and one author
|
||||
"""
|
||||
# GIVEN: A Song and a Service Item, mocked settings: False for 'songs/display written by'
|
||||
# and False for 'core/ccli number' (ccli will cause traceback if true)
|
||||
|
||||
mocked_settings = MagicMock()
|
||||
mocked_settings.value.side_effect = [False, False]
|
||||
MockedSettings.return_value = mocked_settings
|
||||
|
||||
mock_song = MagicMock()
|
||||
mock_song.title = 'My Song'
|
||||
mock_song.authors_songs = []
|
||||
mock_author = MagicMock()
|
||||
mock_author.display_name = 'my author'
|
||||
mock_author_song = MagicMock()
|
||||
mock_author_song.author = mock_author
|
||||
mock_song.authors_songs.append(mock_author_song)
|
||||
mock_song.copyright = 'My copyright'
|
||||
service_item = ServiceItem(None)
|
||||
|
||||
# WHEN: I generate the Footer with default settings
|
||||
author_list = self.media_item.generate_footer(service_item, mock_song)
|
||||
|
||||
# THEN: I get the following Array returned
|
||||
self.assertEqual(service_item.raw_footer, ['My Song', 'my author', 'My copyright'],
|
||||
'The array should be returned correctly with a song, one author and copyright,'
|
||||
'text Written by should not be part of the text.')
|
||||
self.assertEqual(author_list, ['my author'],
|
||||
'The author list should be returned correctly with one author')
|
||||
# AND: The psytache function was called with the following arguments
|
||||
MockedRenderer.assert_called_once_with('', {'authors_music_label': 'Music',
|
||||
'authors_none': [{'first': True, 'entry': 'my author',
|
||||
'last': True}], 'authors_words_music': False,
|
||||
'authors_words': False, 'authors_music': False,
|
||||
'authors_translation_label': 'Translation',
|
||||
'authors_words_music_label': 'Words and Music',
|
||||
'title': 'My Song', 'ccli_license': "0",
|
||||
'copyright': 'My copyright', 'authors_none_label': 'Written by',
|
||||
'ccli_license_label': 'CCLI License',
|
||||
'authors_translation': False, 'authors_words_label': 'Words',
|
||||
'songbook_entries': False})
|
||||
self.assertEqual(author_list, ['my author'],
|
||||
'The author list should be returned correctly with one author')
|
||||
|
||||
def test_build_song_footer_two_authors(self):
|
||||
"""
|
||||
@ -387,6 +413,7 @@ class TestMediaItem(TestCase, TestMixin):
|
||||
mock_author_song.author_type = AuthorType.Translation
|
||||
mock_song.authors_songs.append(mock_author_song)
|
||||
mock_song.copyright = 'My copyright'
|
||||
mock_song.songbook_entries = []
|
||||
service_item = ServiceItem(None)
|
||||
|
||||
# WHEN: I generate the Footer with default settings
|
||||
@ -394,7 +421,7 @@ class TestMediaItem(TestCase, TestMixin):
|
||||
|
||||
# THEN: I get the following Array returned
|
||||
self.assertEqual(service_item.raw_footer, ['My Song', 'Words: another author', 'Music: my author',
|
||||
'Translation: translator', 'My copyright'],
|
||||
'Translation: translator', '© My copyright'],
|
||||
'The array should be returned correctly with a song, two authors and copyright')
|
||||
self.assertEqual(author_list, ['another author', 'my author', 'translator'],
|
||||
'The author list should be returned correctly with two authors')
|
||||
@ -407,6 +434,7 @@ class TestMediaItem(TestCase, TestMixin):
|
||||
mock_song = MagicMock()
|
||||
mock_song.title = 'My Song'
|
||||
mock_song.copyright = 'My copyright'
|
||||
mock_song.songbook_entries = []
|
||||
service_item = ServiceItem(None)
|
||||
Settings().setValue('core/ccli number', '1234')
|
||||
|
||||
@ -414,7 +442,7 @@ class TestMediaItem(TestCase, TestMixin):
|
||||
self.media_item.generate_footer(service_item, mock_song)
|
||||
|
||||
# THEN: I get the following Array returned
|
||||
self.assertEqual(service_item.raw_footer, ['My Song', 'My copyright', 'CCLI License: 1234'],
|
||||
self.assertEqual(service_item.raw_footer, ['My Song', '© My copyright', 'CCLI License: 1234'],
|
||||
'The array should be returned correctly with a song, an author, copyright and ccli')
|
||||
|
||||
# WHEN: I amend the CCLI value
|
||||
@ -422,7 +450,7 @@ class TestMediaItem(TestCase, TestMixin):
|
||||
self.media_item.generate_footer(service_item, mock_song)
|
||||
|
||||
# THEN: I would get an amended footer string
|
||||
self.assertEqual(service_item.raw_footer, ['My Song', 'My copyright', 'CCLI License: 4321'],
|
||||
self.assertEqual(service_item.raw_footer, ['My Song', '© My copyright', 'CCLI License: 4321'],
|
||||
'The array should be returned correctly with a song, an author, copyright and amended ccli')
|
||||
|
||||
def test_build_song_footer_base_songbook(self):
|
||||
@ -448,15 +476,8 @@ class TestMediaItem(TestCase, TestMixin):
|
||||
# WHEN: I generate the Footer with default settings
|
||||
self.media_item.generate_footer(service_item, song)
|
||||
|
||||
# THEN: The songbook should not be in the footer
|
||||
self.assertEqual(service_item.raw_footer, ['My Song', 'My copyright'])
|
||||
|
||||
# WHEN: I activate the "display songbook" option
|
||||
self.media_item.display_songbook = True
|
||||
self.media_item.generate_footer(service_item, song)
|
||||
|
||||
# THEN: The songbook should be in the footer
|
||||
self.assertEqual(service_item.raw_footer, ['My Song', 'My copyright', 'My songbook #12, Thy songbook #502A'])
|
||||
self.assertEqual(service_item.raw_footer, ['My Song', '© My copyright', 'My songbook #12, Thy songbook #502A'])
|
||||
|
||||
def test_build_song_footer_copyright_enabled(self):
|
||||
"""
|
||||
@ -467,6 +488,7 @@ class TestMediaItem(TestCase, TestMixin):
|
||||
mock_song = MagicMock()
|
||||
mock_song.title = 'My Song'
|
||||
mock_song.copyright = 'My copyright'
|
||||
mock_song.songbook_entries = []
|
||||
service_item = ServiceItem(None)
|
||||
|
||||
# WHEN: I generate the Footer with default settings
|
||||
@ -483,13 +505,14 @@ class TestMediaItem(TestCase, TestMixin):
|
||||
mock_song = MagicMock()
|
||||
mock_song.title = 'My Song'
|
||||
mock_song.copyright = 'My copyright'
|
||||
mock_song.songbook_entries = []
|
||||
service_item = ServiceItem(None)
|
||||
|
||||
# WHEN: I generate the Footer with default settings
|
||||
self.media_item.generate_footer(service_item, mock_song)
|
||||
|
||||
# THEN: The copyright symbol should not be in the footer
|
||||
self.assertEqual(service_item.raw_footer, ['My Song', 'My copyright'])
|
||||
self.assertEqual(service_item.raw_footer, ['My Song', '© My copyright'])
|
||||
|
||||
def test_authors_match(self):
|
||||
"""
|
||||
|
Loading…
Reference in New Issue
Block a user