merged classes together

This commit is contained in:
Andreas Preikschat 2011-01-09 17:52:31 +01:00
parent f2784fc4dd
commit ce1241aa0f
7 changed files with 109 additions and 244 deletions

View File

@ -31,7 +31,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import Receiver, translate
from openlp.plugins.songs.forms import EditVerseForm
from openlp.plugins.songs.lib import SongXMLBuilder, SongXMLParser, VerseType
from openlp.plugins.songs.lib import SongXML, VerseType
from openlp.plugins.songs.lib.db import Book, Song, Author, Topic
from editsongdialog import Ui_EditSongDialog
@ -263,8 +263,8 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
if isinstance(self.song.lyrics, buffer):
self.song.lyrics = unicode(self.song.lyrics)
if self.song.lyrics.startswith(u'<?xml version='):
songXML = SongXMLParser(self.song.lyrics)
verseList = songXML.get_verses()
songXML = SongXML()
verseList = songXML.get_verses(self.song.lyrics)
for count, verse in enumerate(verseList):
self.verseListWidget.setRowCount(
self.verseListWidget.rowCount() + 1)
@ -731,7 +731,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
def processLyrics(self):
log.debug(u'processLyrics')
try:
sxml = SongXMLBuilder()
sxml = SongXML()
text = u''
multiple = []
for i in range(0, self.verseListWidget.rowCount()):

View File

@ -175,7 +175,6 @@ def retrieve_windows_encoding(recommendation=None):
return None
return filter(lambda item: item[1] == choice[0], encodings)[0][0]
from xml import OpenLyricsBuilder, OpenLyricsParser, SongXMLBuilder, \
SongXMLParser
from xml import OpenLyrics, SongXML
from songstab import SongsTab
from mediaitem import SongMediaItem

View File

@ -35,8 +35,7 @@ from openlp.core.lib import MediaManagerItem, BaseListWithDnD, Receiver, \
ItemCapabilities, translate, check_item_selected
from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \
SongImportForm
from openlp.plugins.songs.lib import OpenLyricsBuilder, OpenLyricsParser, \
SongXMLParser
from openlp.plugins.songs.lib import OpenLyrics, SongXML
from openlp.plugins.songs.lib.db import Author, Song
from openlp.core.lib.searchedit import SearchEdit
@ -59,8 +58,7 @@ class SongMediaItem(MediaManagerItem):
self.ListViewWithDnD_class = SongListView
MediaManagerItem.__init__(self, parent, self, icon)
self.edit_song_form = EditSongForm(self, self.parent.manager)
self.openLyricsParser = OpenLyricsParser(self.parent.manager)
self.openLyricsBuilder = OpenLyricsBuilder(self.parent.manager)
self.openLyrics = OpenLyrics(self.parent.manager)
self.singleServiceItem = False
self.song_maintenance_form = SongMaintenanceForm(
self.parent.manager, self)
@ -353,8 +351,8 @@ class SongMediaItem(MediaManagerItem):
service_item.theme = song.theme_name
service_item.edit_id = item_id
if song.lyrics.startswith(u'<?xml version='):
songXML = SongXMLParser(song.lyrics)
verseList = songXML.get_verses()
songXML = SongXML()
verseList = songXML.get_verses(song.lyrics)
# no verse list or only 1 space (in error)
if not song.verse_order or not song.verse_order.strip():
for verse in verseList:
@ -397,7 +395,7 @@ class SongMediaItem(MediaManagerItem):
]
service_item.data_string = {u'title': song.search_title,
u'authors': author_list}
service_item.xml_version = self.openLyricsBuilder.song_to_xml(song)
service_item.xml_version = self.openLyrics.song_to_xml(song)
return True
def serviceLoad(self, item):
@ -439,7 +437,7 @@ class SongMediaItem(MediaManagerItem):
break
if add_song:
if self.addSongFromService:
editId = self.openLyricsParser.xml_to_song(item.xml_version)
editId = self.openLyrics.xml_to_song(item.xml_version)
# Update service with correct song id.
if editId != 0:
Receiver.send_message(u'service_item_update',

View File

@ -35,7 +35,7 @@ from lxml import etree
from openlp.core.lib import translate
from openlp.plugins.songs.lib.songimport import SongImport
from openlp.plugins.songs.lib import OpenLyricsParser
from openlp.plugins.songs.lib import OpenLyrics
log = logging.getLogger(__name__)
@ -50,7 +50,7 @@ class OpenLyricsImport(SongImport):
log.debug(u'initialise OpenLyricsImport')
SongImport.__init__(self, master_manager)
self.master_manager = master_manager
self.openLyricsParser = OpenLyricsParser(master_manager)
self.openLyrics = OpenLyrics(master_manager)
if kwargs.has_key(u'filename'):
self.import_source = kwargs[u'filename']
if kwargs.has_key(u'filenames'):
@ -70,7 +70,7 @@ class OpenLyricsImport(SongImport):
parser = etree.XMLParser(remove_blank_text=True)
file = etree.parse(file_path, parser)
xml = unicode(etree.tostring(file))
if self.openLyricsParser.xml_to_song(xml) == 0:
if self.openLyrics.xml_to_song(xml) == 0:
log.debug(u'File could not be imported: %s' % file_path)
# Importing this song failed! For now we stop import.
return False

View File

@ -31,7 +31,7 @@ from PyQt4 import QtCore
from openlp.core.lib import Receiver, translate
from openlp.plugins.songs.lib import VerseType
from openlp.plugins.songs.lib.db import Song, Author, Topic, Book, MediaFile
from openlp.plugins.songs.lib.xml import SongXMLBuilder
from openlp.plugins.songs.lib.xml import SongXML
log = logging.getLogger(__name__)
@ -270,7 +270,7 @@ class SongImport(QtCore.QObject):
song.song_number = self.song_number
song.search_lyrics = u''
verses_changed_to_other = {}
sxml = SongXMLBuilder()
sxml = SongXML()
other_count = 1
for (versetag, versetext) in self.verses:
if versetag[0] == u'C':

View File

@ -30,7 +30,7 @@ The basic XML for storing the lyrics in the song database is of the format::
<?xml version="1.0" encoding="UTF-8"?>
<song version="1.0">
<lyrics language="en">
<lyrics>
<verse type="chorus" label="1">
<![CDATA[ ... ]]>
</verse>
@ -71,32 +71,26 @@ from openlp.plugins.songs.lib.db import Author, Book, Song, Topic
log = logging.getLogger(__name__)
class SongXMLBuilder(object):
class SongXML(object):
"""
This class builds the XML used to describe songs.
This class builds and parses the XML used to describe songs.
"""
log.info(u'SongXMLBuilder Loaded')
log.info(u'SongXML Loaded')
def __init__(self, song_language=None):
def __init__(self):
"""
Set up the song builder.
``song_language``
The language used in this song
Set up the default variables.
"""
lang = u'en'
if song_language:
lang = song_language
self.song_xml = objectify.fromstring(u'<song version="1.0" />')
self.lyrics = etree.SubElement(self.song_xml, u'lyrics', language=lang)
self.lyrics = etree.SubElement(self.song_xml, u'lyrics')
def add_verse_to_lyrics(self, type, number, content):
"""
Add a verse to the ``<lyrics>`` tag.
Add a verse to the *<lyrics>* tag.
``type``
A string denoting the type of verse. Possible values are "Chorus",
"Verse", "Bridge", and "Custom".
A string denoting the type of verse. Possible values are "V",
"C", "B", "P", "I", "E" and "O".
``number``
An integer denoting the number of the item, for example: verse 1.
@ -109,13 +103,6 @@ class SongXMLBuilder(object):
verse.text = etree.CDATA(content)
self.lyrics.append(verse)
def dump_xml(self):
"""
Debugging aid to dump XML so that we can see what we have.
"""
return etree.tostring(self.song_xml, encoding=u'UTF-8',
xml_declaration=True, pretty_print=True)
def extract_xml(self):
"""
Extract our newly created XML song.
@ -123,16 +110,10 @@ class SongXMLBuilder(object):
return etree.tostring(self.song_xml, encoding=u'UTF-8',
xml_declaration=True)
class SongXMLParser(object):
def get_verses(self, xml):
"""
A class to read in and parse a song's XML.
"""
log.info(u'SongXMLParser Loaded')
def __init__(self, xml):
"""
Set up our song XML parser.
Iterates through the verses in the XML and returns a list of verses
and their attributes.
``xml``
The XML of the song to be parsed.
@ -144,12 +125,6 @@ class SongXMLParser(object):
self.song_xml = objectify.fromstring(xml)
except etree.XMLSyntaxError:
log.exception(u'Invalid xml %s', xml)
def get_verses(self):
"""
Iterates through the verses in the XML and returns a list of verses
and their attributes.
"""
xml_iter = self.song_xml.getiterator()
verse_list = []
for element in xml_iter:
@ -166,191 +141,9 @@ class SongXMLParser(object):
return etree.dump(self.song_xml)
#class LyricsXML(object):
# """
# This class represents the XML in the ``lyrics`` field of a 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.languages = []
#
# 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.languages = []
# song = objectify.fromstring(xml)
# for lyrics in song.lyrics:
# language = {
# u'language': lyrics.attrib[u'language'],
# u'verses': []
# }
# for verse in lyrics.verse:
# language[u'verses'].append({
# u'type': verse.attrib[u'type'],
# u'label': verse.attrib[u'label'],
# u'text': unicode(verse.text)
# })
# self.lyrics.append(language)
# return True
# except etree.XMLSyntaxError:
# 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.languages = [{u'language': u'en', u'verses': []}]
# for counter, verse in enumerate(verses):
# self.languages[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 language in self.languages:
# verse_output = u''
# for verse in language[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>' % \
# (language[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
class OpenLyricsBuilder(object):
class OpenLyrics(object):
"""
This class represents the converter for song to OpenLyrics XML.
"""
def __init__(self, manager):
self.manager = manager
def song_to_xml(self, song, pretty_print=False):
"""
Convert the song to OpenLyrics Format.
"""
song_xml_parser = SongXMLParser(song.lyrics)
verse_list = song_xml_parser.get_verses()
song_xml = objectify.fromstring(
u'<song version="0.7" createdIn="OpenLP 2.0"/>')
properties = etree.SubElement(song_xml, u'properties')
titles = etree.SubElement(properties, u'titles')
self._add_text_to_element(u'title', titles, song.title)
if song.alternate_title:
self._add_text_to_element(u'title', titles, song.alternate_title)
if song.comments:
comments = etree.SubElement(properties, u'comments')
self._add_text_to_element(u'comment', comments, song.comments)
if song.copyright:
self._add_text_to_element(u'copyright', properties, song.copyright)
if song.verse_order:
self._add_text_to_element(
u'verseOrder', properties, song.verse_order)
if song.ccli_number:
self._add_text_to_element(u'ccliNo', properties, song.ccli_number)
if song.authors:
authors = etree.SubElement(properties, u'authors')
for author in song.authors:
self._add_text_to_element(
u'author', authors, author.display_name)
book = self.manager.get_object_filtered(
Book, Book.id == song.song_book_id)
if book is not None:
book = book.name
songbooks = etree.SubElement(properties, u'songbooks')
element = self._add_text_to_element(
u'songbook', songbooks, None, book)
element.set(u'entry', song.song_number)
if song.topics:
themes = etree.SubElement(properties, u'themes')
for topic in song.topics:
self._add_text_to_element(u'theme', themes, topic.name)
lyrics = etree.SubElement(song_xml, u'lyrics')
for verse in verse_list:
verse_tag = u'%s%s' % (
verse[0][u'type'][0].lower(), verse[0][u'label'])
element = \
self._add_text_to_element(u'verse', lyrics, None, verse_tag)
element = self._add_text_to_element(u'lines', element)
for line in unicode(verse[1]).split(u'\n'):
self._add_text_to_element(u'line', element, line)
return self._extract_xml(song_xml, pretty_print)
def _add_text_to_element(self, tag, parent, text=None, label=None):
if label:
element = etree.Element(tag, name=unicode(label))
else:
element = etree.Element(tag)
if text:
element.text = unicode(text)
parent.append(element)
return element
def _extract_xml(self, xml, pretty_print):
"""
Extract our newly created XML song.
"""
return etree.tostring(xml, encoding=u'UTF-8',
xml_declaration=True, pretty_print=pretty_print)
def _dump_xml(self, xml):
"""
Debugging aid to dump XML so that we can see what we have.
"""
return etree.tostring(xml, encoding=u'UTF-8',
xml_declaration=True, pretty_print=True)
class OpenLyricsParser(object):
"""
This class represents the converter for OpenLyrics XML to a song.
This class represents the converter for OpenLyrics XML to/from a song.
As OpenLyrics has a rich set of different features, we cannot support them
all. The following features are supported by the :class:`OpenLyricsParser`::
@ -410,6 +203,57 @@ class OpenLyricsParser(object):
def __init__(self, manager):
self.manager = manager
def song_to_xml(self, song, pretty_print=False):
"""
Convert the song to OpenLyrics Format.
"""
sxml = SongXML()
verse_list = sxml.get_verses(song.lyrics)
song_xml = objectify.fromstring(
u'<song version="0.7" createdIn="OpenLP 2.0"/>')
properties = etree.SubElement(song_xml, u'properties')
titles = etree.SubElement(properties, u'titles')
self._add_text_to_element(u'title', titles, song.title)
if song.alternate_title:
self._add_text_to_element(u'title', titles, song.alternate_title)
if song.comments:
comments = etree.SubElement(properties, u'comments')
self._add_text_to_element(u'comment', comments, song.comments)
if song.copyright:
self._add_text_to_element(u'copyright', properties, song.copyright)
if song.verse_order:
self._add_text_to_element(
u'verseOrder', properties, song.verse_order)
if song.ccli_number:
self._add_text_to_element(u'ccliNo', properties, song.ccli_number)
if song.authors:
authors = etree.SubElement(properties, u'authors')
for author in song.authors:
self._add_text_to_element(
u'author', authors, author.display_name)
book = self.manager.get_object_filtered(
Book, Book.id == song.song_book_id)
if book is not None:
book = book.name
songbooks = etree.SubElement(properties, u'songbooks')
element = self._add_text_to_element(
u'songbook', songbooks, None, book)
element.set(u'entry', song.song_number)
if song.topics:
themes = etree.SubElement(properties, u'themes')
for topic in song.topics:
self._add_text_to_element(u'theme', themes, topic.name)
lyrics = etree.SubElement(song_xml, u'lyrics')
for verse in verse_list:
verse_tag = u'%s%s' % (
verse[0][u'type'][0].lower(), verse[0][u'label'])
element = \
self._add_text_to_element(u'verse', lyrics, None, verse_tag)
element = self._add_text_to_element(u'lines', element)
for line in unicode(verse[1]).split(u'\n'):
self._add_text_to_element(u'line', element, line)
return self._extract_xml(song_xml, pretty_print)
def xml_to_song(self, xml):
"""
Create and save a song from OpenLyrics format xml to the database. Since
@ -441,6 +285,23 @@ class OpenLyricsParser(object):
self.manager.save_object(song)
return song.id
def _add_text_to_element(self, tag, parent, text=None, label=None):
if label:
element = etree.Element(tag, name=unicode(label))
else:
element = etree.Element(tag)
if text:
element.text = unicode(text)
parent.append(element)
return element
def _extract_xml(self, xml, pretty_print):
"""
Extract our newly created XML song.
"""
return etree.tostring(xml, encoding=u'UTF-8',
xml_declaration=True, pretty_print=pretty_print)
def _get(self, element, attribute):
"""
This returns the element's attribute as unicode string.
@ -562,7 +423,7 @@ class OpenLyricsParser(object):
``song``
The song object.
"""
sxml = SongXMLBuilder()
sxml = SongXML()
search_text = u''
temp_verse_order = []
for verse in lyrics.verse:
@ -682,3 +543,10 @@ class OpenLyricsParser(object):
song.topics.append(topic)
except AttributeError:
pass
def _dump_xml(self, xml):
"""
Debugging aid to dump XML so that we can see what we have.
"""
return etree.tostring(xml, encoding=u'UTF-8',
xml_declaration=True, pretty_print=True)

View File

@ -31,7 +31,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import Plugin, StringContent, build_icon, translate
from openlp.core.lib.db import Manager
from openlp.plugins.songs.lib import SongMediaItem, SongsTab, SongXMLParser
from openlp.plugins.songs.lib import SongMediaItem, SongsTab, SongXML
from openlp.plugins.songs.lib.db import init_schema, Song
from openlp.plugins.songs.lib.importer import SongFormat
@ -153,7 +153,7 @@ class SongsPlugin(Plugin):
song.search_title = self.whitespace.sub(u' ', song.title.lower() + \
u' ' + song.alternate_title.lower())
lyrics = u''
verses = SongXMLParser(song.lyrics).get_verses()
verses = SongXML().get_verses(song.lyrics)
for verse in verses:
lyrics = lyrics + self.whitespace.sub(u' ', verse[1]) + u' '
song.search_lyrics = lyrics.lower()