Added a SongXML class to read the lyrics of songs.

This commit is contained in:
Raoul Snyman 2010-04-03 02:13:07 +02:00
parent 20636bf655
commit f955c8d096
7 changed files with 227 additions and 163 deletions

View File

@ -240,7 +240,7 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
"""
log.debug('Cancel button pressed!')
if self.currentId() == 3:
Receiver.send_message(u'openlpstopimport')
Receiver.send_message(u'openlp_stop_bible_import')
def onCurrentIdChanged(self, id):
if id == 3:

View File

@ -52,7 +52,7 @@ class CSVBible(BibleDB):
raise KeyError(u'You have to supply a file to import verses from.')
self.versesfile = kwargs[u'versesfile']
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'openlpstopimport'), self.stop_import)
QtCore.SIGNAL(u'openlp_stop_bible_import'), self.stop_import)
def stop_import(self):
"""

View File

@ -49,7 +49,7 @@ class OpenSongBible(BibleDB):
raise KeyError(u'You have to supply a file name to import from.')
self.filename = kwargs['filename']
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'openlpstopimport'), self.stop_import)
QtCore.SIGNAL(u'openlp_stop_bible_import'), self.stop_import)
def stop_import(self):
"""

View File

@ -84,7 +84,7 @@ class OSISBible(BibleDB):
if fbibles:
fbibles.close()
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'openlpstopimport'), self.stop_import)
QtCore.SIGNAL(u'openlp_stop_bible_import'), self.stop_import)
def stop_import(self):
"""

View File

@ -33,7 +33,7 @@ from PyQt4 import QtCore, QtGui
from songimportwizard import Ui_SongImportWizard
#from openlp.core.lib import Receiver
#from openlp.core.utils import AppLocation, variant_to_unicode
#from openlp.plugins.bibles.lib.manager import BibleFormat
from openlp.plugins.songs.lib.manager import SongFormat
log = logging.getLogger(__name__)
@ -62,18 +62,13 @@ class ImportWizardForm(QtGui.QWizard, Ui_SongImportWizard):
"""
QtGui.QWizard.__init__(self, parent)
self.setupUi(self)
#self.registerFields()
self.registerFields()
self.finishButton = self.button(QtGui.QWizard.FinishButton)
self.cancelButton = self.button(QtGui.QWizard.CancelButton)
self.manager = manager
self.config = config
self.songsplugin = songsplugin
#self.manager.set_process_dialog(self)
#self.web_bible_list = {}
#self.loadWebBibles()
#QtCore.QObject.connect(self.LocationComboBox,
# QtCore.SIGNAL(u'currentIndexChanged(int)'),
# self.onLocationComboBoxChanged)
# QtCore.QObject.connect(self.OsisFileButton,
# QtCore.SIGNAL(u'clicked()'),
# self.onOsisFileButtonClicked)
@ -89,96 +84,67 @@ class ImportWizardForm(QtGui.QWizard, Ui_SongImportWizard):
QtCore.QObject.connect(self.cancelButton,
QtCore.SIGNAL(u'clicked(bool)'),
self.onCancelButtonClicked)
# QtCore.QObject.connect(self,
# QtCore.SIGNAL(u'currentIdChanged(int)'),
# self.onCurrentIdChanged)
QtCore.QObject.connect(self,
QtCore.SIGNAL(u'currentIdChanged(int)'),
self.onCurrentIdChanged)
def exec_(self):
"""
Run the wizard.
"""
#self.setDefaults()
self.setDefaults()
return QtGui.QWizard.exec_(self)
def validateCurrentPage(self):
"""
Validate the current page before moving on to the next page.
"""
return True
# if self.currentId() == 0:
# # Welcome page
# return True
# elif self.currentId() == 1:
# # Select page
# if self.field(u'source_format').toInt()[0] == BibleFormat.OSIS:
# if self.field(u'osis_location').toString() == u'':
# QtGui.QMessageBox.critical(self,
# self.trUtf8('Invalid Bible Location'),
# self.trUtf8('You need to specify a file to import your '
# 'Bible from.'),
# QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok))
# self.OSISLocationEdit.setFocus()
# return False
# elif self.field(u'source_format').toInt()[0] == BibleFormat.CSV:
# if self.field(u'csv_booksfile').toString() == u'':
# QtGui.QMessageBox.critical(self,
# self.trUtf8('Invalid Books File'),
# self.trUtf8('You need to specify a file with books of '
# 'the Bible to use in the import.'),
# QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok))
# self.BooksLocationEdit.setFocus()
# return False
# elif self.field(u'csv_versefile').toString() == u'':
# QtGui.QMessageBox.critical(self,
# self.trUtf8('Invalid Verse File'),
# self.trUtf8('You need to specify a file of Bible '
# 'verses to import.'),
# QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok))
# self.CsvVerseLocationEdit.setFocus()
# return False
# elif self.field(u'source_format').toInt()[0] == BibleFormat.OpenSong:
# if self.field(u'opensong_file').toString() == u'':
# QtGui.QMessageBox.critical(self,
# self.trUtf8('Invalid OpenSong Bible'),
# self.trUtf8('You need to specify an OpenSong Bible '
# 'file to import.'),
# QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok))
# self.OpenSongFileEdit.setFocus()
# return False
# return True
# elif self.currentId() == 2:
# # License details
# license_version = variant_to_unicode(self.field(u'license_version'))
# license_copyright = variant_to_unicode(self.field(u'license_copyright'))
# if license_version == u'':
# QtGui.QMessageBox.critical(self,
# self.trUtf8('Empty Version Name'),
# self.trUtf8('You need to specify a version name for your '
# 'Bible.'),
# QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok))
# self.VersionNameEdit.setFocus()
# return False
# elif license_copyright == u'':
# QtGui.QMessageBox.critical(self,
# self.trUtf8('Empty Copyright'),
# self.trUtf8('You need to set a copyright for your Bible! '
# 'Bibles in the Public Domain need to be marked as '
# 'such.'),
# QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok))
# self.CopyrightEdit.setFocus()
# return False
# elif self.manager.exists(license_version):
# QtGui.QMessageBox.critical(self,
# self.trUtf8('Bible Exists'),
# self.trUtf8('This Bible already exists! Please import '
# 'a different Bible or first delete the existing one.'),
# QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok))
# self.VersionNameEdit.setFocus()
# return False
# return True
# if self.currentId() == 3:
# # Progress page
# return True
if self.currentId() == 0:
# Welcome page
return True
elif self.currentId() == 1:
# Select page
source_format = self.field(u'source_format').toInt()[0]
if source_format == SongFormat.OpenLyrics:
if self.OpenLyricsFileListWidget.count() == 0:
QtGui.QMessageBox.critical(self,
self.trUtf8('No OpenLyrics Files Selected'),
self.trUtf8('You need to add at least one OpenLyrics '
'song file to import from.'),
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok))
self.OpenLyricsAddButton.setFocus()
return False
elif source_format == SongFormat.OpenSong:
if self.OpenSongFileListWidget.count() == 0:
QtGui.QMessageBox.critical(self,
self.trUtf8('No OpenSong Files Selected'),
self.trUtf8('You need to add at least one OpenSong '
'song file to import from.'),
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok))
self.OpenSongAddButton.setFocus()
return False
elif source_format == SongFormat.CCLI:
if self.CCLIFileListWidget.count() == 0:
QtGui.QMessageBox.critical(self,
self.trUtf8('No CCLI Files Selected'),
self.trUtf8('You need to add at least one CCLI file '
'to import from.'),
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok))
self.CCLIAddButton.setFocus()
return False
elif source_format == SongFormat.CSV:
if self.CSVFilenameEdit.text().isEmpty():
QtGui.QMessageBox.critical(self,
self.trUtf8('No CSV File Selected'),
self.trUtf8('You need to specify a CSV file to import '
'from.'),
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok))
self.CSVFilenameEdit.setFocus()
return False
return True
elif self.currentId() == 2:
# Progress page
return True
def onCancelButtonClicked(self, checked):
"""
@ -186,62 +152,23 @@ class ImportWizardForm(QtGui.QWizard, Ui_SongImportWizard):
"""
log.debug('Cancel button pressed!')
if self.currentId() == 3:
Receiver.send_message(u'openlpstopimport')
Receiver.send_message(u'openlp_stop_song_import')
# def onCurrentIdChanged(self, id):
# if id == 3:
# self.preImport()
# self.performImport()
# self.postImport()
def onCurrentIdChanged(self, id):
if id == 3:
self.preImport()
self.performImport()
self.postImport()
def registerFields(self):
pass
# self.SourcePage.registerField(
# u'source_format', self.FormatComboBox)
# self.SourcePage.registerField(
# u'openlyrics_filename', self.OpenLyricsFilenameEdit)
# self.SourcePage.registerField(
# u'openlyrics_directory', self.OpenLyricsDirectoryEdit)
# self.SourcePage.registerField(
# u'opensong_filename', self.OpenSongFilenameEdit)
# self.SourcePage.registerField(
# u'opensong_directory', self.OpenSongDirectoryEdit)
# self.SourcePage.registerField(
# u'csv_versefile', self.CsvVerseLocationEdit)
# self.SourcePage.registerField(
# u'opensong_file', self.OpenSongFileEdit)
# self.SourcePage.registerField(
# u'web_location', self.LocationComboBox)
# self.SourcePage.registerField(
# u'web_biblename', self.BibleComboBox)
# self.SourcePage.registerField(
# u'proxy_server', self.AddressEdit)
# self.SourcePage.registerField(
# u'proxy_username', self.UsernameEdit)
# self.SourcePage.registerField(
# u'proxy_password', self.PasswordEdit)
self.SourcePage.registerField(u'source_format', self.FormatComboBox)
def setDefaults(self):
pass
# self.setField(u'source_format', QtCore.QVariant(0))
# self.setField(u'openlyrics_filename', QtCore.QVariant(''))
# self.setField(u'openlyrics_directory', QtCore.QVariant(''))
# self.setField(u'opensong_filename', QtCore.QVariant(''))
# self.setField(u'opensong_directory', QtCore.QVariant(''))
# self.setField(u'csv_versefile', QtCore.QVariant(''))
# self.setField(u'opensong_file', QtCore.QVariant(''))
# self.setField(u'web_location', QtCore.QVariant(WebDownload.Crosswalk))
# self.setField(u'web_biblename', QtCore.QVariant(self.BibleComboBox))
# self.setField(u'proxy_server',
# QtCore.QVariant(self.config.get_config(u'proxy address', '')))
# self.setField(u'proxy_username',
# QtCore.QVariant(self.config.get_config(u'proxy username','')))
# self.setField(u'proxy_password',
# QtCore.QVariant(self.config.get_config(u'proxy password','')))
# self.setField(u'license_version', QtCore.QVariant(self.VersionNameEdit))
# self.setField(u'license_copyright', QtCore.QVariant(self.CopyrightEdit))
# self.setField(u'license_permission', QtCore.QVariant(self.PermissionEdit))
# self.onLocationComboBoxChanged(WebDownload.Crosswalk)
self.setField(u'source_format', QtCore.QVariant(0))
self.OpenLyricsFileListWidget.clear()
self.OpenSongFileListWidget.clear()
self.CCLIFileListWidget.clear()
self.CSVFilenameEdit.setText(u'')
def getFileName(self, title, editbox):
filename = QtGui.QFileDialog.getOpenFileName(self, title,
@ -266,10 +193,7 @@ class ImportWizardForm(QtGui.QWizard, Ui_SongImportWizard):
def performImport(self):
pass
# bible_type = self.field(u'source_format').toInt()[0]
# license_version = variant_to_unicode(self.field(u'license_version'))
# license_copyright = variant_to_unicode(self.field(u'license_copyright'))
# license_permission = variant_to_unicode(self.field(u'license_permission'))
# source_format = self.field(u'source_format').toInt()[0]
# importer = None
# if bible_type == BibleFormat.OSIS:
# # Import an OSIS bible

View File

@ -27,6 +27,8 @@ import logging
from openlp.plugins.songs.lib.models import init_models, metadata, Song, \
Author, Topic, Book
#from openlp.plugins.songs.lib import OpenLyricsSong, OpenSongSong, CCLISong, \
# CSVSong
log = logging.getLogger(__name__)
@ -38,8 +40,8 @@ class SongFormat(object):
"""
Unknown = -1
OpenLyrics = 0
OpenSongFile = 1
OpenSongDirectory = 2
OpenSong = 1
CCLI = 2
CSV = 3
@staticmethod
@ -48,29 +50,29 @@ class SongFormat(object):
Return the appropriate imeplementation class.
``id``
The Bible format.
The song format.
"""
if id == BibleFormat.OSIS:
return OSISBible
elif id == BibleFormat.CSV:
return CSVBible
elif id == BibleFormat.OpenSong:
return OpenSongBible
elif id == BibleFormat.WebDownload:
return HTTPBible
else:
return None
# if id == SongFormat.OpenLyrics:
# return OpenLyricsSong
# elif id == SongFormat.OpenSong:
# return OpenSongSong
# elif id == SongFormat.CCLI:
# return CCLISong
# elif id == SongFormat.CSV:
# return CSVSong
# else:
return None
@staticmethod
def list():
"""
Return a list of the supported Bible formats.
Return a list of the supported song formats.
"""
return [
BibleFormat.OSIS,
BibleFormat.CSV,
BibleFormat.OpenSong,
BibleFormat.WebDownload
SongFormat.OpenLyrics,
SongFormat.OpenSong,
SongFormat.CCLI,
SongFormat.CSV
]

View File

@ -0,0 +1,138 @@
# -*- 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, Christian Richter, Maikel Stuivenberg, Martin #
# Thompson, Jon Tibble, Carsten Tinggaard #
# --------------------------------------------------------------------------- #
# 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 #
###############################################################################
from lxml import objectify
class SongXML(object):
"""
This class represents the XML in the ``lyrics`` field of a song.
The basic XML looks like this::
<?xml version="1.0" encoding="UTF-8"?>
<song version="1.0">
<lyrics language="en">
<verse type="chorus" label="1">
<![CDATA[ ... ]]>
</verse>
</lyrics>
</song>
"""
def __init__(self, song=None):
if song:
if song.lyrics.startswith(u'<?xml'):
self.parse(song.lyrics)
else:
self.extract(song.lyrics)
else:
self.lyrics = []
def parse(self, xml):
"""
Parse XML from the ``lyrics`` field in the database, and set the list
of verses from it.
``xml``
The XML to parse.
"""
try:
self.lyrics = []
song = objectify.fromstring(xml)
for lyrics in song.lyrics:
lyrlang = {
u'language': lyrics.attrib[u'language'],
u'verses': []
}
for verse in lyrics.verse:
lyrlang[u'verses'].append({
u'type': verse.attrib[u'type'],
u'label': verse.attrib[u'label'],
u'text': unicode(verse.text)
})
self.lyrics.append(lyrlang)
return True
except:
return False
def extract(self, text):
"""
If the ``lyrics`` field in the database is not XML, this method is
called and used to construct the verse structure similar to the output
of the ``parse`` function.
``text``
The text to pull verses out of.
"""
text = text.replace('\r\n', '\n')
verses = text.split('\n\n')
self.lyrics = [{u'language': u'en', u'verses': []}]
counter = 0
for verse in verses:
counter = counter + 1
self.lyrics[0][u'verses'].append({
u'type': u'verse',
u'label': unicode(counter),
u'text': verse
})
return True
def add_verse(self, type, label, text):
"""
Add a verse to the list of verses.
``type``
The type of list, one of "verse", "chorus", "bridge", "pre-chorus",
"intro", "outtro".
``label``
The number associated with this verse, like 1 or 2.
``text``
The text of the verse.
"""
self.verses.append({
u'type': type,
u'label': label,
u'text': text
})
def export(self):
"""
Build up the XML for the verse structure.
"""
lyrics_output = u''
for lyrics in self.lyrics:
verse_output = u''
for verse in lyrics[u'verses']:
verse_output = verse_output + \
u'<verse type="%s" label="%s"><![CDATA[%s]]></verse>' % \
(verse[u'type'], verse[u'label'], verse[u'text'])
lyrics_output = lyrics_output + \
u'<lyrics language="%s">%s</lyrics>' % \
(lyrics[u'language'], verse_output)
song_output = u'<?xml version="1.0" encoding="UTF-8"?>' + \
u'<song version="1.0">%s</song>' % lyrics_output
return song_output