forked from openlp/openlp
head
This commit is contained in:
commit
b2563f0ce0
@ -47,26 +47,13 @@ class Renderer(object):
|
||||
Initialise the renderer.
|
||||
"""
|
||||
self._rect = None
|
||||
self._debug = False
|
||||
self._display_shadow_size_footer = 0
|
||||
self._display_outline_size_footer = 0
|
||||
self.theme_name = None
|
||||
self._theme = None
|
||||
self._bg_image_filename = None
|
||||
self.frame = None
|
||||
self.frame_opaque = None
|
||||
self.bg_frame = None
|
||||
self.bg_image = None
|
||||
|
||||
def set_debug(self, debug):
|
||||
"""
|
||||
Set the debug mode of the renderer.
|
||||
|
||||
``debug``
|
||||
The debug mode.
|
||||
"""
|
||||
self._debug = debug
|
||||
|
||||
def set_theme(self, theme):
|
||||
"""
|
||||
Set the theme to be used.
|
||||
@ -159,7 +146,7 @@ class Renderer(object):
|
||||
doc = QtGui.QTextDocument()
|
||||
doc.setPageSize(QtCore.QSizeF(self._rect.width(), self._rect.height()))
|
||||
df = doc.defaultFont()
|
||||
df.setPixelSize(self._theme.font_main_proportion)
|
||||
df.setPointSize(self._theme.font_main_proportion)
|
||||
df.setFamily(self._theme.font_main_name)
|
||||
main_weight = 50
|
||||
if self._theme.font_main_weight == u'Bold':
|
||||
@ -188,7 +175,7 @@ class Renderer(object):
|
||||
# Text too long so gone to next mage
|
||||
if layout.pageCount() != 1:
|
||||
formatted.append(shell % old_html_text)
|
||||
temp_text = line
|
||||
temp_text = line + line_end
|
||||
old_html_text = temp_text
|
||||
formatted.append(shell % old_html_text)
|
||||
log.debug(u'format_slide - End')
|
||||
|
@ -93,6 +93,7 @@ class RenderManager(object):
|
||||
"""
|
||||
self.global_theme = global_theme
|
||||
self.theme_level = theme_level
|
||||
self.themedata = None
|
||||
|
||||
def set_service_theme(self, service_theme):
|
||||
"""
|
||||
@ -102,6 +103,7 @@ class RenderManager(object):
|
||||
The service-level theme to be set.
|
||||
"""
|
||||
self.service_theme = service_theme
|
||||
self.themedata = None
|
||||
|
||||
def set_override_theme(self, theme, overrideLevels=False):
|
||||
"""
|
||||
@ -111,6 +113,10 @@ class RenderManager(object):
|
||||
``theme``
|
||||
The name of the song-level theme. None means the service
|
||||
item wants to use the given value.
|
||||
|
||||
``overrideLevels``
|
||||
Used to force the theme data passed in to be used.
|
||||
|
||||
"""
|
||||
log.debug(u'set override theme to %s', theme)
|
||||
theme_level = self.theme_level
|
||||
@ -137,6 +143,7 @@ class RenderManager(object):
|
||||
if self.theme != self.renderer.theme_name or self.themedata is None \
|
||||
or overrideLevels:
|
||||
log.debug(u'theme is now %s', self.theme)
|
||||
# Force the theme to be the one passed in.
|
||||
if overrideLevels:
|
||||
self.themedata = theme
|
||||
else:
|
||||
|
@ -322,9 +322,6 @@ class MainDisplay(DisplayWidget):
|
||||
# Make display show up if in single screen mode
|
||||
if self.isLive:
|
||||
self.setVisible(True)
|
||||
# save preview for debugging
|
||||
if log.isEnabledFor(logging.DEBUG):
|
||||
preview.save(u'temp.png', u'png')
|
||||
return preview
|
||||
|
||||
def buildHtml(self, serviceItem):
|
||||
|
@ -574,7 +574,7 @@ class ServiceManager(QtGui.QWidget):
|
||||
* An osd which is a pickle of the service items
|
||||
* All image, presentation and video files needed to run the service.
|
||||
"""
|
||||
log.debug(u'onSaveService')
|
||||
log.debug(u'onSaveService %s' % quick)
|
||||
if not quick or self.isNew:
|
||||
filename = QtGui.QFileDialog.getSaveFileName(self,
|
||||
translate('OpenLP.ServiceManager', 'Save Service'),
|
||||
@ -755,6 +755,7 @@ class ServiceManager(QtGui.QWidget):
|
||||
"""
|
||||
Set the theme for the current service
|
||||
"""
|
||||
log.debug(u'onThemeComboBoxSelected')
|
||||
self.service_theme = unicode(self.themeComboBox.currentText())
|
||||
self.parent.RenderManager.set_service_theme(self.service_theme)
|
||||
QtCore.QSettings().setValue(
|
||||
@ -767,6 +768,7 @@ class ServiceManager(QtGui.QWidget):
|
||||
The theme may have changed in the settings dialog so make
|
||||
sure the theme combo box is in the correct state.
|
||||
"""
|
||||
log.debug(u'themeChange')
|
||||
if self.parent.RenderManager.theme_level == ThemeLevel.Global:
|
||||
self.toolbar.actions[u'ThemeLabel'].setVisible(False)
|
||||
self.toolbar.actions[u'ThemeWidget'].setVisible(False)
|
||||
@ -779,6 +781,7 @@ class ServiceManager(QtGui.QWidget):
|
||||
Rebuild the service list as things have changed and a
|
||||
repaint is the easiest way to do this.
|
||||
"""
|
||||
log.debug(u'regenerateServiceItems')
|
||||
# force reset of renderer as theme data has changed
|
||||
self.parent.RenderManager.themedata = None
|
||||
if self.serviceItems:
|
||||
@ -800,6 +803,7 @@ class ServiceManager(QtGui.QWidget):
|
||||
``item``
|
||||
Service Item to be added
|
||||
"""
|
||||
log.debug(u'addServiceItem')
|
||||
sitem = self.findServiceItem()[0]
|
||||
item.render()
|
||||
if replace:
|
||||
|
@ -51,9 +51,9 @@ class CSVBible(BibleDB):
|
||||
if u'booksfile' not in kwargs:
|
||||
raise KeyError(u'You have to supply a file to import books from.')
|
||||
self.booksfile = kwargs[u'booksfile']
|
||||
if u'versesfile' not in kwargs:
|
||||
if u'versefile' not in kwargs:
|
||||
raise KeyError(u'You have to supply a file to import verses from.')
|
||||
self.versesfile = kwargs[u'versesfile']
|
||||
self.versesfile = kwargs[u'versefile']
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'bibles_stop_import'), self.stop_import)
|
||||
|
||||
|
@ -47,7 +47,6 @@ class BibleListView(BaseListWithDnD):
|
||||
self.parent().onListViewResize(event.size().width(),
|
||||
event.size().width())
|
||||
|
||||
|
||||
class BibleMediaItem(MediaManagerItem):
|
||||
"""
|
||||
This is the custom media manager item for Bibles.
|
||||
@ -466,19 +465,27 @@ class BibleMediaItem(MediaManagerItem):
|
||||
|
||||
def generateSlideData(self, service_item, item=None):
|
||||
"""
|
||||
Generates and formats the slides for the service item.
|
||||
Generates and formats the slides for the service item as well as the
|
||||
service item's title.
|
||||
"""
|
||||
log.debug(u'generating slide data')
|
||||
items = self.listView.selectedIndexes()
|
||||
if len(items) == 0:
|
||||
return False
|
||||
has_dual_bible = False
|
||||
bible_text = u''
|
||||
old_chapter = u''
|
||||
raw_footer = []
|
||||
raw_slides = []
|
||||
service_item.add_capability(ItemCapabilities.AllowsPreview)
|
||||
service_item.add_capability(ItemCapabilities.AllowsLoop)
|
||||
service_item.add_capability(ItemCapabilities.AllowsAdditions)
|
||||
for item in items:
|
||||
bitem = self.listView.item(item.row())
|
||||
reference = bitem.data(QtCore.Qt.UserRole)
|
||||
if isinstance(reference, QtCore.QVariant):
|
||||
reference = reference.toPyObject()
|
||||
dual_bible = self._decodeQtObject(reference, 'dual_bible')
|
||||
if dual_bible:
|
||||
has_dual_bible = True
|
||||
break
|
||||
# Let's loop through the main lot, and assemble our verses.
|
||||
for item in items:
|
||||
bitem = self.listView.item(item.row())
|
||||
@ -491,7 +498,7 @@ class BibleMediaItem(MediaManagerItem):
|
||||
bible = self._decodeQtObject(reference, 'bible')
|
||||
version = self._decodeQtObject(reference, 'version')
|
||||
copyright = self._decodeQtObject(reference, 'copyright')
|
||||
#permission = self._decodeQtObject(reference, 'permission')
|
||||
permission = self._decodeQtObject(reference, 'permission')
|
||||
text = self._decodeQtObject(reference, 'text')
|
||||
dual_bible = self._decodeQtObject(reference, 'dual_bible')
|
||||
if dual_bible:
|
||||
@ -499,70 +506,57 @@ class BibleMediaItem(MediaManagerItem):
|
||||
'dual_version')
|
||||
dual_copyright = self._decodeQtObject(reference,
|
||||
'dual_copyright')
|
||||
#dual_permission = self._decodeQtObject(reference,
|
||||
# 'dual_permission')
|
||||
dual_permission = self._decodeQtObject(reference,
|
||||
'dual_permission')
|
||||
dual_text = self._decodeQtObject(reference, 'dual_text')
|
||||
if self.parent.settings_tab.display_style == 1:
|
||||
verse_text = self.formatVerse(old_chapter, chapter, verse,
|
||||
u'{su}(', u'){/su}')
|
||||
elif self.parent.settings_tab.display_style == 2:
|
||||
verse_text = self.formatVerse(old_chapter, chapter, verse,
|
||||
u'{su}{', u'}{/su}')
|
||||
elif self.parent.settings_tab.display_style == 3:
|
||||
verse_text = self.formatVerse(old_chapter, chapter, verse,
|
||||
u'{su}[', u']{/su}')
|
||||
else:
|
||||
verse_text = self.formatVerse(old_chapter, chapter, verse,
|
||||
u'{su}', u'{/su}')
|
||||
old_chapter = chapter
|
||||
footer = u'%s (%s %s)' % (book, version, copyright)
|
||||
# If not found add to footer
|
||||
verse_text = self.formatVerse(old_chapter, chapter, verse)
|
||||
footer = u'%s (%s %s %s)' % (book, version, copyright, permission)
|
||||
if footer not in raw_footer:
|
||||
raw_footer.append(footer)
|
||||
if has_dual_bible:
|
||||
if dual_bible:
|
||||
footer = u'%s (%s %s)' % (book, dual_version,
|
||||
dual_copyright)
|
||||
# If not found add second version and copyright to footer.
|
||||
footer = u'%s (%s %s %s)' % (book, dual_version,
|
||||
dual_copyright, dual_permission)
|
||||
if footer not in raw_footer:
|
||||
raw_footer.append(footer)
|
||||
bible_text = u'%s %s \n\n %s %s' % (verse_text, text,
|
||||
# If there is an old bible_text we have to add it.
|
||||
if bible_text:
|
||||
raw_slides.append(bible_text)
|
||||
bible_text = u''
|
||||
bible_text = u'%s %s\n\n%s %s' % (verse_text, text,
|
||||
verse_text, dual_text)
|
||||
raw_slides.append(bible_text)
|
||||
bible_text = u''
|
||||
elif self.parent.settings_tab.layout_style == 0:
|
||||
bible_text = u'%s %s' % (verse_text, text)
|
||||
raw_slides.append(bible_text)
|
||||
bible_text = u''
|
||||
else:
|
||||
bible_text = u'%s %s %s\n' % (bible_text, verse_text, text)
|
||||
# If we are 'Verse Per Slide' then create a new slide.
|
||||
elif self.parent.settings_tab.layout_style == 0:
|
||||
bible_text = u'%s %s' % (verse_text, text)
|
||||
raw_slides.append(bible_text)
|
||||
bible_text = u''
|
||||
# If we are 'Verse Per Line' then force a new line.
|
||||
if self.parent.settings_tab.layout_style == 1:
|
||||
text = text + u'\n'
|
||||
elif self.parent.settings_tab.layout_style == 1:
|
||||
bible_text = u'%s %s %s\n' % (bible_text, verse_text, text)
|
||||
# We have to be 'Continuous'.
|
||||
else:
|
||||
bible_text = u'%s %s %s\n' % (bible_text, verse_text, text)
|
||||
old_chapter = chapter
|
||||
# If there are no more items we check whether we have to add bible_text.
|
||||
if bible_text:
|
||||
raw_slides.append(bible_text)
|
||||
bible_text = u''
|
||||
# Service Item: Capabilities
|
||||
if self.parent.settings_tab.layout_style == 2 and not has_dual_bible:
|
||||
# split the line but do not replace line breaks in renderer
|
||||
service_item.add_capability(ItemCapabilities.NoLineBreaks)
|
||||
text = text + u'\n'
|
||||
bible_text = u'%s %s %s' % (bible_text, verse_text, text)
|
||||
# If we are 'Verse Per Slide' then create a new slide.
|
||||
if self.parent.settings_tab.layout_style == 0:
|
||||
raw_slides.append(bible_text)
|
||||
bible_text = u''
|
||||
# If we are not 'Verse Per Slide' we have to make sure, that we
|
||||
# add more verses.
|
||||
else:
|
||||
if item.row() < len(items) - 1:
|
||||
bitem = items[item.row() + 1]
|
||||
reference = bitem.data(QtCore.Qt.UserRole)
|
||||
if isinstance(reference, QtCore.QVariant):
|
||||
reference = reference.toPyObject()
|
||||
bible_new = self._decodeQtObject(reference, 'bible')
|
||||
dual_bible_new = self._decodeQtObject(reference,
|
||||
'dual_bible')
|
||||
if dual_bible_new:
|
||||
raw_slides.append(bible_text)
|
||||
bible_text = u''
|
||||
elif bible != bible_new:
|
||||
raw_slides.append(bible_text)
|
||||
bible_text = u''
|
||||
else:
|
||||
raw_slides.append(bible_text)
|
||||
bible_text = u''
|
||||
# service item title
|
||||
service_item.add_capability(ItemCapabilities.AllowsPreview)
|
||||
service_item.add_capability(ItemCapabilities.AllowsLoop)
|
||||
service_item.add_capability(ItemCapabilities.AllowsAdditions)
|
||||
# Service Item: Title
|
||||
if not service_item.title:
|
||||
if dual_bible:
|
||||
service_item.title = u'%s (%s, %s) %s' % (book, version,
|
||||
@ -573,7 +567,7 @@ class BibleMediaItem(MediaManagerItem):
|
||||
translate('BiblesPlugin.MediaItem', 'etc')) == -1:
|
||||
service_item.title = u'%s, %s' % (service_item.title,
|
||||
translate('BiblesPlugin.MediaItem', 'etc'))
|
||||
# item theme
|
||||
# Service Item: Theme
|
||||
if len(self.parent.settings_tab.bible_theme) == 0:
|
||||
service_item.theme = None
|
||||
else:
|
||||
@ -587,14 +581,20 @@ class BibleMediaItem(MediaManagerItem):
|
||||
service_item.raw_footer = raw_footer
|
||||
return True
|
||||
|
||||
def formatVerse(self, old_chapter, chapter, verse, opening, closing):
|
||||
verse_text = opening
|
||||
if old_chapter != chapter:
|
||||
verse_text += chapter + u':'
|
||||
elif not self.parent.settings_tab.show_new_chapters:
|
||||
verse_text += chapter + u':'
|
||||
verse_text += verse
|
||||
verse_text += closing
|
||||
def formatVerse(self, old_chapter, chapter, verse):
|
||||
if not self.parent.settings_tab.show_new_chapters or \
|
||||
old_chapter != chapter:
|
||||
verse_text = chapter + u':' + verse
|
||||
else:
|
||||
verse_text = verse
|
||||
if self.parent.settings_tab.display_style == 1:
|
||||
verse_text = u'{su}(' + verse_text + u'){/su}'
|
||||
elif self.parent.settings_tab.display_style == 2:
|
||||
verse_text = u'{su}{' + verse_text + u'}{/su}'
|
||||
elif self.parent.settings_tab.display_style == 3:
|
||||
verse_text = u'{su}[' + verse_text + u']{/su}'
|
||||
else:
|
||||
verse_text = u'{su}' + verse_text + u'{/su}'
|
||||
return verse_text
|
||||
|
||||
def reloadBibles(self):
|
||||
@ -639,14 +639,14 @@ class BibleMediaItem(MediaManagerItem):
|
||||
for i in range(int(range_from), int(range_to) + 1):
|
||||
combo.addItem(unicode(i))
|
||||
|
||||
def displayResults(self, bible, dual_bible=None):
|
||||
def displayResults(self, bible, dual_bible=u''):
|
||||
"""
|
||||
Displays the search results in the media manager. All data needed for
|
||||
further action is saved for/in each row.
|
||||
"""
|
||||
version = self.parent.manager.get_meta_data(bible, u'Version')
|
||||
copyright = self.parent.manager.get_meta_data(bible, u'Copyright')
|
||||
#permission = self.parent.manager.get_meta_data(bible, u'Permissions')
|
||||
permission = self.parent.manager.get_meta_data(bible, u'Permissions')
|
||||
if dual_bible:
|
||||
dual_version = self.parent.manager.get_meta_data(dual_bible,
|
||||
u'Version')
|
||||
@ -654,43 +654,41 @@ class BibleMediaItem(MediaManagerItem):
|
||||
u'Copyright')
|
||||
dual_permission = self.parent.manager.get_meta_data(dual_bible,
|
||||
u'Permissions')
|
||||
if dual_permission:
|
||||
dual_permission = dual_permission.value
|
||||
else:
|
||||
if not dual_permission:
|
||||
dual_permission = u''
|
||||
# We count the number of rows which are maybe already present.
|
||||
start_count = self.listView.count()
|
||||
for count, verse in enumerate(self.search_results):
|
||||
if dual_bible:
|
||||
vdict = {
|
||||
'book':QtCore.QVariant(verse.book.name),
|
||||
'chapter':QtCore.QVariant(verse.chapter),
|
||||
'verse':QtCore.QVariant(verse.verse),
|
||||
'bible':QtCore.QVariant(bible),
|
||||
'version':QtCore.QVariant(version.value),
|
||||
'copyright':QtCore.QVariant(copyright.value),
|
||||
#'permission':QtCore.QVariant(permission.value),
|
||||
'text':QtCore.QVariant(verse.text),
|
||||
'dual_bible':QtCore.QVariant(dual_bible),
|
||||
'dual_version':QtCore.QVariant(dual_version.value),
|
||||
'dual_copyright':QtCore.QVariant(dual_copyright.value),
|
||||
#'dual_permission':QtCore.QVariant(dual_permission),
|
||||
'dual_text':QtCore.QVariant(
|
||||
'book': QtCore.QVariant(verse.book.name),
|
||||
'chapter': QtCore.QVariant(verse.chapter),
|
||||
'verse': QtCore.QVariant(verse.verse),
|
||||
'bible': QtCore.QVariant(bible),
|
||||
'version': QtCore.QVariant(version.value),
|
||||
'copyright': QtCore.QVariant(copyright.value),
|
||||
'permission': QtCore.QVariant(permission.value),
|
||||
'text': QtCore.QVariant(verse.text),
|
||||
'dual_bible': QtCore.QVariant(dual_bible),
|
||||
'dual_version': QtCore.QVariant(dual_version.value),
|
||||
'dual_copyright': QtCore.QVariant(dual_copyright.value),
|
||||
'dual_permission': QtCore.QVariant(dual_permission.value),
|
||||
'dual_text': QtCore.QVariant(
|
||||
self.dual_search_results[count].text)
|
||||
}
|
||||
bible_text = u' %s %d:%d (%s, %s)' % (verse.book.name,
|
||||
verse.chapter, verse.verse, version.value, dual_version.value)
|
||||
else:
|
||||
vdict = {
|
||||
'book':QtCore.QVariant(verse.book.name),
|
||||
'chapter':QtCore.QVariant(verse.chapter),
|
||||
'verse':QtCore.QVariant(verse.verse),
|
||||
'bible':QtCore.QVariant(bible),
|
||||
'version':QtCore.QVariant(version.value),
|
||||
'copyright':QtCore.QVariant(copyright.value),
|
||||
#'permission':QtCore.QVariant(permission.value),
|
||||
'text':QtCore.QVariant(verse.text),
|
||||
'dual_bible':QtCore.QVariant(dual_bible)
|
||||
'book': QtCore.QVariant(verse.book.name),
|
||||
'chapter': QtCore.QVariant(verse.chapter),
|
||||
'verse': QtCore.QVariant(verse.verse),
|
||||
'bible': QtCore.QVariant(bible),
|
||||
'version': QtCore.QVariant(version.value),
|
||||
'copyright': QtCore.QVariant(copyright.value),
|
||||
'permission': QtCore.QVariant(permission.value),
|
||||
'text': QtCore.QVariant(verse.text),
|
||||
'dual_bible': QtCore.QVariant(dual_bible)
|
||||
}
|
||||
bible_text = u' %s %d:%d (%s)' % (verse.book.name,
|
||||
verse.chapter, verse.verse, version.value)
|
||||
|
@ -83,6 +83,12 @@ class ImportWizardForm(QtGui.QWizard, Ui_SongImportWizard):
|
||||
QtCore.QObject.connect(self.wordsOfWorshipRemoveButton,
|
||||
QtCore.SIGNAL(u'clicked()'),
|
||||
self.onWordsOfWorshipRemoveButtonClicked)
|
||||
QtCore.QObject.connect(self.ccliAddButton,
|
||||
QtCore.SIGNAL(u'clicked()'),
|
||||
self.onCCLIAddButtonClicked)
|
||||
QtCore.QObject.connect(self.ccliRemoveButton,
|
||||
QtCore.SIGNAL(u'clicked()'),
|
||||
self.onCCLIRemoveButtonClicked)
|
||||
QtCore.QObject.connect(self.songsOfFellowshipAddButton,
|
||||
QtCore.SIGNAL(u'clicked()'),
|
||||
self.onSongsOfFellowshipAddButtonClicked)
|
||||
@ -277,6 +283,16 @@ class ImportWizardForm(QtGui.QWizard, Ui_SongImportWizard):
|
||||
def onWordsOfWorshipRemoveButtonClicked(self):
|
||||
self.removeSelectedItems(self.wordsOfWorshipFileListWidget)
|
||||
|
||||
def onCCLIAddButtonClicked(self):
|
||||
self.getFiles(
|
||||
translate('SongsPlugin.ImportWizardForm',
|
||||
'Select CCLI Files'),
|
||||
self.ccliFileListWidget
|
||||
)
|
||||
|
||||
def onCCLIRemoveButtonClicked(self):
|
||||
self.removeSelectedItems(self.ccliFileListWidget)
|
||||
|
||||
def onSongsOfFellowshipAddButtonClicked(self):
|
||||
self.getFiles(
|
||||
translate('SongsPlugin.ImportWizardForm',
|
||||
|
310
openlp/plugins/songs/lib/cclifileimport.py
Executable file
310
openlp/plugins/songs/lib/cclifileimport.py
Executable file
@ -0,0 +1,310 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2010 Raoul Snyman #
|
||||
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
|
||||
# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian #
|
||||
# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
|
||||
# Carsten Tinggaard, Frode Woldsund, Derek Scotney #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# 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 #
|
||||
###############################################################################
|
||||
|
||||
import logging
|
||||
import os
|
||||
import chardet
|
||||
import codecs
|
||||
|
||||
from songimport import SongImport
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
class CCLIFileImportError(Exception):
|
||||
pass
|
||||
|
||||
class CCLIFileImport(SongImport):
|
||||
"""
|
||||
The :class:`CCLIFileImport` class provides OpenLP with the
|
||||
ability to import CCLI SongSelect song files in both .txt and
|
||||
.usr formats. See http://www.ccli.com
|
||||
"""
|
||||
|
||||
def __init__(self, manager, **kwargs):
|
||||
"""
|
||||
Initialise the import.
|
||||
|
||||
``manager``
|
||||
The song manager for the running OpenLP installation.
|
||||
``filenames``
|
||||
The files to be imported.
|
||||
"""
|
||||
SongImport.__init__(self, manager)
|
||||
if u'filenames' in kwargs:
|
||||
self.filenames = kwargs[u'filenames']
|
||||
log.debug(self.filenames)
|
||||
else:
|
||||
raise KeyError(u'Keyword argument "filenames" not supplied.')
|
||||
|
||||
def do_import(self):
|
||||
"""
|
||||
Import either a .usr or a .txt SongSelect file
|
||||
"""
|
||||
log.debug(u'Starting CCLI File Import')
|
||||
song_total = len(self.filenames)
|
||||
self.import_wizard.importProgressBar.setMaximum(song_total)
|
||||
song_count = 1
|
||||
for filename in self.filenames:
|
||||
self.import_wizard.incrementProgressBar(
|
||||
u'Importing song %s of %s' % (song_count, song_total))
|
||||
filename = unicode(filename)
|
||||
log.debug(u'Importing CCLI File: %s', filename)
|
||||
lines = []
|
||||
if os.path.isfile(filename):
|
||||
detect_file = open(filename, u'r')
|
||||
details = chardet.detect(detect_file.read(2048))
|
||||
detect_file.close()
|
||||
infile = codecs.open(filename, u'r', details['encoding'])
|
||||
lines = infile.readlines()
|
||||
ext = os.path.splitext(filename)[1]
|
||||
if ext.lower() == ".usr":
|
||||
log.info(u'SongSelect .usr format file found %s: ' , filename)
|
||||
self.do_import_usr_file(lines)
|
||||
elif ext.lower() == ".txt":
|
||||
log.info(u'SongSelect .txt format file found %s: ', filename)
|
||||
self.do_import_txt_file(lines)
|
||||
else:
|
||||
log.info(u'Extension %s is not valid', filename)
|
||||
pass
|
||||
song_count += 1
|
||||
if self.stop_import_flag:
|
||||
return False
|
||||
return True
|
||||
|
||||
def do_import_usr_file(self, textList):
|
||||
"""
|
||||
The :method:`do_import_usr_file` method provides OpenLP
|
||||
with the ability to import CCLI SongSelect songs in
|
||||
*USR* file format
|
||||
|
||||
``textList``
|
||||
An array of strings containing the usr file content.
|
||||
|
||||
**SongSelect .usr file format**
|
||||
``[File]``
|
||||
USR file format first line
|
||||
``Type=``
|
||||
Indicates the file type
|
||||
e.g. *Type=SongSelect Import File*
|
||||
``Version=3.0``
|
||||
File format version
|
||||
``[S A2672885]``
|
||||
Contains the CCLI Song number e.g. *2672885*
|
||||
``Title=``
|
||||
Contains the song title (e.g. *Title=Above All*)
|
||||
``Author=``
|
||||
Contains a | delimited list of the song authors
|
||||
e.g. *Author=LeBlanc, Lenny | Baloche, Paul*
|
||||
``Copyright=``
|
||||
Contains a | delimited list of the song copyrights
|
||||
e.g. Copyright=1999 Integrity's Hosanna! Music |
|
||||
LenSongs Publishing (Verwaltet von Gerth Medien
|
||||
Musikverlag)
|
||||
``Admin=``
|
||||
Contains the song administrator
|
||||
e.g. *Admin=Gerth Medien Musikverlag*
|
||||
``Themes=``
|
||||
Contains a /t delimited list of the song themes
|
||||
e.g. *Themes=Cross/tKingship/tMajesty/tRedeemer*
|
||||
``Keys=``
|
||||
Contains the keys in which the music is played??
|
||||
e.g. *Keys=A*
|
||||
``Fields=``
|
||||
Contains a list of the songs fields in order /t delimited
|
||||
e.g. *Fields=Vers 1/tVers 2/tChorus 1/tAndere 1*
|
||||
``Words=``
|
||||
Contains the songs various lyrics in order as shown by the
|
||||
*Fields* description
|
||||
e.g. *Words=Above all powers....* [/n = CR, /n/t = CRLF]
|
||||
"""
|
||||
log.debug(u'USR file text: %s', textList)
|
||||
lyrics = []
|
||||
self.set_defaults()
|
||||
for line in textList:
|
||||
if line.startswith(u'Title='):
|
||||
song_name = line[6:].strip()
|
||||
elif line.startswith(u'Author='):
|
||||
song_author = line[7:].strip()
|
||||
elif line.startswith(u'Copyright='):
|
||||
song_copyright = line[10:].strip()
|
||||
elif line.startswith(u'[S A'):
|
||||
song_ccli = line[4:-3].strip()
|
||||
elif line.startswith(u'Fields='):
|
||||
#Fields contain single line indicating verse, chorus, etc,
|
||||
#/t delimited, same as with words field. store seperately
|
||||
#and process at end.
|
||||
song_fields = line[7:].strip()
|
||||
elif line.startswith(u'Words='):
|
||||
song_words = line[6:].strip()
|
||||
#Unhandled usr keywords:Type,Version,Admin,Themes,Keys
|
||||
#Process Fields and words sections
|
||||
field_list = song_fields.split(u'/t')
|
||||
words_list = song_words.split(u'/t')
|
||||
for counter in range(0, len(field_list)):
|
||||
if field_list[counter].startswith(u'Ver'):
|
||||
verse_type = u'V'
|
||||
elif field_list[counter].startswith(u'Ch'):
|
||||
verse_type = u'C'
|
||||
elif field_list[counter].startswith(u'Br'):
|
||||
verse_type = u'B'
|
||||
else: #Other
|
||||
verse_type = u'O'
|
||||
verse_text = unicode(words_list[counter])
|
||||
verse_text = verse_text.replace("/n", "\n")
|
||||
if len(verse_text) > 0:
|
||||
self.add_verse(verse_text, verse_type);
|
||||
#Handle multiple authors
|
||||
author_list = song_author.split(u'/')
|
||||
if len(author_list) < 2:
|
||||
author_list = song_author.split(u'|')
|
||||
for author in author_list:
|
||||
seperated = author.split(u',')
|
||||
self.add_author(seperated[1].strip() + " " + seperated[0].strip())
|
||||
self.title = song_name
|
||||
self.copyright = song_copyright
|
||||
self.ccli_number = song_ccli
|
||||
self.finish()
|
||||
|
||||
def do_import_txt_file(self, textList):
|
||||
"""
|
||||
The :method:`do_import_txt_file` method provides OpenLP
|
||||
with the ability to import CCLI SongSelect songs in
|
||||
*TXT* file format
|
||||
|
||||
``textList``
|
||||
An array of strings containing the txt file content.
|
||||
|
||||
**SongSelect .txt file format**
|
||||
|
||||
``Song Title``
|
||||
Contains the song title
|
||||
|
||||
<Empty line>
|
||||
|
||||
``Title of following verse/chorus and number``
|
||||
e.g. Verse 1, Chorus 1
|
||||
|
||||
``Verse/Chorus lyrics``
|
||||
|
||||
<Empty line>
|
||||
|
||||
<Empty line>
|
||||
|
||||
``Title of next verse/chorus (repeats)``
|
||||
|
||||
``Verse/Chorus lyrics``
|
||||
|
||||
<Empty line>
|
||||
|
||||
<Empty line>
|
||||
|
||||
``Song CCLI Number``
|
||||
e.g. CCLI Number (e.g.CCLI-Liednummer: 2672885)
|
||||
``Song Copyright``
|
||||
e.g. © 1999 Integrity's Hosanna! Music | LenSongs Publishing
|
||||
``Song Authors``
|
||||
e.g. Lenny LeBlanc | Paul Baloche
|
||||
``Licencing info``
|
||||
e.g. For use solely with the SongSelect Terms of Use.
|
||||
All rights Reserved. www.ccli.com
|
||||
``CCLI Licence number of user``
|
||||
e.g. CCL-Liedlizenznummer: 14 / CCLI License No. 14
|
||||
"""
|
||||
log.debug(u'TXT file text: %s', textList)
|
||||
self.set_defaults()
|
||||
line_number = 0
|
||||
verse_text = u''
|
||||
song_comments = u''
|
||||
song_copyright = u'';
|
||||
verse_start = False
|
||||
for line in textList:
|
||||
clean_line = line.strip()
|
||||
if not clean_line:
|
||||
if line_number==0:
|
||||
continue
|
||||
elif verse_start:
|
||||
if verse_text:
|
||||
self.add_verse(verse_text, verse_type)
|
||||
verse_text = ''
|
||||
verse_start = False
|
||||
else:
|
||||
#line_number=0, song title
|
||||
if line_number==0:
|
||||
song_name = clean_line
|
||||
line_number += 1
|
||||
#line_number=1, verses
|
||||
elif line_number==1:
|
||||
#line_number=1, ccli number, first line after verses
|
||||
if clean_line.startswith(u'CCLI'):
|
||||
line_number += 1
|
||||
ccli_parts = clean_line.split(' ')
|
||||
song_ccli = ccli_parts[len(ccli_parts)-1]
|
||||
elif not verse_start:
|
||||
# We have the verse descriptor
|
||||
verse_desc_parts = clean_line.split(' ')
|
||||
if len(verse_desc_parts) == 2:
|
||||
if verse_desc_parts[0].startswith(u'Ver'):
|
||||
verse_type = u'V'
|
||||
elif verse_desc_parts[0].startswith(u'Ch'):
|
||||
verse_type = u'C'
|
||||
elif verse_desc_parts[0].startswith(u'Br'):
|
||||
verse_type = u'B'
|
||||
else:
|
||||
verse_type = u'O'
|
||||
verse_number = verse_desc_parts[1]
|
||||
else:
|
||||
verse_type = u'O'
|
||||
verse_number = 1
|
||||
verse_start = True
|
||||
else:
|
||||
# We have verse content or the start of the
|
||||
# last part. Add l so as to keep the CRLF
|
||||
verse_text = verse_text + line
|
||||
else:
|
||||
#line_number=2, copyright
|
||||
if line_number==2:
|
||||
line_number += 1
|
||||
song_copyright = clean_line
|
||||
#n=3, authors
|
||||
elif line_number==3:
|
||||
line_number += 1
|
||||
song_author = clean_line
|
||||
#line_number=4, comments lines before last line
|
||||
elif (line_number==4) and (not clean_line.startswith(u'CCL')):
|
||||
song_comments = song_comments + clean_line
|
||||
# split on known separators
|
||||
author_list = song_author.split(u'/')
|
||||
if len(author_list) < 2:
|
||||
author_list = song_author.split(u'|')
|
||||
#Clean spaces before and after author names
|
||||
for author_name in author_list:
|
||||
self.add_author(author_name.strip())
|
||||
self.title = song_name
|
||||
self.copyright = song_copyright
|
||||
self.ccli_number = song_ccli
|
||||
self.comments = song_comments
|
||||
self.finish()
|
||||
|
@ -29,6 +29,7 @@ from olpimport import OpenLPSongImport
|
||||
try:
|
||||
from sofimport import SofImport
|
||||
from oooimport import OooImport
|
||||
from cclifileimport import CCLIFileImport
|
||||
from wowimport import WowImport
|
||||
except ImportError:
|
||||
pass
|
||||
@ -68,6 +69,8 @@ class SongFormat(object):
|
||||
return WowImport
|
||||
elif format == SongFormat.Generic:
|
||||
return OooImport
|
||||
elif format == SongFormat.CCLI:
|
||||
return CCLIFileImport
|
||||
# else:
|
||||
return None
|
||||
|
||||
|
@ -43,12 +43,6 @@ class SongImport(QtCore.QObject):
|
||||
whether the authors etc already exist and add them or refer to them
|
||||
as necessary
|
||||
"""
|
||||
|
||||
COPYRIGHT_STRING = unicode(translate(
|
||||
'SongsPlugin.SongImport', 'copyright'))
|
||||
COPYRIGHT_SYMBOL = unicode(translate(
|
||||
'SongsPlugin.SongImport', '\xa9'))
|
||||
|
||||
def __init__(self, manager):
|
||||
"""
|
||||
Initialise and create defaults for properties
|
||||
@ -58,11 +52,11 @@ class SongImport(QtCore.QObject):
|
||||
"""
|
||||
self.manager = manager
|
||||
self.stop_import_flag = False
|
||||
self.set_defaults()
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'songs_stop_import'), self.stop_import)
|
||||
self.setDefaults()
|
||||
|
||||
def setDefaults(self):
|
||||
def set_defaults(self):
|
||||
self.title = u''
|
||||
self.song_number = u''
|
||||
self.alternate_title = u''
|
||||
@ -78,6 +72,10 @@ class SongImport(QtCore.QObject):
|
||||
self.verses = []
|
||||
self.versecount = 0
|
||||
self.choruscount = 0
|
||||
self.copyright_string = unicode(translate(
|
||||
'SongsPlugin.SongImport', 'copyright'))
|
||||
self.copyright_symbol = unicode(translate(
|
||||
'SongsPlugin.SongImport', '\xa9'))
|
||||
|
||||
def stop_import(self):
|
||||
"""
|
||||
@ -163,8 +161,7 @@ class SongImport(QtCore.QObject):
|
||||
def parse_author(self, text):
|
||||
"""
|
||||
Add the author. OpenLP stores them individually so split by 'and', '&'
|
||||
and comma.
|
||||
However need to check for 'Mr and Mrs Smith' and turn it to
|
||||
and comma. However need to check for 'Mr and Mrs Smith' and turn it to
|
||||
'Mr Smith' and 'Mrs Smith'.
|
||||
"""
|
||||
for author in text.split(u','):
|
||||
@ -241,7 +238,7 @@ class SongImport(QtCore.QObject):
|
||||
"""
|
||||
All fields have been set to this song. Write it away
|
||||
"""
|
||||
if len(self.authors) == 0:
|
||||
if not self.authors:
|
||||
self.authors.append(u'Author unknown')
|
||||
self.commit_song()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user