openlyrics fixes, add meta data to songs, opensong import fix, signals for openlyrics export

This commit is contained in:
Andreas Preikschat 2011-01-24 20:36:44 +01:00
commit e7b1f88e53
4 changed files with 141 additions and 52 deletions

View File

@ -27,11 +27,10 @@
The song export function for OpenLP.
"""
import logging
import os
from PyQt4 import QtCore, QtGui
from openlp.core.lib import Receiver, SettingsManager, translate
from openlp.core.lib import Receiver, translate
from openlp.core.ui import criticalErrorMessageBox
from openlp.core.ui.wizard import OpenLPWizard
from openlp.plugins.songs.lib.db import Song
@ -59,6 +58,16 @@ class SongExportForm(OpenLPWizard):
self.plugin = plugin
OpenLPWizard.__init__(self, parent, plugin, u'songExportWizard',
u':/wizards/wizard_importsong.bmp')
self.stop_export_flag = False
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'openlp_stop_wizard'), self.stop_export)
def stop_export(self):
"""
Sets the flag for exporters to stop their export
"""
log.debug(u'Stopping songs export')
self.stop_export_flag = True
def setupUi(self, image):
"""
@ -70,25 +79,22 @@ class SongExportForm(OpenLPWizard):
"""
Song wizard specific initialisation.
"""
songs = self.plugin.manager.get_all_objects(Song)
for song in songs:
author_list = u''
for author in song.authors:
if author_list != u'':
author_list = author_list + u', '
author_list = author_list + author.display_name
song_title = unicode(song.title)
song_detail = u'%s (%s)' % (song_title, author_list)
song_name = QtGui.QListWidgetItem(song_detail)
song_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(song))
self.availableListWidget.addItem(song_name)
self.availableListWidget.selectAll()
pass
def customSignals(self):
"""
Song wizard specific signals.
"""
pass
QtCore.QObject.connect(self.addSelected,
QtCore.SIGNAL(u'clicked()'), self.onAddSelectedClicked)
QtCore.QObject.connect(self.removeSelected,
QtCore.SIGNAL(u'clicked()'), self.onRemoveSelectedClicked)
QtCore.QObject.connect(self.availableListWidget,
QtCore.SIGNAL(u'itemDoubleClicked(QListWidgetItem *)'),
self.onAvailableListItemDoubleClicked)
QtCore.QObject.connect(self.selectedListWidget,
QtCore.SIGNAL(u'itemDoubleClicked(QListWidgetItem *)'),
self.onSelectedListItemDoubleClicked)
def addCustomPages(self):
"""
@ -105,6 +111,11 @@ class SongExportForm(OpenLPWizard):
self.verticalLayout.setObjectName(u'verticalLayout')
self.availableListWidget = QtGui.QListWidget(self.availableGroupBox)
self.availableListWidget.setObjectName(u'availableListWidget')
self.availableListWidget.setSelectionMode(
QtGui.QAbstractItemView.ExtendedSelection)
self.availableListWidget.setSizePolicy(
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
self.availableListWidget.setSortingEnabled(True)
self.verticalLayout.addWidget(self.availableListWidget)
self.sourceLayout.addWidget(self.availableGroupBox)
self.selectionWidget = QtGui.QWidget(self.sourcePage)
@ -138,9 +149,15 @@ class SongExportForm(OpenLPWizard):
self.verticalLayout.setObjectName(u'verticalLayout')
self.selectedListWidget = QtGui.QListWidget(self.selectedGroupBox)
self.selectedListWidget.setObjectName(u'selectedListWidget')
self.selectedListWidget.setSelectionMode(
QtGui.QAbstractItemView.ExtendedSelection)
self.selectedListWidget.setSizePolicy(
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
self.selectedListWidget.setSortingEnabled(True)
self.verticalLayout.addWidget(self.selectedListWidget)
self.sourceLayout.addWidget(self.selectedGroupBox)
self.addPage(self.sourcePage)
#TODO: Add save dialog
def retranslateUi(self):
"""
@ -151,28 +168,28 @@ class SongExportForm(OpenLPWizard):
self.titleLabel.setText(
u'<span style="font-size:14pt; font-weight:600;">%s</span>' % \
translate('SongsPlugin.ExportWizardForm',
'Welcome to the Song Export Wizard'))
'Welcome to the Song Export Wizard'))
self.informationLabel.setText(
translate('SongsPlugin.ExportWizardForm', 'This wizard will help to '
'export your songs to the free and open OpenLyrics worship song '
'format. You can import these songs in all lyrics projection '
'software, which supports OpenLyrics.'))
self.sourcePage.setTitle(
translate('SongsPlugin.ExportWizardForm', 'Select Emport Source'))
translate('SongsPlugin.ExportWizardForm', 'Select Songs'))
self.sourcePage.setSubTitle(
translate('SongsPlugin.ExportWizardForm',
'Select the export format, and where to export from.'))
'Select the songs, you want to export.'))
self.progressPage.setTitle(
translate('SongsPlugin.ExportWizardForm', 'Exporting'))
self.progressPage.setSubTitle(
translate('SongsPlugin.ExportWizardForm',
'Please wait while your songs are exported.'))
'Please wait while your songs are exported.'))
self.progressLabel.setText(
translate('SongsPlugin.ExportWizardForm', 'Ready.'))
self.progressBar.setFormat(
translate('SongsPlugin.ExportWizardForm', '%p%'))
self.availableGroupBox.setTitle(
translate('SongsPlugin.ExportWizardForm', 'Available Songs'))
self.addSelected.setText(
@ -187,10 +204,35 @@ class SongExportForm(OpenLPWizard):
Validate the current page before moving on to the next page.
"""
if self.currentPage() == self.welcomePage:
Receiver.send_message(u'cursor_busy')
songs = self.plugin.manager.get_all_objects(Song)
for song in songs:
author_list = u''
for author in song.authors:
if author_list != u'':
author_list = author_list + u', '
author_list = author_list + author.display_name
song_title = unicode(song.title)
song_detail = u'%s (%s)' % (song_title, author_list)
song_name = QtGui.QListWidgetItem(song_detail)
song_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(song))
self.availableListWidget.addItem(song_name)
self.availableListWidget.selectAll()
Receiver.send_message(u'cursor_normal')
return True
elif self.currentPage() == self.sourcePage:
self.selectedListWidget.selectAll()
if not self.selectedListWidget.selectedItems():
criticalErrorMessageBox(
translate('SongsPlugin.ExportWizardForm',
'No Song Selected'),
translate('SongsPlugin.ImportWizardForm',
'You need to add at least one Song to export.'))
return False
return True
elif self.currentPage() == self.progressPage:
self.availableListWidget.clear()
self.selectedListWidget.clear()
return True
def registerFields(self):
@ -222,8 +264,9 @@ class SongExportForm(OpenLPWizard):
class, and then runs the ``do_export`` method of the exporter to do
the actual exporting.
"""
exporter = OpenLyricsExport(self.plugin.manager,
self.plugin.manager.get_all_objects(Song), u'/tmp/')
songs = [item.data(QtCore.Qt.UserRole).toPyObject()
for item in self.selectedListWidget.selectedItems()]
exporter = OpenLyricsExport(self, songs, u'/tmp/')
if exporter.do_export():
self.progressLabel.setText(
translate('SongsPlugin.SongExportForm', 'Finished export.'))
@ -231,3 +274,47 @@ class SongExportForm(OpenLPWizard):
self.progressLabel.setText(
translate('SongsPlugin.SongExportForm',
'Your song export failed.'))
def onAddSelectedClicked(self):
"""
Removes the selected items from the list of available songs and add them
to the list of selected songs.
"""
items = self.availableListWidget.selectedItems()
# Save a list with tuples which consist of the item row, and the item.
items = [(self.availableListWidget.row(item), item) for item in items]
items.sort(reverse=True)
for item in items:
self.availableListWidget.takeItem(item[0])
self.selectedListWidget.addItem(item[1])
def onRemoveSelectedClicked(self):
"""
Removes the selected items from the list of selected songs and add them
back to the list of available songs.
"""
items = self.selectedListWidget.selectedItems()
# Save a list with tuples which consist of the item row, and the item.
items = [(self.selectedListWidget.row(item), item) for item in items]
items.sort(reverse=True)
for item in items:
self.selectedListWidget.takeItem(item[0])
self.availableListWidget.addItem(item[1])
def onAvailableListItemDoubleClicked(self, item):
"""
Adds the double clicked item to the list of selected songs and removes
it from the list of availables songs.
"""
row = self.availableListWidget.row(item)
self.availableListWidget.takeItem(row)
self.selectedListWidget.addItem(item)
def onSelectedListItemDoubleClicked(self, item):
"""
Adds the double clicked item back to the list of available songs and
removes it from the list of selected songs.
"""
row = self.selectedListWidget.row(item)
self.selectedListWidget.takeItem(row)
self.availableListWidget.addItem(item)

View File

@ -27,13 +27,12 @@
The :mod:`openlyricsexport` module provides the functionality for exporting
songs from the database.
"""
import datetime
import logging
import os
from lxml import etree, objectify
from openlp.core.lib import translate
from openlp.core.lib import Receiver, translate
from openlp.plugins.songs.lib import OpenLyrics
log = logging.getLogger(__name__)
@ -42,42 +41,34 @@ class OpenLyricsExport(object):
"""
This provides the Openlyrics export.
"""
def __init__(self, master_manager, song_ids, save_path):
def __init__(self, parent, songs, save_path):
"""
Initialise the export.
"""
log.debug(u'initialise OpenLyricsExport')
self.master_manager = master_manager
self.songs = song_ids
self.parent = parent
self.manager = parent.plugin.manager
self.songs = songs
self.save_path = save_path
def do_export(self):
"""
Export the songs.
"""
openLyrics = OpenLyrics(self.master_manager)
# self.export_wizard.exportProgressBar.setMaximum(len(songs))
openLyrics = OpenLyrics(self.manager)
self.parent.progressBar.setMaximum(len(self.songs))
for song in self.songs:
# if self.stop_export_flag:
# return False
# self.export_wizard.incrementProgressBar(unicode(translate(
# 'SongsPlugin.OpenLyricsExport', 'Exporting %s...')) %
# song.title)
Receiver.send_message(u'openlp_process_events')
if self.parent.stop_export_flag:
return False
self.parent.incrementProgressBar(unicode(translate(
'SongsPlugin.OpenLyricsExport', 'Exporting %s...')) %
song.title)
# Check if path exists. If not, create the directories!
# What do we do with songs with the same title? I do not want to
# overwrite them!
path = os.path.join(self.save_path, song.title + u'.xml')
# Convert the song object to an unicode string.
xml = openLyrics.song_to_xml(song)
song_xml = objectify.fromstring(xml)
# Append the necessary meta data to the song.
# (Maybe move this to the xml module?
song_xml.set(u'version', OpenLyrics.IMPLEMENTED_VERSION)
song_xml.set(u'createdIn', u'OpenLP 1.9.4') # Use variable
song_xml.set(u'modifiedIn', u'OpenLP 1.9.4') # Use variable
song_xml.set(u'modifiedDate',
datetime.datetime.now().strftime(u'%Y-%m-%dT%H:%M:%S'))
xml = etree.tostring(song_xml)
tree = etree.ElementTree(etree.fromstring(xml))
tree.write(path, encoding=u'utf-8', xml_declaration=True,
pretty_print=True)

View File

@ -39,6 +39,7 @@ log = logging.getLogger(__name__)
class OpenSongImportError(Exception):
pass
#TODO: Use lxml for parsing and make sure we use methods of "SongImport" .
class OpenSongImport(SongImport):
"""
Import songs exported from OpenSong
@ -149,7 +150,7 @@ class OpenSongImport(SongImport):
log.info(u'Zip importing %s', parts[-1])
self.import_wizard.incrementProgressBar(
unicode(translate('SongsPlugin.ImportWizardForm',
'Importing %s...')) % parts[-1])
'Importing %s...')) % parts[-1])
songfile = z.open(song)
self.do_import_file(songfile)
if self.commit:
@ -279,7 +280,7 @@ class OpenSongImport(SongImport):
for num in versenums:
versetag = u'%s%s' % (our_verse_type, num)
lines = u'\n'.join(verses[versetype][num])
self.verses.append([versetag, lines])
self.add_verse(lines, versetag)
# Keep track of what we have for error checking later
versetags[versetag] = 1
# now figure out the presentation order
@ -295,6 +296,8 @@ class OpenSongImport(SongImport):
else:
log.warn(u'No verse order available for %s, skipping.',
self.title)
# TODO: make sure that the default order list will be overwritten, if
# the songs provides its own order list.
for tag in order:
if tag[0].isdigit():
# Assume it's a verse if it has no prefix

View File

@ -60,6 +60,7 @@ The XML of `OpenLyrics <http://openlyrics.info/>`_ songs is of the format::
</song>
"""
import datetime
import logging
import re
@ -207,7 +208,8 @@ class OpenLyrics(object):
This property is not supported.
*<verse name="v1a" lang="he" translit="en">*
The attribute *translit* is not supported.
The attribute *translit* is not supported. Note, the attribute *lang* is
considered, but there is not further functionality implemented yet.
*<verseOrder>*
OpenLP supports this property.
@ -222,8 +224,14 @@ class OpenLyrics(object):
"""
sxml = SongXML()
verse_list = sxml.get_verses(song.lyrics)
song_xml = objectify.fromstring(
u'<song version="0.7" createdIn="OpenLP 2.0"/>')
song_xml = objectify.fromstring(u'<song/>')
# Append the necessary meta data to the song.
song_xml.set(u'xmlns', u'http://openlyrics.info/namespace/2009/song')
song_xml.set(u'version', OpenLyrics.IMPLEMENTED_VERSION)
song_xml.set(u'createdIn', u'OpenLP 1.9.4') # Use variable
song_xml.set(u'modifiedIn', u'OpenLP 1.9.4') # Use variable
song_xml.set(u'modifiedDate',
datetime.datetime.now().strftime(u'%Y-%m-%dT%H:%M:%S'))
properties = etree.SubElement(song_xml, u'properties')
titles = etree.SubElement(properties, u'titles')
self._add_text_to_element(u'title', titles, song.title.strip())
@ -237,7 +245,7 @@ class OpenLyrics(object):
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)
u'verseOrder', properties, song.verse_order.lower())
if song.ccli_number:
self._add_text_to_element(u'ccliNo', properties, song.ccli_number)
if song.authors:
@ -450,7 +458,7 @@ class OpenLyrics(object):
text += u'\n'
text += u'\n'.join([unicode(line) for line in lines.line])
verse_name = self._get(verse, u'name')
verse_type = unicode(VerseType.to_string(verse_name[0]))[0]
verse_type = unicode(VerseType.to_string(verse_name[0]))
verse_number = re.compile(u'[a-zA-Z]*').sub(u'', verse_name)
verse_part = re.compile(u'[0-9]*').sub(u'', verse_name[1:])
# OpenLyrics allows e. g. "c", but we need "c1".