diff --git a/documentation/manual/source/pics/songusage.png b/documentation/manual/source/pics/songusage.png new file mode 100644 index 000000000..10f29f2a9 Binary files /dev/null and b/documentation/manual/source/pics/songusage.png differ diff --git a/documentation/manual/source/pics/songusagedelete.png b/documentation/manual/source/pics/songusagedelete.png new file mode 100644 index 000000000..fec1b5e5d Binary files /dev/null and b/documentation/manual/source/pics/songusagedelete.png differ diff --git a/documentation/manual/source/pics/songusagereport.png b/documentation/manual/source/pics/songusagereport.png new file mode 100644 index 000000000..c0d9df3dd Binary files /dev/null and b/documentation/manual/source/pics/songusagereport.png differ diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index 0dc138abc..8afa02111 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -294,4 +294,5 @@ class Manager(object): """ if self.is_dirty: engine = create_engine(self.db_url) - engine.execute("vacuum") + if self.db_url.startswith(u'sqlite'): + engine.execute("vacuum") diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py index 3eae97238..130da0c0e 100644 --- a/openlp/core/lib/mediamanageritem.py +++ b/openlp/core/lib/mediamanageritem.py @@ -320,15 +320,9 @@ class MediaManagerItem(QtGui.QWidget): translate('OpenLP.MediaManagerItem', '&Add to selected Service Item'), self.onAddEditClick)) - if QtCore.QSettings().value(u'advanced/double click live', - QtCore.QVariant(False)).toBool(): - QtCore.QObject.connect(self.listView, - QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), - self.onLiveClick) - else: - QtCore.QObject.connect(self.listView, - QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), - self.onPreviewClick) + QtCore.QObject.connect(self.listView, + QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), + self.onClickPressed) def initialise(self): """ @@ -426,10 +420,20 @@ class MediaManagerItem(QtGui.QWidget): raise NotImplementedError(u'MediaManagerItem.onDeleteClick needs to ' u'be defined by the plugin') - def generateSlideData(self, service_item, item=None): + def generateSlideData(self, serviceItem, item=None, xmlVersion=False): raise NotImplementedError(u'MediaManagerItem.generateSlideData needs ' u'to be defined by the plugin') + def onClickPressed(self): + """ + Allows the list click action to be determined dynamically + """ + if QtCore.QSettings().value(u'advanced/double click live', + QtCore.QVariant(False)).toBool(): + self.onLiveClick() + else: + self.onPreviewClick() + def onPreviewClick(self): """ Preview an item by building a service item then adding that service @@ -442,10 +446,10 @@ class MediaManagerItem(QtGui.QWidget): 'You must select one or more items to preview.')) else: log.debug(self.plugin.name + u' Preview requested') - service_item = self.buildServiceItem() - if service_item: - service_item.from_plugin = True - self.parent.previewController.addServiceItem(service_item) + serviceItem = self.buildServiceItem() + if serviceItem: + serviceItem.from_plugin = True + self.parent.previewController.addServiceItem(serviceItem) def onLiveClick(self): """ @@ -459,10 +463,10 @@ class MediaManagerItem(QtGui.QWidget): 'You must select one or more items to send live.')) else: log.debug(self.plugin.name + u' Live requested') - service_item = self.buildServiceItem() - if service_item: - service_item.from_plugin = True - self.parent.liveController.addServiceItem(service_item) + serviceItem = self.buildServiceItem() + if serviceItem: + serviceItem.from_plugin = True + self.parent.liveController.addServiceItem(serviceItem) def onAddClick(self): """ @@ -474,22 +478,22 @@ class MediaManagerItem(QtGui.QWidget): translate('OpenLP.MediaManagerItem', 'You must select one or more items.')) else: - # Is it posssible to process multiple list items to generate multiple - # service items? + # Is it posssible to process multiple list items to generate + # multiple service items? if self.singleServiceItem or self.remoteTriggered: log.debug(self.plugin.name + u' Add requested') - service_item = self.buildServiceItem() - if service_item: - service_item.from_plugin = False - self.parent.serviceManager.addServiceItem(service_item, + serviceItem = self.buildServiceItem(None, True) + if serviceItem: + serviceItem.from_plugin = False + self.parent.serviceManager.addServiceItem(serviceItem, replace=self.remoteTriggered) else: items = self.listView.selectedIndexes() for item in items: - service_item = self.buildServiceItem(item) - if service_item: - service_item.from_plugin = False - self.parent.serviceManager.addServiceItem(service_item) + serviceItem = self.buildServiceItem(item, True) + if serviceItem: + serviceItem.from_plugin = False + self.parent.serviceManager.addServiceItem(serviceItem) def onAddEditClick(self): """ @@ -502,16 +506,16 @@ class MediaManagerItem(QtGui.QWidget): 'You must select one or more items')) else: log.debug(self.plugin.name + u' Add requested') - service_item = self.parent.serviceManager.getServiceItem() - if not service_item: + serviceItem = self.parent.serviceManager.getServiceItem() + if not serviceItem: QtGui.QMessageBox.information(self, translate('OpenLP.MediaManagerItem', 'No Service Item Selected'), translate('OpenLP.MediaManagerItem', 'You must select an existing service item to add to.')) - elif self.title.lower() == service_item.name.lower(): - self.generateSlideData(service_item) - self.parent.serviceManager.addServiceItem(service_item, + elif self.title.lower() == serviceItem.name.lower(): + self.generateSlideData(serviceItem) + self.parent.serviceManager.addServiceItem(serviceItem, replace=True) else: # Turn off the remote edit update message indicator @@ -521,17 +525,17 @@ class MediaManagerItem(QtGui.QWidget): unicode(translate('OpenLP.MediaManagerItem', 'You must select a %s service item.')) % self.title) - def buildServiceItem(self, item=None): + def buildServiceItem(self, item=None, xmlVersion=False): """ Common method for generating a service item """ - service_item = ServiceItem(self.parent) + serviceItem = ServiceItem(self.parent) if self.serviceItemIconName: - service_item.add_icon(self.serviceItemIconName) + serviceItem.add_icon(self.serviceItemIconName) else: - service_item.add_icon(self.parent.icon_path) - if self.generateSlideData(service_item, item): - return service_item + serviceItem.add_icon(self.parent.icon_path) + if self.generateSlideData(serviceItem, item, xmlVersion): + return serviceItem else: return None diff --git a/openlp/core/lib/serviceitem.py b/openlp/core/lib/serviceitem.py index 0cbc34de5..b9394030a 100644 --- a/openlp/core/lib/serviceitem.py +++ b/openlp/core/lib/serviceitem.py @@ -101,6 +101,7 @@ class ServiceItem(object): self.search_string = u'' self.data_string = u'' self.edit_id = None + self.xml_version = None self._new_item() def _new_item(self): @@ -252,7 +253,8 @@ class ServiceItem(object): u'from_plugin': self.from_plugin, u'capabilities': self.capabilities, u'search': self.search_string, - u'data': self.data_string + u'data': self.data_string, + u'xml_version': self.xml_version } service_data = [] if self.service_item_type == ServiceItemType.Text: @@ -294,6 +296,8 @@ class ServiceItem(object): if u'search' in header: self.search_string = header[u'search'] self.data_string = header[u'data'] + if u'xml_version' in header: + self.xml_version = header[u'xml_version'] if self.service_item_type == ServiceItemType.Text: for slide in serviceitem[u'serviceitem'][u'data']: self._raw_frames.append(slide) diff --git a/openlp/core/ui/advancedtab.py b/openlp/core/ui/advancedtab.py index dc126d863..a390780ca 100644 --- a/openlp/core/ui/advancedtab.py +++ b/openlp/core/ui/advancedtab.py @@ -146,7 +146,7 @@ class AdvancedTab(SettingsTab): self.mediaPluginCheckBox.setText(translate('OpenLP.AdvancedTab', 'Remember active media manager tab on startup')) self.doubleClickLiveCheckBox.setText(translate('OpenLP.AdvancedTab', - 'Double-click to send items straight to live (requires restart)')) + 'Double-click to send items straight to live')) self.expandServiceItemCheckBox.setText(translate('OpenLP.AdvancedTab', 'Expand new service items on creation')) # self.sharedDirGroupBox.setTitle( diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 5a53a84fe..90f920a50 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -100,7 +100,7 @@ class MainDisplay(DisplayWidget): self.screens = screens self.isLive = live self.alertTab = None - self.hide_mode = None + self.hideMode = None self.setWindowTitle(u'OpenLP Display') self.setStyleSheet(u'border: 0px; margin: 0px; padding: 0px;') self.setWindowFlags(QtCore.Qt.FramelessWindowHint | @@ -381,8 +381,8 @@ class MainDisplay(DisplayWidget): if self.isLive: self.setVisible(True) # if was hidden keep it hidden - if self.hide_mode and self.isLive: - self.hideDisplay(self.hide_mode) + if self.hideMode and self.isLive: + self.hideDisplay(self.hideMode) preview = QtGui.QImage(self.screen[u'size'].width(), self.screen[u'size'].height(), QtGui.QImage.Format_ARGB32_Premultiplied) @@ -412,8 +412,8 @@ class MainDisplay(DisplayWidget): if serviceItem.foot_text and serviceItem.foot_text: self.footer(serviceItem.foot_text) # if was hidden keep it hidden - if self.hide_mode and self.isLive: - self.hideDisplay(self.hide_mode) + if self.hideMode and self.isLive: + self.hideDisplay(self.hideMode) def footer(self, text): """ @@ -444,7 +444,7 @@ class MainDisplay(DisplayWidget): self.setVisible(True) if self.phononActive: self.webView.setVisible(True) - self.hide_mode = mode + self.hideMode = mode def showDisplay(self): """ @@ -459,9 +459,9 @@ class MainDisplay(DisplayWidget): if self.phononActive: self.webView.setVisible(False) self.videoPlay() + self.hideMode = None # Trigger actions when display is active again Receiver.send_message(u'maindisplay_active') - self.hide_mode = None class AudioPlayer(QtCore.QObject): """ diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index f294cedd4..6d721823a 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -789,6 +789,8 @@ class ServiceManager(QtGui.QWidget): self.serviceName = name[len(name) - 1] self.parent.addRecentFile(filename) self.parent.serviceChanged(True, self.serviceName) + # Refresh Plugin lists + Receiver.send_message(u'plugin_list_refresh') def validateItem(self, serviceItem): """ @@ -1028,6 +1030,9 @@ class ServiceManager(QtGui.QWidget): # ServiceManager started the drag and drop if plugin == u'ServiceManager': startpos, startCount = self.findServiceItem() + # If no items selected + if startpos == -1: + return if item is None: endpos = len(self.serviceItems) else: diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 0afb0efaa..48810990a 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -331,10 +331,8 @@ class SlideController(QtGui.QWidget): QtCore.QObject.connect(self.PreviewListWidget, QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onSlideSelected) if not self.isLive: - if QtCore.QSettings().value(u'advanced/double click live', - QtCore.QVariant(False)).toBool(): - QtCore.QObject.connect(self.PreviewListWidget, - QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), self.onGoLive) + QtCore.QObject.connect(self.PreviewListWidget, + QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), self.onGoLiveClick) if isLive: QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'slidecontroller_live_spin_delay'), @@ -391,6 +389,8 @@ class SlideController(QtGui.QWidget): if self.isLive: QtCore.QObject.connect(self.volumeSlider, QtCore.SIGNAL(u'sliderReleased()'), self.mediaVolume) + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'maindisplay_active'), self.updatePreview) def screenSizeChanged(self): """ @@ -823,16 +823,15 @@ class SlideController(QtGui.QWidget): row) def updatePreview(self): + log.debug(u'updatePreview %s ' %self.screens.current[u'primary']) if not self.screens.current[u'primary']: # Grab now, but try again in a couple of seconds if slide change # is slow QtCore.QTimer.singleShot(0.5, self.grabMainDisplay) QtCore.QTimer.singleShot(2.5, self.grabMainDisplay) else: - label = self.PreviewListWidget.cellWidget( - self.PreviewListWidget.currentRow(), 1) - if label: - self.SlidePreview.setPixmap(label.pixmap()) + self.SlidePreview.setPixmap( + QtGui.QPixmap.fromImage(self.display.preview())) def grabMainDisplay(self): winid = QtGui.QApplication.desktop().winId() @@ -944,6 +943,14 @@ class SlideController(QtGui.QWidget): Receiver.send_message(u'%s_edit' % self.serviceItem.name.lower(), u'P:%s' % self.serviceItem.edit_id) + def onGoLiveClick(self): + """ + triggered by clicking the Preview slide items + """ + if QtCore.QSettings().value(u'advanced/double click live', + QtCore.QVariant(False)).toBool(): + self.onGoLive() + def onGoLive(self): """ If preview copy slide item to live diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index bb3c1b26d..0e1850485 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -545,7 +545,7 @@ class BibleMediaItem(MediaManagerItem): self.dual_search_results = self.parent.manager.get_verses( dual_bible, text) else: - # We are doing a ' Text Search'. + # We are doing a 'Text Search'. bibles = self.parent.manager.get_bibles() self.search_results = self.parent.manager.verse_search(bible, text) if dual_bible and self.search_results: @@ -651,7 +651,7 @@ class BibleMediaItem(MediaManagerItem): obj = obj.toPyObject() return unicode(obj) - def generateSlideData(self, service_item, item=None): + def generateSlideData(self, service_item, item=None, xmlVersion=False): """ Generates and formats the slides for the service item as well as the service item's title. diff --git a/openlp/plugins/custom/forms/editcustomform.py b/openlp/plugins/custom/forms/editcustomform.py index 65a73337a..c5281574b 100644 --- a/openlp/plugins/custom/forms/editcustomform.py +++ b/openlp/plugins/custom/forms/editcustomform.py @@ -46,7 +46,6 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog): Constructor """ QtGui.QDialog.__init__(self, parent) - #self.parent = parent self.setupUi(self) # Connecting signals and slots self.previewButton = QtGui.QPushButton() @@ -124,8 +123,9 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog): self.slideListView.addItem(slide[1]) theme = self.customSlide.theme_name id = self.themeComboBox.findText(theme, QtCore.Qt.MatchExactly) + # No theme match if id == -1: - id = 0 # Not Found + id = 0 self.themeComboBox.setCurrentIndex(id) else: self.themeComboBox.setCurrentIndex(0) @@ -264,7 +264,7 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog): self.titleEdit.setFocus() return False, translate('CustomPlugin.EditCustomForm', 'You need to type in a title.') - # We must have one slide. + # We must have at least one slide. if self.slideListView.count() == 0: return False, translate('CustomPlugin.EditCustomForm', 'You need to add at least one slide') diff --git a/openlp/plugins/custom/forms/editcustomslideform.py b/openlp/plugins/custom/forms/editcustomslideform.py index 5f535c8bc..72c7dbb4a 100644 --- a/openlp/plugins/custom/forms/editcustomslideform.py +++ b/openlp/plugins/custom/forms/editcustomslideform.py @@ -50,7 +50,7 @@ class EditCustomSlideForm(QtGui.QDialog, Ui_CustomSlideEditDialog): def setText(self, text): """ Set the text for slideTextEdit. - + ``text`` The text (unicode). """ @@ -67,7 +67,7 @@ class EditCustomSlideForm(QtGui.QDialog, Ui_CustomSlideEditDialog): def onSplitButtonPressed(self): """ - Splits a slide in two slides. + Adds a slide split at the cursor. """ if self.slideTextEdit.textCursor().columnNumber() != 0: self.slideTextEdit.insertPlainText(u'\n') diff --git a/openlp/plugins/custom/lib/customxmlhandler.py b/openlp/plugins/custom/lib/customxmlhandler.py index b554f9657..907c3470d 100644 --- a/openlp/plugins/custom/lib/customxmlhandler.py +++ b/openlp/plugins/custom/lib/customxmlhandler.py @@ -43,6 +43,7 @@ import logging from xml.dom.minidom import Document from xml.etree.ElementTree import ElementTree, XML, dump +from lxml import etree, objectify from xml.parsers.expat import ExpatError log = logging.getLogger(__name__) @@ -55,14 +56,14 @@ class CustomXMLBuilder(object): def __init__(self): """ - Set up the song builder. + Set up the custom builder. """ # Create the minidom document self.custom_xml = Document() def new_document(self): """ - Create a new song XML document. + Create a new custom XML document. """ # Create the base element self.song = self.custom_xml.createElement(u'song') @@ -72,7 +73,7 @@ class CustomXMLBuilder(object): def add_lyrics_to_song(self): """ Set up and add a ```` tag which contains the lyrics of the - song. + custom item. """ # Create the main element self.lyrics = self.custom_xml.createElement(u'lyrics') @@ -93,7 +94,6 @@ class CustomXMLBuilder(object): ``content`` The actual text of the verse to be stored. """ - #log.debug(u'add_verse_to_lyrics %s, %s\n%s' % (type, number, content)) verse = self.custom_xml.createElement(u'verse') verse.setAttribute(u'type', type) verse.setAttribute(u'label', number) @@ -102,7 +102,7 @@ class CustomXMLBuilder(object): cds = self.custom_xml.createCDATASection(content) verse.appendChild(cds) - def dump_xml(self): + def _dump_xml(self): """ Debugging aid to dump XML so that we can see what we have. """ @@ -110,29 +110,30 @@ class CustomXMLBuilder(object): def extract_xml(self): """ - Extract our newly created XML song. + Extract our newly created XML custom. """ return self.custom_xml.toxml(u'utf-8') class CustomXMLParser(object): """ - A class to read in and parse a song's XML. + A class to read in and parse a custom's XML. """ log.info(u'CustomXMLParser Loaded') def __init__(self, xml): """ - Set up our song XML parser. + Set up our custom XML parser. ``xml`` - The XML of the song to be parsed. + The XML of the custom to be parsed. """ self.custom_xml = None + if xml[:5] == u' 1: self.DisplayTypeComboBox.insertItem(0, self.Automatic) self.DisplayTypeComboBox.setCurrentIndex(0) - if QtCore.QSettings().value(self.settingsSection + u'/override app', + if QtCore.QSettings().value(self.settingsSection + u'/override app', QtCore.QVariant(QtCore.Qt.Unchecked)) == QtCore.Qt.Checked: self.PresentationWidget.show() else: @@ -238,7 +238,7 @@ class PresentationMediaItem(MediaManagerItem): SettingsManager.set_list(self.settingsSection, self.settingsSection, self.getFileList()) - def generateSlideData(self, service_item, item=None): + def generateSlideData(self, service_item, item=None, xmlVersion=False): """ Load the relevant information for displaying the presentation in the slidecontroller. In the case of powerpoints, an image @@ -277,7 +277,7 @@ class PresentationMediaItem(MediaManagerItem): def findControllerByType(self, filename): """ Determine the default application controller to use for the selected - file type. This is used if "Automatic" is set as the preferred + file type. This is used if "Automatic" is set as the preferred controller. Find the first (alphabetic) enabled controller which "supports" the extension. If none found, then look for a controller which "alsosupports" it instead. diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py index 241c6fd95..c9868d2e3 100644 --- a/openlp/plugins/songs/forms/editsongform.py +++ b/openlp/plugins/songs/forms/editsongform.py @@ -630,14 +630,17 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): Get all the data from the widgets on the form, and then save it to the database. - ``preview`` + ``preview`` Should be True if song is also previewed. """ self.song.title = unicode(self.TitleEditItem.text()) self.song.alternate_title = unicode(self.AlternativeEdit.text()) self.song.copyright = unicode(self.CopyrightEditItem.text()) - self.song.search_title = self.song.title + u'@' + \ - self.song.alternate_title + if self.song.alternate_title: + self.song.search_title = self.song.title + u'@' + \ + self.song.alternate_title + else: + self.song.search_title = self.song.title self.song.comments = unicode(self.CommentsEdit.toPlainText()) self.song.verse_order = unicode(self.VerseOrderEdit.text()) self.song.ccli_number = unicode(self.CCLNumberEdit.text()) @@ -648,6 +651,11 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): Book.name == book_name) else: self.song.book = None + theme_name = unicode(self.ThemeSelectionComboItem.currentText()) + if theme_name: + self.song.theme_name = theme_name + else: + self.song.theme_name = None if self._validate_song(): self.processLyrics() self.processTitle() diff --git a/openlp/plugins/songs/lib/__init__.py b/openlp/plugins/songs/lib/__init__.py index 351d50071..795116b4e 100644 --- a/openlp/plugins/songs/lib/__init__.py +++ b/openlp/plugins/songs/lib/__init__.py @@ -62,6 +62,36 @@ class VerseType(object): elif verse_type == VerseType.Other: return translate('SongsPlugin.VerseType', 'Other') + @staticmethod + def expand_string(verse_type): + """ + Return the VerseType for a given string + + ``verse_type`` + The string to return a VerseType for + """ + verse_type = verse_type.lower() + if verse_type == unicode(VerseType.to_string(VerseType.Verse)).lower()[0]: + return translate('SongsPlugin.VerseType', 'Verse') + elif verse_type == \ + unicode(VerseType.to_string(VerseType.Chorus)).lower()[0]: + return translate('SongsPlugin.VerseType', 'Chorus') + elif verse_type == \ + unicode(VerseType.to_string(VerseType.Bridge)).lower()[0]: + return translate('SongsPlugin.VerseType', 'Bridge') + elif verse_type == \ + unicode(VerseType.to_string(VerseType.PreChorus)).lower()[0]: + return translate('SongsPlugin.VerseType', 'PreChorus') + elif verse_type == \ + unicode(VerseType.to_string(VerseType.Intro)).lower()[0]: + return translate('SongsPlugin.VerseType', 'Intro') + elif verse_type == \ + unicode(VerseType.to_string(VerseType.Ending)).lower()[0]: + return translate('SongsPlugin.VerseType', 'Ending') + elif verse_type == \ + unicode(VerseType.to_string(VerseType.Other)).lower()[0]: + return translate('SongsPlugin.VerseType', 'Other') + @staticmethod def from_string(verse_type): """ @@ -92,7 +122,6 @@ class VerseType(object): unicode(VerseType.to_string(VerseType.Other)).lower(): return VerseType.Other - -from xml import LyricsXML, SongXMLBuilder, SongXMLParser +from xml import LyricsXML, SongXMLBuilder, SongXMLParser, OpenLyricsParser from songstab import SongsTab from mediaitem import SongMediaItem diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index cb2d6a6e0..432eee744 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -32,7 +32,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 SongXMLParser +from openlp.plugins.songs.lib import SongXMLParser, OpenLyricsParser from openlp.plugins.songs.lib.db import Author, Song log = logging.getLogger(__name__) @@ -53,8 +53,8 @@ class SongMediaItem(MediaManagerItem): self.ListViewWithDnD_class = SongListView MediaManagerItem.__init__(self, parent, self, icon) self.edit_song_form = EditSongForm(self, self.parent.manager) + self.openLyrics = OpenLyricsParser(self.parent.manager) self.singleServiceItem = False - #self.edit_song_form = EditSongForm(self.parent.manager, self) self.song_maintenance_form = SongMaintenanceForm( self.parent.manager, self) # Holds information about whether the edit is remotly triggered and @@ -114,6 +114,8 @@ class SongMediaItem(MediaManagerItem): self.SearchButtonLayout.addWidget(self.ClearTextButton) self.pageLayout.addLayout(self.SearchButtonLayout) # Signals and slots + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'plugin_list_refresh'), self.onSearchTextButtonClick) QtCore.QObject.connect(self.SearchTextEdit, QtCore.SIGNAL(u'returnPressed()'), self.onSearchTextButtonClick) QtCore.QObject.connect(self.SearchTextButton, @@ -141,7 +143,7 @@ class SongMediaItem(MediaManagerItem): self.updateServiceOnEdit = QtCore.QSettings().value( self.settingsSection + u'/update service on edit', QtCore.QVariant(u'False')).toBool() - self.AddSongFromServide = QtCore.QSettings().value( + self.addSongFromService = QtCore.QSettings().value( self.settingsSection + u'/add song from service', QtCore.QVariant(u'True')).toBool() @@ -328,7 +330,7 @@ class SongMediaItem(MediaManagerItem): self.parent.manager.delete_object(Song, item_id) self.onSearchTextButtonClick() - def generateSlideData(self, service_item, item=None): + def generateSlideData(self, service_item, item=None, xmlVersion=False): log.debug(u'generateSlideData (%s:%s)' % (service_item, item)) raw_footer = [] author_list = u'' @@ -355,7 +357,7 @@ class SongMediaItem(MediaManagerItem): if song.lyrics.startswith(u'' + \ u'%s' % lyrics_output return song_output + + +class OpenLyricsParser(object): + """ + This class represents the converter for Song to/from OpenLyrics XML. + """ + def __init__(self, manager): + self.manager = manager + + def song_to_xml(self, song): + """ + Convert the song to OpenLyrics Format + """ + song_xml_parser = SongXMLParser(song.lyrics) + verse_list = song_xml_parser.get_verses() + song_xml = objectify.fromstring( + u'') + 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.theme_name: + themes = etree.SubElement(properties, u'themes') + self._add_text_to_element(u'theme', themes, song.theme_name) + self._add_text_to_element(u'copyright', properties, song.copyright) + 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) + authors = etree.SubElement(properties, u'authors') + for author in song.authors: + self._add_text_to_element(u'author', authors, author.display_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) + + def xml_to_song(self, xml): + """ + Create a Song from OpenLyrics format xml + """ + # No xml get out of here + if not xml: + return 0 + song = Song() + if xml[:5] == u'