openlp-core team mailing list archive
-
openlp-core team
-
Mailing list archive
-
Message #06199
[Merge] lp:~phill-ridout/openlp/ssp_import into lp:openlp
phill has proposed merging lp:~phill-ridout/openlp/ssp_import into lp:openlp.
Requested reviews:
OpenLP Core (openlp-core)
For more details, see:
https://code.launchpad.net/~phill-ridout/openlp/ssp_import/+merge/49548
Importer for SongShow Plus
--
https://code.launchpad.net/~phill-ridout/openlp/ssp_import/+merge/49548
Your team OpenLP Core is requested to review the proposed merge of lp:~phill-ridout/openlp/ssp_import into lp:openlp.
=== modified file 'openlp/plugins/songs/forms/songimportform.py'
--- openlp/plugins/songs/forms/songimportform.py 2011-02-10 19:37:02 +0000
+++ openlp/plugins/songs/forms/songimportform.py 2011-02-13 15:19:54 +0000
@@ -140,6 +140,12 @@
QtCore.QObject.connect(self.songBeamerRemoveButton,
QtCore.SIGNAL(u'clicked()'),
self.onSongBeamerRemoveButtonClicked)
+ QtCore.QObject.connect(self.songShowPlusAddButton,
+ QtCore.SIGNAL(u'clicked()'),
+ self.onSongShowPlusAddButtonClicked)
+ QtCore.QObject.connect(self.songShowPlusRemoveButton,
+ QtCore.SIGNAL(u'clicked()'),
+ self.onSongShowPlusRemoveButtonClicked)
def addCustomPages(self):
"""
@@ -188,6 +194,8 @@
self.addFileSelectItem(u'ew', single_select=True)
# Words of Worship
self.addFileSelectItem(u'songBeamer')
+ # Song Show Plus
+ self.addFileSelectItem(u'songShowPlus')
# Commented out for future use.
# self.addFileSelectItem(u'csv', u'CSV', single_select=True)
self.sourceLayout.addLayout(self.formatStack)
@@ -237,6 +245,8 @@
translate('SongsPlugin.ImportWizardForm', 'EasyWorship'))
self.formatComboBox.setItemText(10,
translate('SongsPlugin.ImportWizardForm', 'SongBeamer'))
+ self.formatComboBox.setItemText(11,
+ translate('SongsPlugin.ImportWizardForm', 'SongShow Plus'))
# self.formatComboBox.setItemText(11,
# translate('SongsPlugin.ImportWizardForm', 'CSV'))
self.openLP2FilenameLabel.setText(
@@ -301,6 +311,10 @@
translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
self.songBeamerRemoveButton.setText(
translate('SongsPlugin.ImportWizardForm', 'Remove File(s)'))
+ self.songShowPlusAddButton.setText(
+ translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
+ self.songShowPlusRemoveButton.setText(
+ translate('SongsPlugin.ImportWizardForm', 'Remove File(s)'))
# self.csvFilenameLabel.setText(
# translate('SongsPlugin.ImportWizardForm', 'Filename:'))
# self.csvBrowseButton.setText(
@@ -438,6 +452,16 @@
'file to import from.'))
self.songBeamerAddButton.setFocus()
return False
+ elif source_format == SongFormat.SongShowPlus:
+ if self.songShowPlusFileListWidget.count() == 0:
+ critical_error_message_box(
+ translate('SongsPlugin.ImportWizardForm',
+ 'No SongShow Plus Files Selected'),
+ translate('SongsPlugin.ImportWizardForm',
+ 'You need to add at least one SongShow Plus '
+ 'file to import from.'))
+ self.wordsOfWorshipAddButton.setFocus()
+ return False
return True
elif self.currentPage() == self.progressPage:
return True
@@ -643,6 +667,24 @@
Remove selected SongBeamer files from the import list
"""
self.removeSelectedItems(self.songBeamerFileListWidget)
+
+ def onSongShowPlusAddButtonClicked(self):
+ """
+ Get SongShow Plus song database files
+ """
+ self.getFiles(
+ translate('SongsPlugin.ImportWizardForm',
+ 'Select SongShow Plus Files'),
+ self.songShowPlusFileListWidget, u'%s (*.sbsong)'
+ % translate('SongsPlugin.ImportWizardForm',
+ 'SongShow Plus Song Files')
+ )
+
+ def onSongShowPlusRemoveButtonClicked(self):
+ """
+ Remove selected SongShow Plus files from the import list
+ """
+ self.removeSelectedItems(self.songShowPlusFileListWidget)
def setDefaults(self):
"""
@@ -663,6 +705,7 @@
self.easiSlidesFilenameEdit.setText(u'')
self.ewFilenameEdit.setText(u'')
self.songBeamerFileListWidget.clear()
+ self.songShowPlusFileListWidget.clear()
#self.csvFilenameEdit.setText(u'')
def preWizard(self):
@@ -739,6 +782,12 @@
importer = self.plugin.importSongs(SongFormat.SongBeamer,
filenames=self.getListOfFiles(self.songBeamerFileListWidget)
)
+ elif source_format == SongFormat.SongShowPlus:
+ # Import ShongShow Plus songs
+ importer = self.plugin.importSongs(SongFormat.SongShowPlus,
+ filenames=self.getListOfFiles(
+ self.songShowPlusFileListWidget)
+ )
if importer.do_import():
self.progressLabel.setText(
translate('SongsPlugin.SongImportForm', 'Finished import.'))
=== modified file 'openlp/plugins/songs/lib/importer.py'
--- openlp/plugins/songs/lib/importer.py 2011-01-26 02:43:16 +0000
+++ openlp/plugins/songs/lib/importer.py 2011-02-13 15:19:54 +0000
@@ -34,6 +34,7 @@
from cclifileimport import CCLIFileImport
from ewimport import EasyWorshipSongImport
from songbeamerimport import SongBeamerImport
+from songshowplusimport import SongShowPlusImport
# Imports that might fail
try:
from olp1import import OpenLP1SongImport
@@ -71,6 +72,7 @@
EasiSlides = 8
EasyWorship = 9
SongBeamer = 10
+ SongShowPlus = 11
@staticmethod
def get_class(format):
@@ -102,6 +104,8 @@
return EasyWorshipSongImport
elif format == SongFormat.SongBeamer:
return SongBeamerImport
+ elif format == SongFormat.SongShowPlus:
+ return SongShowPlusImport
return None
@staticmethod
@@ -120,7 +124,8 @@
SongFormat.Generic,
SongFormat.EasiSlides,
SongFormat.EasyWorship,
- SongFormat.SongBeamer
+ SongFormat.SongBeamer,
+ SongFormat.SongShowPlus
]
@staticmethod
=== added file 'openlp/plugins/songs/lib/songshowplusimport.py'
--- openlp/plugins/songs/lib/songshowplusimport.py 1970-01-01 00:00:00 +0000
+++ openlp/plugins/songs/lib/songshowplusimport.py 2011-02-13 15:19:54 +0000
@@ -0,0 +1,212 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2011 Raoul Snyman #
+# Portions copyright (c) 2008-2011 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 #
+# --------------------------------------------------------------------------- #
+# 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:`wowimport` module provides the functionality for importing Words of
+Worship songs into the OpenLP database.
+"""
+import os
+import logging
+import struct
+
+from openlp.plugins.songs.lib.songimport import SongImport
+
+TITLE = 1
+AUTHOR = 2
+COPYRIGHT = 3
+CCLI_NO = 5
+VERSE = 12
+CHORUS = 20
+TOPIC = 29
+COMMENTS = 30
+VERSE_ORDER = 31
+SONG_BOOK = 35
+SONG_NUMBER = 36
+CUSTOM_VERSE = 37
+
+log = logging.getLogger(__name__)
+
+class SongShowPlusImport(SongImport):
+ """
+ The :class:`SongShowPlusImport` class provides the ability to import song
+ files from SongShow Plus.
+
+ **SongShow Plus Song File Format:**
+
+ The SongShow Plus song file format is as follows:
+
+ * Each piece of data in the song file has some information that precedes
+ it.
+ * The general format of this data is as follows:
+ 4 Bytes, forming a 32 bit number, a key if you will, this describes what
+ the data is (see blockKey below)
+ 4 Bytes, forming a 32 bit number, which is the number of bytes until the
+ next block starts
+ 1 Byte, which tells how namy bytes follows
+ 1 or 4 Bytes, describes how long the string is, if its 1 byte, the string
+ is less than 255
+ The next bytes are the actuall data.
+ The next block of data follows on.
+
+ This description does differ for verses. Which includes extra bytes
+ stating the verse type or number. In some cases a "custom" verse is used,
+ in that case, this block will in include 2 strings, with the associated
+ string length descriptors. The first string is the name of the verse, the
+ second is the verse content.
+
+ The file is ended with four null bytes.
+
+ Valid extensions for a SongShow Plus song file are:
+
+ * .sbsong
+ """
+ otherList = {}
+ otherCount = 0
+
+ def __init__(self, master_manager, **kwargs):
+ """
+ Initialise the import.
+
+ ``master_manager``
+ The song manager for the running OpenLP installation.
+ """
+ SongImport.__init__(self, master_manager)
+ if kwargs.has_key(u'filename'):
+ self.import_source = kwargs[u'filename']
+ if kwargs.has_key(u'filenames'):
+ self.import_source = kwargs[u'filenames']
+ log.debug(self.import_source)
+
+ def do_import(self):
+ """
+ Receive a single file or a list of files to import.
+ """
+ if isinstance(self.import_source, list):
+ self.import_wizard.progressBar.setMaximum(len(self.import_source))
+ for file in self.import_source:
+ author = u''
+ copyright = u''
+ self.sspVerseOrderList = []
+ otherCount = 0
+ otherList = {}
+ file_name = os.path.split(file)[1]
+ self.import_wizard.incrementProgressBar(
+ u'Importing %s' % (file_name), 0)
+ songData = open(file, 'rb')
+ while (1):
+ blockKey, = struct.unpack("I",songData.read(4))
+ # The file ends with 4 NUL's
+ if blockKey == 0:
+ break
+ nextBlockStarts, = struct.unpack("I",songData.read(4))
+ if blockKey == VERSE or blockKey == CHORUS:
+ null, verseNo, = struct.unpack("BB",songData.read(2))
+ elif blockKey == CUSTOM_VERSE:
+ null, verseNameLength, = struct.unpack("BB",
+ songData.read(2))
+ verseName = songData.read(verseNameLength)
+ lengthDescriptorSize, = struct.unpack("B",songData.read(1))
+ # Detect if/how long the length descriptor is
+ if lengthDescriptorSize == 12:
+ lengthDescriptor, = struct.unpack("I",songData.read(4))
+ elif lengthDescriptorSize == 2:
+ lengthDescriptor = 1
+ elif lengthDescriptorSize == 9:
+ lengthDescriptor = 0
+ else:
+ lengthDescriptor, = struct.unpack("B",songData.read(1))
+ data = songData.read(lengthDescriptor)
+
+ if blockKey == TITLE:
+ self.title = unicode(data, u'cp1252')
+ elif blockKey == AUTHOR:
+ authors = data.split(" / ")
+ for author in authors:
+ if author.find(",") !=-1:
+ authorParts = author.split(", ")
+ author = authorParts[1] + " " + authorParts[0]
+ self.parse_author(unicode(author, u'cp1252'))
+ elif blockKey == COPYRIGHT:
+ self.add_copyright(unicode(data, u'cp1252'))
+ elif blockKey == CCLI_NO:
+ self.ccli_number = int(data)
+ elif blockKey == VERSE:
+ self.add_verse(unicode(data, u'cp1252'),
+ "V%s" % verseNo)
+ elif blockKey == CHORUS:
+ self.add_verse(unicode(data, u'cp1252'),
+ "C%s" % verseNo)
+ elif blockKey == TOPIC:
+ self.topics.append(unicode(data, u'cp1252'))
+ elif blockKey == COMMENTS:
+ self.comments = unicode(data, u'cp1252')
+ elif blockKey == VERSE_ORDER:
+ verseTag = self.toOpenLPVerseTag(data)
+ self.sspVerseOrderList.append(unicode(verseTag,
+ u'cp1252'))
+ elif blockKey == SONG_BOOK:
+ self.song_book_name = unicode(data, u'cp1252')
+ elif blockKey == SONG_NUMBER:
+ self.song_number = ord(data)
+ elif blockKey == CUSTOM_VERSE:
+ verseTag = self.toOpenLPVerseTag(verseName)
+ self.add_verse(unicode(data, u'cp1252'), verseTag)
+ else:
+ log.debug("Unrecognised blockKey: %s, data: %s"
+ %(blockKey, data))
+ self.verse_order_list = self.sspVerseOrderList
+ songData.close()
+ self.finish()
+ self.import_wizard.incrementProgressBar(
+ u'Importing %s' % (file_name))
+ return True
+
+ def toOpenLPVerseTag(self, verseName):
+ if verseName.find(" ")!=-1:
+ verseParts = verseName.split(" ")
+ verseType = verseParts[0]
+ verseNumber = verseParts[1]
+ else:
+ verseType = verseName
+ verseNumber = "1"
+ verseType = verseType.lower()
+ if verseType == "verse":
+ verseTag = "V"
+ elif verseType == "chorus":
+ verseTag = "C"
+ elif verseType == "bridge":
+ verseTag = "B"
+ elif verseType == "pre-chorus":
+ verseTag = "P"
+ elif verseType == "bridge":
+ verseTag = "B"
+ else:
+ if not self.otherList.has_key(verseName):
+ self.otherCount = self.otherCount + 1
+ self.otherList[verseName] = str(self.otherCount)
+ verseTag = "O"
+ verseNumber = self.otherList[verseName]
+ verseTag = verseTag + verseNumber
+ return verseTag
Follow ups