forked from openlp/openlp
Change generation on song footer and clean up code
bzr-revno: 2243
This commit is contained in:
commit
31c6d8deb4
@ -102,7 +102,6 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
self.setupUi()
|
||||
self.retranslateUi()
|
||||
self.auto_select_id = -1
|
||||
Registry().register_function(u'%s_service_load' % self.plugin.name, self.service_load)
|
||||
# Need to use event as called across threads and UI is updated
|
||||
QtCore.QObject.connect(self, QtCore.SIGNAL(u'%s_go_live' % self.plugin.name), self.go_live_remote)
|
||||
QtCore.QObject.connect(self, QtCore.SIGNAL(u'%s_add_to_service' % self.plugin.name), self.add_to_service_remote)
|
||||
@ -585,12 +584,15 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
else:
|
||||
return None
|
||||
|
||||
def service_load(self, message):
|
||||
def service_load(self, item):
|
||||
"""
|
||||
Method to add processing when a service has been loaded and individual service items need to be processed by the
|
||||
plugins.
|
||||
|
||||
``item``
|
||||
The item to be processed and returned.
|
||||
"""
|
||||
pass
|
||||
return item
|
||||
|
||||
def check_search_result(self):
|
||||
"""
|
||||
|
@ -715,13 +715,10 @@ class ServiceManager(QtGui.QWidget, ServiceManagerDialog):
|
||||
else:
|
||||
service_item.set_from_service(item, self.servicePath)
|
||||
service_item.validate_item(self.suffixes)
|
||||
self.load_item_unique_identifier = 0
|
||||
if service_item.is_capable(ItemCapabilities.OnLoadUpdate):
|
||||
Registry().execute(u'%s_service_load' % service_item.name.lower(), service_item)
|
||||
# if the item has been processed
|
||||
if service_item.unique_identifier == self.load_item_unique_identifier:
|
||||
service_item.edit_id = int(self.load_item_edit_id)
|
||||
service_item.temporary_edit = self.load_item_temporary
|
||||
new_item = Registry().get(service_item.name).service_load(service_item)
|
||||
if new_item:
|
||||
service_item = new_item
|
||||
self.add_service_item(service_item, repaint=False)
|
||||
delete_file(p_file)
|
||||
self.main_window.add_recent_file(file_name)
|
||||
@ -1260,14 +1257,6 @@ class ServiceManager(QtGui.QWidget, ServiceManagerDialog):
|
||||
self.repaint_service_list(-1, -1)
|
||||
self.application.set_normal_cursor()
|
||||
|
||||
def service_item_update(self, edit_id, unique_identifier, temporary=False):
|
||||
"""
|
||||
Triggered from plugins to update service items. Save the values as they will be used as part of the service load
|
||||
"""
|
||||
self.load_item_unique_identifier = unique_identifier
|
||||
self.load_item_edit_id = int(edit_id)
|
||||
self.load_item_temporary = str_to_bool(temporary)
|
||||
|
||||
def replace_service_item(self, newItem):
|
||||
"""
|
||||
Using the service item passed replace the one with the same edit id if found.
|
||||
|
@ -40,6 +40,7 @@ from openlp.plugins.custom.lib.db import CustomSlide
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class CustomSearch(object):
|
||||
"""
|
||||
An enumeration for custom search methods.
|
||||
@ -214,7 +215,6 @@ class CustomMediaItem(MediaManagerItem):
|
||||
Settings().setValue(u'%s/last search type' % self.settings_section, self.search_text_edit.current_search_type())
|
||||
# Reload the list considering the new search type.
|
||||
search_keywords = self.search_text_edit.displayText()
|
||||
search_results = []
|
||||
search_type = self.search_text_edit.current_search_type()
|
||||
if search_type == CustomSearch.Titles:
|
||||
log.debug(u'Titles Search')
|
||||
@ -252,7 +252,8 @@ class CustomMediaItem(MediaManagerItem):
|
||||
and_(CustomSlide.title == item.title, CustomSlide.theme_name == item.theme,
|
||||
CustomSlide.credits == item.raw_footer[0][len(item.title) + 1:]))
|
||||
if custom:
|
||||
self.service_manager.service_item_update(custom.id, item.unique_identifier)
|
||||
item.edit_id = custom.id
|
||||
return item
|
||||
else:
|
||||
if self.add_custom_from_service:
|
||||
self.create_from_service_item(item)
|
||||
@ -281,8 +282,6 @@ class CustomMediaItem(MediaManagerItem):
|
||||
custom.text = unicode(custom_xml.extract_xml(), u'utf-8')
|
||||
self.plugin.manager.save_object(custom)
|
||||
self.on_search_text_button_clicked()
|
||||
if item.name.lower() == u'custom':
|
||||
Registry().execute(u'service_item_update', u'%s:%s:%s' % (custom.id, item.unique_identifier, False))
|
||||
|
||||
def on_clear_text_button_click(self):
|
||||
"""
|
||||
|
@ -52,3 +52,4 @@ This allows OpenLP to use ``self.object`` for all the GUI elements while keeping
|
||||
them separate from the functionality, so that it is easier to recreate the GUI
|
||||
from the .ui files later if necessary.
|
||||
"""
|
||||
from editsongform import EditSongForm
|
||||
|
@ -72,10 +72,7 @@ class SongMediaItem(MediaManagerItem):
|
||||
def __init__(self, parent, plugin):
|
||||
self.icon_path = u'songs/song'
|
||||
MediaManagerItem.__init__(self, parent, plugin)
|
||||
self.edit_song_form = EditSongForm(self, self.main_window, self.plugin.manager)
|
||||
self.openLyrics = OpenLyrics(self.plugin.manager)
|
||||
self.single_service_item = False
|
||||
self.song_maintenance_form = SongMaintenanceForm(self.plugin.manager, self)
|
||||
# Holds information about whether the edit is remotely triggered and which Song is required.
|
||||
self.remote_song = -1
|
||||
self.edit_item = None
|
||||
@ -132,6 +129,12 @@ class SongMediaItem(MediaManagerItem):
|
||||
'Maintain the lists of authors, topics and books.'))
|
||||
|
||||
def initialise(self):
|
||||
"""
|
||||
Initialise variables when they cannot be initialised in the constructor.
|
||||
"""
|
||||
self.songMaintenanceForm = SongMaintenanceForm(self.plugin.manager, self)
|
||||
self.editSongForm = EditSongForm(self, self.main_window, self.plugin.manager)
|
||||
self.openLyrics = OpenLyrics(self.plugin.manager)
|
||||
self.search_text_edit.set_search_types([
|
||||
(SongSearch.Entire, u':/songs/song_search_all.png',
|
||||
translate('SongsPlugin.MediaItem', 'Entire Song'),
|
||||
@ -157,7 +160,6 @@ class SongMediaItem(MediaManagerItem):
|
||||
Settings().setValue(u'%s/last search type' % self.settings_section, self.search_text_edit.current_search_type())
|
||||
# Reload the list considering the new search type.
|
||||
search_keywords = unicode(self.search_text_edit.displayText())
|
||||
search_results = []
|
||||
search_type = self.search_text_edit.current_search_type()
|
||||
if search_type == SongSearch.Entire:
|
||||
log.debug(u'Entire Song Search')
|
||||
@ -457,14 +459,7 @@ class SongMediaItem(MediaManagerItem):
|
||||
for slide in verses:
|
||||
service_item.add_from_text(unicode(slide))
|
||||
service_item.title = song.title
|
||||
author_list = [unicode(author.display_name) for author in song.authors]
|
||||
service_item.raw_footer.append(song.title)
|
||||
service_item.raw_footer.append(create_separated_list(author_list))
|
||||
service_item.raw_footer.append(song.copyright)
|
||||
if Settings().value(u'core/ccli number'):
|
||||
service_item.raw_footer.append(translate('SongsPlugin.MediaItem', 'CCLI License: ') +
|
||||
Settings().value(u'core/ccli number'))
|
||||
service_item.audit = [song.title, author_list, song.copyright, unicode(song.ccli_number)]
|
||||
author_list = self.generate_footer(service_item, song)
|
||||
service_item.data_string = {u'title': song.search_title, u'authors': u', '.join(author_list)}
|
||||
service_item.xml_version = self.openLyrics.song_to_xml(song)
|
||||
# Add the audio file to the service item.
|
||||
@ -473,6 +468,30 @@ class SongMediaItem(MediaManagerItem):
|
||||
service_item.background_audio = [m.file_name for m in song.media_files]
|
||||
return True
|
||||
|
||||
def generate_footer(self, item, song):
|
||||
"""
|
||||
Generates the song footer based on a song and adds details to a service item.
|
||||
author_list is only required for initial song generation.
|
||||
|
||||
``item``
|
||||
The service item to be amended
|
||||
|
||||
``song``
|
||||
The song to be used to generate the footer
|
||||
"""
|
||||
author_list = [unicode(author.display_name) for author in song.authors]
|
||||
item.audit = [
|
||||
song.title, author_list, song.copyright, unicode(song.ccli_number)
|
||||
]
|
||||
item.raw_footer = []
|
||||
item.raw_footer.append(song.title)
|
||||
item.raw_footer.append(create_separated_list(author_list))
|
||||
item.raw_footer.append(song.copyright)
|
||||
if Settings().value(u'core/ccli number'):
|
||||
item.raw_footer.append(translate('SongsPlugin.MediaItem', 'CCLI License: ') +
|
||||
Settings().value(u'core/ccli number'))
|
||||
return author_list
|
||||
|
||||
def service_load(self, item):
|
||||
"""
|
||||
Triggered by a song being loaded by the service manager.
|
||||
@ -490,9 +509,8 @@ class SongMediaItem(MediaManagerItem):
|
||||
else:
|
||||
search_results = self.plugin.manager.get_all_objects(Song,
|
||||
Song.search_title == item.data_string[u'title'], Song.search_title.asc())
|
||||
editId = 0
|
||||
edit_id = 0
|
||||
add_song = True
|
||||
temporary = False
|
||||
if search_results:
|
||||
for song in search_results:
|
||||
author_list = item.data_string[u'authors']
|
||||
@ -505,7 +523,7 @@ class SongMediaItem(MediaManagerItem):
|
||||
break
|
||||
if same_authors and author_list.strip(u', ') == u'':
|
||||
add_song = False
|
||||
editId = song.id
|
||||
edit_id = song.id
|
||||
break
|
||||
# If there's any backing tracks, copy them over.
|
||||
if item.background_audio:
|
||||
@ -523,11 +541,11 @@ class SongMediaItem(MediaManagerItem):
|
||||
# If there's any backing tracks, copy them over.
|
||||
if item.background_audio:
|
||||
self._update_background_audio(song, item)
|
||||
editId = song.id
|
||||
temporary = True
|
||||
# Update service with correct song id.
|
||||
if editId:
|
||||
self.service_manager.service_item_update(editId, item.unique_identifier, temporary)
|
||||
edit_id = song.id
|
||||
# Update service with correct song id and return it to caller.
|
||||
item.edit_id = edit_id
|
||||
self.generate_footer(item, song)
|
||||
return item
|
||||
|
||||
def search(self, string, showError):
|
||||
"""
|
||||
|
@ -235,8 +235,7 @@ class SongsPlugin(Plugin):
|
||||
u'delete': translate('SongsPlugin', 'Delete the selected song.'),
|
||||
u'preview': translate('SongsPlugin', 'Preview the selected song.'),
|
||||
u'live': translate('SongsPlugin', 'Send the selected song live.'),
|
||||
u'service': translate('SongsPlugin',
|
||||
'Add the selected song to the service.')
|
||||
u'service': translate('SongsPlugin', 'Add the selected song to the service.')
|
||||
}
|
||||
self.set_plugin_ui_text_strings(tooltips)
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""
|
||||
Package to test the openlp.core.lib.screenlist package.
|
||||
"""
|
||||
import copy
|
||||
|
||||
from unittest import TestCase
|
||||
|
||||
from mock import MagicMock
|
||||
|
125
tests/functional/openlp_plugins/songs/test_mediaitem.py
Normal file
125
tests/functional/openlp_plugins/songs/test_mediaitem.py
Normal file
@ -0,0 +1,125 @@
|
||||
"""
|
||||
This module contains tests for the lib submodule of the Songs plugin.
|
||||
"""
|
||||
import os
|
||||
from tempfile import mkstemp
|
||||
from unittest import TestCase
|
||||
|
||||
from mock import patch, MagicMock
|
||||
|
||||
from PyQt4 import QtGui
|
||||
|
||||
from openlp.core.lib import Registry, ServiceItem, Settings
|
||||
|
||||
from openlp.plugins.songs.lib.mediaitem import SongMediaItem
|
||||
|
||||
|
||||
class TestMediaItem(TestCase):
|
||||
"""
|
||||
Test the functions in the :mod:`lib` module.
|
||||
"""
|
||||
def setUp(self):
|
||||
"""
|
||||
Set up the components need for all tests.
|
||||
"""
|
||||
Registry.create()
|
||||
Registry().register(u'service_list', MagicMock())
|
||||
Registry().register(u'main_window', MagicMock())
|
||||
with patch('openlp.core.lib.mediamanageritem.MediaManagerItem.__init__'), \
|
||||
patch('openlp.plugins.songs.forms.editsongform.EditSongForm.__init__'):
|
||||
self.media_item = SongMediaItem(MagicMock(), MagicMock())
|
||||
|
||||
fd, self.ini_file = mkstemp(u'.ini')
|
||||
Settings().set_filename(self.ini_file)
|
||||
self.application = QtGui.QApplication.instance()
|
||||
|
||||
def tearDown(self):
|
||||
"""
|
||||
Delete all the C++ objects at the end so that we don't have a segfault
|
||||
"""
|
||||
del self.application
|
||||
# Not all tests use settings!
|
||||
try:
|
||||
os.unlink(self.ini_file)
|
||||
os.unlink(Settings().fileName())
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def build_song_footer_one_author_test(self):
|
||||
"""
|
||||
Test build songs footer with basic song and one author
|
||||
"""
|
||||
# GIVEN: A Song and a Service Item
|
||||
mock_song = MagicMock()
|
||||
mock_song.title = u'My Song'
|
||||
mock_author = MagicMock()
|
||||
mock_author.display_name = u'my author'
|
||||
mock_song.authors = []
|
||||
mock_song.authors.append(mock_author)
|
||||
mock_song.copyright = u'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, [u'My Song', u'my author', u'My copyright'],
|
||||
u'The array should be returned correctly with a song, one author and copyright')
|
||||
self.assertEqual(author_list, [u'my author'],
|
||||
u'The author list should be returned correctly with one author')
|
||||
|
||||
def build_song_footer_two_authors_test(self):
|
||||
"""
|
||||
Test build songs footer with basic song and two authors
|
||||
"""
|
||||
# GIVEN: A Song and a Service Item
|
||||
mock_song = MagicMock()
|
||||
mock_song.title = u'My Song'
|
||||
mock_author = MagicMock()
|
||||
mock_author.display_name = u'my author'
|
||||
mock_song.authors = []
|
||||
mock_song.authors.append(mock_author)
|
||||
mock_author = MagicMock()
|
||||
mock_author.display_name = u'another author'
|
||||
mock_song.authors.append(mock_author)
|
||||
mock_song.copyright = u'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, [u'My Song', u'my author and another author', u'My copyright'],
|
||||
u'The array should be returned correctly with a song, two authors and copyright')
|
||||
self.assertEqual(author_list, [u'my author', u'another author'],
|
||||
u'The author list should be returned correctly with two authors')
|
||||
|
||||
def build_song_footer_base_ccli_test(self):
|
||||
"""
|
||||
Test build songs footer with basic song and two authors
|
||||
"""
|
||||
# GIVEN: A Song and a Service Item and a configured CCLI license
|
||||
mock_song = MagicMock()
|
||||
mock_song.title = u'My Song'
|
||||
mock_author = MagicMock()
|
||||
mock_author.display_name = u'my author'
|
||||
mock_song.authors = []
|
||||
mock_song.authors.append(mock_author)
|
||||
mock_song.copyright = u'My copyright'
|
||||
service_item = ServiceItem(None)
|
||||
Settings().setValue(u'core/ccli number', u'1234')
|
||||
|
||||
# WHEN: I generate the Footer with default settings
|
||||
self.media_item.generate_footer(service_item, mock_song)
|
||||
|
||||
# THEN: I get the following Array returned
|
||||
self.assertEqual(service_item.raw_footer, [u'My Song', u'my author', u'My copyright', u'CCLI License: 1234'],
|
||||
u'The array should be returned correctly with a song, an author, copyright and ccli')
|
||||
|
||||
# WHEN: I amend the CCLI value
|
||||
Settings().setValue(u'core/ccli number', u'4321')
|
||||
self.media_item.generate_footer(service_item, mock_song)
|
||||
|
||||
# THEN: I would get an amended footer string
|
||||
self.assertEqual(service_item.raw_footer, [u'My Song', u'my author', u'My copyright', u'CCLI License: 4321'],
|
||||
u'The array should be returned correctly with a song, an author, copyright and amended ccli')
|
Loading…
Reference in New Issue
Block a user