diff --git a/openlp/core/ui/__init__.py b/openlp/core/ui/__init__.py
index 5763b3470..0f62a6dcf 100644
--- a/openlp/core/ui/__init__.py
+++ b/openlp/core/ui/__init__.py
@@ -63,7 +63,6 @@ from splashscreen import SplashScreen
from generaltab import GeneralTab
from themestab import ThemesTab
from advancedtab import AdvancedTab
-from displaytagtab import DisplayTagTab
from aboutform import AboutForm
from pluginform import PluginForm
from settingsform import SettingsForm
diff --git a/openlp/core/ui/advancedtab.py b/openlp/core/ui/advancedtab.py
index 39fec1f9d..5cb22cb8b 100644
--- a/openlp/core/ui/advancedtab.py
+++ b/openlp/core/ui/advancedtab.py
@@ -28,8 +28,9 @@ The :mod:`advancedtab` provides an advanced settings facility.
"""
from PyQt4 import QtCore, QtGui
-from openlp.core.lib import SettingsTab, translate
+from openlp.core.lib import SettingsTab, translate, build_icon
from openlp.core.lib.ui import UiStrings
+from openlp.core.utils import get_images_filter
class AdvancedTab(SettingsTab):
"""
@@ -41,6 +42,8 @@ class AdvancedTab(SettingsTab):
Initialise the settings tab
"""
SettingsTab.__init__(self, u'Advanced')
+ self.default_image = u':/graphics/openlp-splash-screen.png'
+ self.default_color = u'#ffffff'
def setupUi(self):
"""
@@ -81,33 +84,38 @@ class AdvancedTab(SettingsTab):
self.hideMouseCheckBox.setObjectName(u'hideMouseCheckBox')
self.hideMouseLayout.addWidget(self.hideMouseCheckBox)
self.leftLayout.addWidget(self.hideMouseGroupBox)
-# self.sharedDirGroupBox = QtGui.QGroupBox(self.leftColumn)
-# self.sharedDirGroupBox.setObjectName(u'sharedDirGroupBox')
-# self.sharedDirLayout = QtGui.QFormLayout(self.sharedDirGroupBox)
-# self.sharedCheckBox = QtGui.QCheckBox(self.sharedDirGroupBox)
-# self.sharedCheckBox.setObjectName(u'sharedCheckBox')
-# self.sharedDirLayout.addRow(self.sharedCheckBox)
-# self.sharedLabel = QtGui.QLabel(self.sharedDirGroupBox)
-# self.sharedLabel.setObjectName(u'sharedLabel')
-# self.sharedSubLayout = QtGui.QHBoxLayout()
-# self.sharedSubLayout.setObjectName(u'sharedSubLayout')
-# self.sharedLineEdit = QtGui.QLineEdit(self.sharedDirGroupBox)
-# self.sharedLineEdit.setObjectName(u'sharedLineEdit')
-# self.sharedSubLayout.addWidget(self.sharedLineEdit)
-# self.sharedPushButton = QtGui.QPushButton(self.sharedDirGroupBox)
-# self.sharedPushButton.setObjectName(u'sharedPushButton')
-# self.sharedSubLayout.addWidget(self.sharedPushButton)
-# self.sharedDirLayout.addRow(self.sharedLabel, self.sharedSubLayout)
-# self.leftLayout.addWidget(self.sharedDirGroupBox)
self.leftLayout.addStretch()
-# self.databaseGroupBox = QtGui.QGroupBox(self.rightColumn)
-# self.databaseGroupBox.setObjectName(u'databaseGroupBox')
-# self.databaseGroupBox.setEnabled(False)
-# self.databaseLayout = QtGui.QVBoxLayout(self.databaseGroupBox)
-# self.rightLayout.addWidget(self.databaseGroupBox)
+ self.defaultImageGroupBox = QtGui.QGroupBox(self.rightColumn)
+ self.defaultImageGroupBox.setObjectName(u'defaultImageGroupBox')
+ self.defaultImageLayout = QtGui.QFormLayout(self.defaultImageGroupBox)
+ self.defaultImageLayout.setObjectName(u'defaultImageLayout')
+ self.defaultColorLabel = QtGui.QLabel(self.defaultImageGroupBox)
+ self.defaultColorLabel.setObjectName(u'defaultColorLabel')
+ self.defaultColorButton = QtGui.QPushButton(self.defaultImageGroupBox)
+ self.defaultColorButton.setObjectName(u'defaultColorButton')
+ self.defaultImageLayout.addRow(self.defaultColorLabel,
+ self.defaultColorButton)
+ self.defaultFileLabel = QtGui.QLabel(self.defaultImageGroupBox)
+ self.defaultFileLabel.setObjectName(u'defaultFileLabel')
+ self.defaultFileEdit = QtGui.QLineEdit(self.defaultImageGroupBox)
+ self.defaultFileEdit.setObjectName(u'defaultFileEdit')
+ self.defaultBrowseButton = QtGui.QToolButton(self.defaultImageGroupBox)
+ self.defaultBrowseButton.setObjectName(u'defaultBrowseButton')
+ self.defaultBrowseButton.setIcon(
+ build_icon(u':/general/general_open.png'))
+ self.defaultFileLayout = QtGui.QHBoxLayout()
+ self.defaultFileLayout.setObjectName(u'defaultFileLayout')
+ self.defaultFileLayout.addWidget(self.defaultFileEdit)
+ self.defaultFileLayout.addWidget(self.defaultBrowseButton)
+ self.defaultImageLayout.addRow(self.defaultFileLabel,
+ self.defaultFileLayout)
+ self.rightLayout.addWidget(self.defaultImageGroupBox)
self.rightLayout.addStretch()
-# QtCore.QObject.connect(self.sharedCheckBox,
-# QtCore.SIGNAL(u'stateChanged(int)'), self.onSharedCheckBoxChanged)
+
+ QtCore.QObject.connect(self.defaultColorButton,
+ QtCore.SIGNAL(u'pressed()'), self.onDefaultColorButtonPressed)
+ QtCore.QObject.connect(self.defaultBrowseButton,
+ QtCore.SIGNAL(u'pressed()'), self.onDefaultBrowseButtonPressed)
def retranslateUi(self):
"""
@@ -129,14 +137,13 @@ class AdvancedTab(SettingsTab):
self.hideMouseGroupBox.setTitle(translate('OpenLP.AdvancedTab',
'Mouse Cursor'))
self.hideMouseCheckBox.setText(translate('OpenLP.AdvancedTab',
- 'Hide the mouse cursor when moved over the display window'))
-# self.sharedDirGroupBox.setTitle(
-# translate('AdvancedTab', 'Central Data Store'))
-# self.sharedCheckBox.setText(
-# translate('AdvancedTab', 'Enable a shared data location'))
-# self.sharedLabel.setText(translate('AdvancedTab', 'Store location:'))
-# self.sharedPushButton.setText(UiStrings.Browse)
-# self.databaseGroupBox.setTitle(translate('AdvancedTab', 'Databases'))
+ 'Hide mouse cursor when over display window'))
+ self.defaultImageGroupBox.setTitle(translate('OpenLP.AdvancedTab',
+ 'Default Image'))
+ self.defaultColorLabel.setText(translate('OpenLP.AdvancedTab',
+ 'Background color:'))
+ self.defaultFileLabel.setText(translate('OpenLP.AdvancedTab',
+ 'Image file:'))
def load(self):
"""
@@ -165,7 +172,14 @@ class AdvancedTab(SettingsTab):
QtCore.QVariant(True)).toBool())
self.hideMouseCheckBox.setChecked(
settings.value(u'hide mouse', QtCore.QVariant(False)).toBool())
+ self.default_color = settings.value(u'default color',
+ QtCore.QVariant(u'#ffffff')).toString()
+ self.defaultFileEdit.setText(settings.value(u'default image',
+ QtCore.QVariant(u':/graphics/openlp-splash-screen.png'))\
+ .toString())
settings.endGroup()
+ self.defaultColorButton.setStyleSheet(
+ u'background-color: %s' % self.default_color)
def save(self):
"""
@@ -185,12 +199,24 @@ class AdvancedTab(SettingsTab):
QtCore.QVariant(self.enableAutoCloseCheckBox.isChecked()))
settings.setValue(u'hide mouse',
QtCore.QVariant(self.hideMouseCheckBox.isChecked()))
+ settings.setValue(u'default color', self.default_color)
+ settings.setValue(u'default image', self.defaultFileEdit.text())
settings.endGroup()
-# def onSharedCheckBoxChanged(self, checked):
-# """
-# Enables the widgets to allow a shared data location
-# """
-# self.sharedLabel.setEnabled(checked)
-# self.sharedTextEdit.setEnabled(checked)
-# self.sharedPushButton.setEnabled(checked)
+ def onDefaultColorButtonPressed(self):
+ new_color = QtGui.QColorDialog.getColor(
+ QtGui.QColor(self.default_color), self)
+ if new_color.isValid():
+ self.default_color = new_color.name()
+ self.defaultColorButton.setStyleSheet(
+ u'background-color: %s' % self.default_color)
+
+ def onDefaultBrowseButtonPressed(self):
+ file_filters = u'%s;;%s (*.*) (*)' % (get_images_filter(),
+ UiStrings.AllFiles)
+ filename = QtGui.QFileDialog.getOpenFileName(self,
+ translate('OpenLP.AdvancedTab', 'Open File'), '',
+ file_filters)
+ if filename:
+ self.defaultFileEdit.setText(filename)
+ self.defaultFileEdit.setFocus()
diff --git a/openlp/core/ui/displaytagdialog.py b/openlp/core/ui/displaytagdialog.py
index ab3363058..edb8567cf 100644
--- a/openlp/core/ui/displaytagdialog.py
+++ b/openlp/core/ui/displaytagdialog.py
@@ -123,30 +123,30 @@ class Ui_DisplayTagDialog(object):
QtCore.QMetaObject.connectSlotsByName(displayTagDialog)
def retranslateUi(self, displayTagDialog):
- displayTagDialog.setWindowTitle(translate('OpenLP.displayTagForm',
+ displayTagDialog.setWindowTitle(translate('OpenLP.displayTagDialog',
'Configure Display Tags'))
self.editGroupBox.setTitle(
- translate('OpenLP.DisplayTagTab', 'Edit Selection'))
+ translate('OpenLP.DisplayTagDialog', 'Edit Selection'))
self.updatePushButton.setText(
- translate('OpenLP.DisplayTagTab', 'Update'))
+ translate('OpenLP.DisplayTagDialog', 'Update'))
self.descriptionLabel.setText(
- translate('OpenLP.DisplayTagTab', 'Description'))
- self.tagLabel.setText(translate('OpenLP.DisplayTagTab', 'Tag'))
+ translate('OpenLP.DisplayTagDialog', 'Description'))
+ self.tagLabel.setText(translate('OpenLP.DisplayTagDialog', 'Tag'))
self.startTagLabel.setText(
- translate('OpenLP.DisplayTagTab', 'Start tag'))
- self.endTagLabel.setText(translate('OpenLP.DisplayTagTab', 'End tag'))
+ translate('OpenLP.DisplayTagDialog', 'Start tag'))
+ self.endTagLabel.setText(translate('OpenLP.DisplayTagDialog', 'End tag'))
self.deletePushButton.setText(UiStrings.Delete)
self.defaultPushButton.setText(
- translate('OpenLP.DisplayTagTab', 'Default'))
+ translate('OpenLP.DisplayTagDialog', 'Default'))
self.newPushButton.setText(UiStrings.New)
self.tagTableWidget.horizontalHeaderItem(0).setText(
- translate('OpenLP.DisplayTagTab', 'Description'))
+ translate('OpenLP.DisplayTagDialog', 'Description'))
self.tagTableWidget.horizontalHeaderItem(1).setText(
- translate('OpenLP.DisplayTagTab', 'Tag id'))
+ translate('OpenLP.DisplayTagDialog', 'Tag id'))
self.tagTableWidget.horizontalHeaderItem(2).setText(
- translate('OpenLP.DisplayTagTab', 'Start Html'))
+ translate('OpenLP.DisplayTagDialog', 'Start Html'))
self.tagTableWidget.horizontalHeaderItem(3).setText(
- translate('OpenLP.DisplayTagTab', 'End Html'))
+ translate('OpenLP.DisplayTagDialog', 'End Html'))
self.tagTableWidget.setColumnWidth(0, 120)
self.tagTableWidget.setColumnWidth(1, 40)
self.tagTableWidget.setColumnWidth(2, 240)
diff --git a/openlp/core/ui/displaytagform.py b/openlp/core/ui/displaytagform.py
index f7a8e7740..fa05c578a 100644
--- a/openlp/core/ui/displaytagform.py
+++ b/openlp/core/ui/displaytagform.py
@@ -47,6 +47,7 @@ class DisplayTagForm(QtGui.QDialog, Ui_DisplayTagDialog):
"""
QtGui.QDialog.__init__(self, parent)
self.setupUi(self)
+ self.preLoad()
QtCore.QObject.connect(self.tagTableWidget,
QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onRowSelected)
QtCore.QObject.connect(self.defaultPushButton,
@@ -63,7 +64,18 @@ class DisplayTagForm(QtGui.QDialog, Ui_DisplayTagDialog):
Load Display and set field state.
"""
# Create initial copy from master
+ self.preLoad()
self._resetTable()
+ self.selected = -1
+ return QtGui.QDialog.exec_(self)
+
+ def preLoad(self):
+ """
+ Load the Tags from store so can be used in the system or used to
+ update the display. If Cancel was selected this is needed to reset the
+ dsiplay to the correct version.
+ """
+ # Initial Load of the Tags
DisplayTags.reset_html_tags()
user_expands = QtCore.QSettings().value(u'displayTags/html_tags',
QtCore.QVariant(u'')).toString()
@@ -74,37 +86,6 @@ class DisplayTagForm(QtGui.QDialog, Ui_DisplayTagDialog):
# If we have some user ones added them as well
for t in user_tags:
DisplayTags.add_html_tag(t)
- self.selected = -1
- self.load()
- return QtGui.QDialog.exec_(self)
-
- def load(self):
- """
- Load the form with data and set the initial state of the buttons
- """
- self.newPushButton.setEnabled(True)
- self.updatePushButton.setEnabled(False)
- self.deletePushButton.setEnabled(False)
- for linenumber, html in enumerate(DisplayTags.get_html_tags()):
- self.tagTableWidget.setRowCount(
- self.tagTableWidget.rowCount() + 1)
- self.tagTableWidget.setItem(linenumber, 0,
- QtGui.QTableWidgetItem(html[u'desc']))
- self.tagTableWidget.setItem(linenumber, 1,
- QtGui.QTableWidgetItem(self._strip(html[u'start tag'])))
- self.tagTableWidget.setItem(linenumber, 2,
- QtGui.QTableWidgetItem(html[u'start html']))
- self.tagTableWidget.setItem(linenumber, 3,
- QtGui.QTableWidgetItem(html[u'end html']))
- self.tagTableWidget.resizeRowsToContents()
- self.descriptionLineEdit.setText(u'')
- self.tagLineEdit.setText(u'')
- self.startTagLineEdit.setText(u'')
- self.endTagLineEdit.setText(u'')
- self.descriptionLineEdit.setEnabled(False)
- self.tagLineEdit.setEnabled(False)
- self.startTagLineEdit.setEnabled(False)
- self.endTagLineEdit.setEnabled(False)
def accept(self):
"""
@@ -223,6 +204,29 @@ class DisplayTagForm(QtGui.QDialog, Ui_DisplayTagDialog):
"""
self.tagTableWidget.clearContents()
self.tagTableWidget.setRowCount(0)
+ self.newPushButton.setEnabled(True)
+ self.updatePushButton.setEnabled(False)
+ self.deletePushButton.setEnabled(False)
+ for linenumber, html in enumerate(DisplayTags.get_html_tags()):
+ self.tagTableWidget.setRowCount(
+ self.tagTableWidget.rowCount() + 1)
+ self.tagTableWidget.setItem(linenumber, 0,
+ QtGui.QTableWidgetItem(html[u'desc']))
+ self.tagTableWidget.setItem(linenumber, 1,
+ QtGui.QTableWidgetItem(self._strip(html[u'start tag'])))
+ self.tagTableWidget.setItem(linenumber, 2,
+ QtGui.QTableWidgetItem(html[u'start html']))
+ self.tagTableWidget.setItem(linenumber, 3,
+ QtGui.QTableWidgetItem(html[u'end html']))
+ self.tagTableWidget.resizeRowsToContents()
+ self.descriptionLineEdit.setText(u'')
+ self.tagLineEdit.setText(u'')
+ self.startTagLineEdit.setText(u'')
+ self.endTagLineEdit.setText(u'')
+ self.descriptionLineEdit.setEnabled(False)
+ self.tagLineEdit.setEnabled(False)
+ self.startTagLineEdit.setEnabled(False)
+ self.endTagLineEdit.setEnabled(False)
def _strip(self, tag):
"""
diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py
index 90042f80b..91d61f1d7 100644
--- a/openlp/core/ui/maindisplay.py
+++ b/openlp/core/ui/maindisplay.py
@@ -132,14 +132,22 @@ class MainDisplay(DisplayWidget):
painter_image.begin(self.black)
painter_image.fillRect(self.black.rect(), QtCore.Qt.black)
# Build the initial frame.
+ image_file = QtCore.QSettings().value(u'advanced/default image',
+ QtCore.QVariant(u':/graphics/openlp-splash-screen.png'))\
+ .toString()
+ background_color = QtGui.QColor(QtCore.QSettings().value(
+ u'advanced/default color',
+ QtCore.QVariant(u'#ffffff')).toString())
+ if not background_color.isValid():
+ background_color = QtCore.Qt.white
+ splash_image = QtGui.QImage(image_file)
initialFrame = QtGui.QImage(
self.screens.current[u'size'].width(),
self.screens.current[u'size'].height(),
QtGui.QImage.Format_ARGB32_Premultiplied)
- splash_image = QtGui.QImage(u':/graphics/openlp-splash-screen.png')
painter_image = QtGui.QPainter()
painter_image.begin(initialFrame)
- painter_image.fillRect(initialFrame.rect(), QtCore.Qt.white)
+ painter_image.fillRect(initialFrame.rect(), background_color)
painter_image.drawImage(
(self.screens.current[u'size'].width() -
splash_image.width()) / 2,
diff --git a/openlp/core/ui/wizard.py b/openlp/core/ui/wizard.py
index 2960607e4..209f3f212 100644
--- a/openlp/core/ui/wizard.py
+++ b/openlp/core/ui/wizard.py
@@ -47,6 +47,7 @@ class WizardStrings(object):
CSV = u'CSV'
EW = u'EasyWorship'
ES = u'EasiSlides'
+ FP = u'Foilpresenter'
OL = u'OpenLyrics'
OS = u'OpenSong'
OSIS = u'OSIS'
diff --git a/openlp/plugins/media/lib/mediaitem.py b/openlp/plugins/media/lib/mediaitem.py
index 9f3f98636..8bf201180 100644
--- a/openlp/plugins/media/lib/mediaitem.py
+++ b/openlp/plugins/media/lib/mediaitem.py
@@ -61,8 +61,8 @@ class MediaMediaItem(MediaManagerItem):
self.onNewPrompt = translate('MediaPlugin.MediaItem', 'Select Media')
self.onNewFileMasks = unicode(translate('MediaPlugin.MediaItem',
'Videos (%s);;Audio (%s);;%s (*)')) % (
- u' '.join(self.parent.video_list),
- u' '.join(self.parent.audio_list), UiStrings.AllFiles)
+ u' '.join(self.parent.video_extensions_list),
+ u' '.join(self.parent.audio_extensions_list), UiStrings.AllFiles)
self.replaceAction.setText(UiStrings.ReplaceBG)
self.replaceAction.setToolTip(UiStrings.ReplaceLiveBG)
self.resetAction.setText(UiStrings.ResetBG)
diff --git a/openlp/plugins/media/mediaplugin.py b/openlp/plugins/media/mediaplugin.py
index 12887a76c..74a8f3f2e 100644
--- a/openlp/plugins/media/mediaplugin.py
+++ b/openlp/plugins/media/mediaplugin.py
@@ -45,28 +45,26 @@ class MediaPlugin(Plugin):
self.icon = build_icon(self.icon_path)
# passed with drag and drop messages
self.dnd_id = u'Media'
- self.audio_list = []
- self.video_list = []
+ self.audio_extensions_list = []
+ self.video_extensions_list = []
mimetypes.init()
for mimetype in Phonon.BackendCapabilities.availableMimeTypes():
mimetype = unicode(mimetype)
if mimetype.startswith(u'audio/'):
- self._addToList(self.audio_list, mimetype)
+ self._addToList(self.audio_extensions_list, mimetype)
elif mimetype.startswith(u'video/'):
- self._addToList(self.video_list, mimetype)
- log.info(u'MediaPlugin handles audio extensions: %s',
- u' '.join(self.audio_list))
- log.info(u'MediaPlugin handles video extensions: %s',
- u' '.join(self.video_list))
+ self._addToList(self.video_extensions_list, mimetype)
def _addToList(self, list, mimetype):
- # Is it a media type
+ # Add all extensions which mimetypes provides us for supported types.
extensions = mimetypes.guess_all_extensions(unicode(mimetype))
for extension in extensions:
ext = u'*%s' % extension
if ext not in list:
list.append(ext)
self.serviceManager.supportedSuffixes(extension[1:])
+ log.info(u'MediaPlugin: %s extensions: %s' % (mimetype,
+ u' '.join(extensions)))
def about(self):
about_text = translate('MediaPlugin', 'Media Plugin'
diff --git a/openlp/plugins/remotes/lib/httpserver.py b/openlp/plugins/remotes/lib/httpserver.py
index 6ec9476a8..7ced66103 100644
--- a/openlp/plugins/remotes/lib/httpserver.py
+++ b/openlp/plugins/remotes/lib/httpserver.py
@@ -68,11 +68,13 @@ class HttpServer(object):
"""
log.debug(u'Start TCP server')
port = QtCore.QSettings().value(
- self.parent.settingsSection + u'/remote port',
+ self.parent.settingsSection + u'/port',
QtCore.QVariant(4316)).toInt()[0]
+ address = QtCore.QSettings().value(
+ self.parent.settingsSection + u'/ip address',
+ QtCore.QVariant(u'0.0.0.0')).toString()
self.server = QtNetwork.QTcpServer()
- self.server.listen(QtNetwork.QHostAddress(QtNetwork.QHostAddress.Any),
- port)
+ self.server.listen(QtNetwork.QHostAddress(address), port)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'slidecontroller_live_changed'),
self.slide_change)
@@ -347,4 +349,4 @@ class HttpConnection(object):
log.debug(u'close socket')
self.socket.close()
self.socket = None
- self.parent.close_connection(self)
\ No newline at end of file
+ self.parent.close_connection(self)
diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py
index d7a575de4..16c0f9edb 100644
--- a/openlp/plugins/songs/forms/songimportform.py
+++ b/openlp/plugins/songs/forms/songimportform.py
@@ -146,6 +146,12 @@ class SongImportForm(OpenLPWizard):
QtCore.QObject.connect(self.songShowPlusRemoveButton,
QtCore.SIGNAL(u'clicked()'),
self.onSongShowPlusRemoveButtonClicked)
+ QtCore.QObject.connect(self.foilPresenterAddButton,
+ QtCore.SIGNAL(u'clicked()'),
+ self.onFoilPresenterAddButtonClicked)
+ QtCore.QObject.connect(self.foilPresenterRemoveButton,
+ QtCore.SIGNAL(u'clicked()'),
+ self.onFoilPresenterRemoveButtonClicked)
def addCustomPages(self):
"""
@@ -196,6 +202,8 @@ class SongImportForm(OpenLPWizard):
self.addFileSelectItem(u'songBeamer')
# Song Show Plus
self.addFileSelectItem(u'songShowPlus')
+ # Foilpresenter
+ self.addFileSelectItem(u'foilPresenter')
# Commented out for future use.
# self.addFileSelectItem(u'csv', u'CSV', single_select=True)
self.sourceLayout.addLayout(self.formatStack)
@@ -238,6 +246,8 @@ class SongImportForm(OpenLPWizard):
SongFormat.SongBeamer, WizardStrings.SB)
self.formatComboBox.setItemText(
SongFormat.SongShowPlus, WizardStrings.SSP)
+ self.formatComboBox.setItemText(
+ SongFormat.FoilPresenter, WizardStrings.FP)
# self.formatComboBox.setItemText(SongFormat.CSV, WizardStrings.CSV)
self.openLP2FilenameLabel.setText(
translate('SongsPlugin.ImportWizardForm', 'Filename:'))
@@ -297,6 +307,10 @@ class SongImportForm(OpenLPWizard):
translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
self.songShowPlusRemoveButton.setText(
translate('SongsPlugin.ImportWizardForm', 'Remove File(s)'))
+ self.foilPresenterAddButton.setText(
+ translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
+ self.foilPresenterRemoveButton.setText(
+ translate('SongsPlugin.ImportWizardForm', 'Remove File(s)'))
# self.csvFilenameLabel.setText(
# translate('SongsPlugin.ImportWizardForm', 'Filename:'))
# self.csvBrowseButton.setText(UiStrings.Browse)
@@ -394,6 +408,12 @@ class SongImportForm(OpenLPWizard):
WizardStrings.YouSpecifyFile % WizardStrings.SSP)
self.wordsOfWorshipAddButton.setFocus()
return False
+ elif source_format == SongFormat.FoilPresenter:
+ if self.foilPresenterFileListWidget.count() == 0:
+ critical_error_message_box(UiStrings.NFSp,
+ WizardStrings.YouSpecifyFile % WizardStrings.FP)
+ self.foilPresenterAddButton.setFocus()
+ return False
return True
elif self.currentPage() == self.progressPage:
return True
@@ -574,7 +594,7 @@ class SongImportForm(OpenLPWizard):
Remove selected SongBeamer files from the import list
"""
self.removeSelectedItems(self.songBeamerFileListWidget)
-
+
def onSongShowPlusAddButtonClicked(self):
"""
Get SongShow Plus song database files
@@ -591,6 +611,22 @@ class SongImportForm(OpenLPWizard):
"""
self.removeSelectedItems(self.songShowPlusFileListWidget)
+ def onFoilPresenterAddButtonClicked(self):
+ """
+ Get FoilPresenter song database files
+ """
+ self.getFiles(WizardStrings.OpenTypeFile % WizardStrings.FP,
+ self.foilPresenterFileListWidget, u'%s (*.foil)'
+ % translate('SongsPlugin.ImportWizardForm',
+ 'Foilpresenter Song Files')
+ )
+
+ def onFoilPresenterRemoveButtonClicked(self):
+ """
+ Remove selected FoilPresenter files from the import list
+ """
+ self.removeSelectedItems(self.foilPresenterFileListWidget)
+
def setDefaults(self):
"""
Set default form values for the song import wizard.
@@ -611,6 +647,7 @@ class SongImportForm(OpenLPWizard):
self.ewFilenameEdit.setText(u'')
self.songBeamerFileListWidget.clear()
self.songShowPlusFileListWidget.clear()
+ self.foilPresenterFileListWidget.clear()
#self.csvFilenameEdit.setText(u'')
def preWizard(self):
@@ -691,6 +728,11 @@ class SongImportForm(OpenLPWizard):
importer = self.plugin.importSongs(SongFormat.SongShowPlus,
filenames=self.getListOfFiles(self.songShowPlusFileListWidget)
)
+ elif source_format == SongFormat.FoilPresenter:
+ # Import Foilpresenter songs
+ importer = self.plugin.importSongs(SongFormat.FoilPresenter,
+ filenames=self.getListOfFiles(self.foilPresenterFileListWidget)
+ )
if importer.do_import():
self.progressLabel.setText(WizardStrings.FinishedImport)
else:
diff --git a/openlp/plugins/songs/lib/__init__.py b/openlp/plugins/songs/lib/__init__.py
index 95fae92a8..70a47a239 100644
--- a/openlp/plugins/songs/lib/__init__.py
+++ b/openlp/plugins/songs/lib/__init__.py
@@ -25,7 +25,10 @@
###############################################################################
from PyQt4 import QtGui
+
from openlp.core.lib import translate
+from db import Author
+from ui import SongStrings
class VerseType(object):
"""
@@ -241,6 +244,23 @@ def retrieve_windows_encoding(recommendation=None):
return None
return filter(lambda item: item[1] == choice[0], encodings)[0][0]
+def add_author_unknown(manager, song):
+ """
+ Add the default author *Author Unknown* to the song.
+
+ ``manager``
+ The song's manager.
+
+ ``song``
+ The song object.
+ """
+ name = SongStrings.AuthorUnknown
+ author = manager.get_object_filtered(Author, Author.display_name == name)
+ if author is None:
+ author = Author.populate(
+ display_name=name, last_name=u'', first_name=u'')
+ song.authors.append(author)
+
from xml import OpenLyrics, SongXML
from songstab import SongsTab
from mediaitem import SongMediaItem
diff --git a/openlp/plugins/songs/lib/foilpresenterimport.py b/openlp/plugins/songs/lib/foilpresenterimport.py
new file mode 100644
index 000000000..2eded332f
--- /dev/null
+++ b/openlp/plugins/songs/lib/foilpresenterimport.py
@@ -0,0 +1,576 @@
+ # -*- 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 XML of `Foilpresenter `_ songs is of the format::
+
+
+
+ 2004.6.18.18.44.37.0767
+ 2011.1.21.8.53.5
+
+ Above all
+
+ 1
+
+
+ 0
+ Notiz
+ 1.0
+
+ 0,0,0
+ 255,255,255
+
+
+ Standard
+ 0
+
+
+
+ 0
+ Verdana
+ 14
+ 0
+ 0
+ 0
+ 1
+ Above all powers, above all kings,
+ above all nature an all created things;
+ above all wisdom and all the ways of man,
+ You were here before the world began.
+ 1
+
+
+
+ Herr du bist maechtig.foil
+
+
+ Arial
+ 7
+ 3
+ 0
+ 1
+ 0
+ Text und Musik: Lenny LeBlanc/Paul Baloche
+
+
+
+ Feiert Jesus 3
+ 10
+
+
+
+ Worship
+
+
+"""
+
+import logging
+import re
+import os
+
+from lxml import etree, objectify
+
+from openlp.core.lib import translate
+from openlp.core.ui.wizard import WizardStrings
+from openlp.plugins.songs.lib import VerseType
+from openlp.plugins.songs.lib.songimport import SongImport
+from openlp.plugins.songs.lib.db import Author, Book, Song, Topic
+from openlp.plugins.songs.lib.xml import SongXML
+from openlp.plugins.songs.lib.ui import SongStrings
+
+log = logging.getLogger(__name__)
+
+class FoilPresenterImport(SongImport):
+ """
+ This provides the Foilpresenter import.
+ """
+ def __init__(self, master_manager, **kwargs):
+ """
+ Initialise the import.
+ """
+ log.debug(u'initialise FoilPresenterImport')
+ SongImport.__init__(self, master_manager, **kwargs)
+ self.FoilPresenter = FoilPresenter(self.manager)
+
+ def do_import(self):
+ """
+ Imports the songs.
+ """
+ self.import_wizard.progressBar.setMaximum(len(self.import_source))
+ parser = etree.XMLParser(remove_blank_text=True)
+ for file_path in self.import_source:
+ if self.stop_import_flag:
+ return False
+ self.import_wizard.incrementProgressBar(
+ WizardStrings.ImportingType % os.path.basename(file_path))
+ try:
+ parsed_file = etree.parse(file_path, parser)
+ xml = unicode(etree.tostring(parsed_file))
+ if self.FoilPresenter.xml_to_song(xml) is None:
+ log.debug(u'File could not be imported: %s' % file_path)
+ except etree.XMLSyntaxError:
+ log.exception(u'XML syntax error in file %s' % file_path)
+ return True
+
+class FoilPresenter(object):
+ """
+ This class represents the converter for Foilpresenter XML from a song.
+
+ As Foilpresenter has a rich set of different features, we cannot support
+ them all. The following features are supported by the :class:`Foilpresenter`
+
+ OpenPL does not support styletype and font attributes like "align, font,
+ textsize, bold, italic, underline"
+
+ **
+ This property is currently not supported.
+
+ **
+ As OpenLP does only support one title, the first titlestring becomes
+ title, all other titlestrings will be alternate titles
+
+ **
+ This property is not supported.
+
+ **
+ The ** property is fully supported.
+
+ **
+ This property is currently not supported.
+
+ **
+ This property is not supported.
+
+ **
+ The ** property is fully supported.
+
+ **
+ This property is not supported.
+
+ **
+ This property is not supported.
+
+ ** = verseOrder
+ OpenLP supports this property.
+
+ **
+ Only the attributes *key* and *text* are supported.
+
+ **
+ This property is not supported.
+
+ **
+ This property is not supported.
+
+ **
+ Only the attribute *text* is supported. => Done
+
+ ** = songbooks
+ As OpenLP does only support one songbook, we cannot consider more than
+ one songbook.
+
+ **
+ This property is not supported.
+
+ The tag ** is not support by foilpresenter, mostly the author is
+ named in the tag. We try to extract the authors from the
+ tag.
+
+ """
+ def __init__(self, manager):
+ self.manager = manager
+
+ def xml_to_song(self, xml):
+ """
+ Create and save a song from Foilpresenter format xml to the database.
+
+ ``xml``
+ The XML to parse (unicode).
+ """
+ # No xml get out of here.
+ if not xml:
+ return None
+ song = Song()
+ if xml[:5] == u'').sub(u'', xml)
+ xml = re.compile(u'').sub(u'', xml)
+ song_xml = objectify.fromstring(xml)
+ foilpresenterfolie = song_xml
+ self._process_copyright(foilpresenterfolie, song)
+ self._process_cclinumber(foilpresenterfolie, song)
+ self._process_titles(foilpresenterfolie, song)
+ # The verse order is processed with the lyrics!
+ self._process_lyrics(foilpresenterfolie, song)
+ self._process_comments(foilpresenterfolie, song)
+ self._process_authors(foilpresenterfolie, song)
+ self._process_songbooks(foilpresenterfolie, song)
+ self._process_topics(foilpresenterfolie, song)
+ self.manager.save_object(song)
+ return song.id
+
+ def _child(self, element):
+ """
+ This returns the text of an element as unicode string.
+
+ ``element``
+ The element.
+ """
+ if element is not None:
+ return unicode(element)
+ return u''
+
+ def _process_authors(self, foilpresenterfolie, song):
+ """
+ Adds the authors specified in the XML to the song.
+
+ ``foilpresenterfolie``
+ The property object (lxml.objectify.ObjectifiedElement).
+
+ ``song``
+ The song object.
+ """
+ authors = []
+ try:
+ copyright = self._child(foilpresenterfolie.copyright.text_)
+ except AttributeError:
+ copyright = None
+ if copyright:
+ strings = []
+ author_temp = []
+ if copyright.find(u'Copyright') != -1:
+ temp = copyright.partition(u'Copyright')
+ copyright = temp[0]
+ elif copyright.find(u'copyright') != -1:
+ temp = copyright.partition(u'copyright')
+ copyright = temp[0]
+ elif copyright.find(u'©') != -1:
+ temp = copyright.partition(u'©')
+ copyright = temp[0]
+ elif copyright.find(u'(c)') != -1:
+ temp = copyright.partition(u'(c)')
+ copyright = temp[0]
+ elif copyright.find(u'(C)') != -1:
+ temp = copyright.partition(u'(C)')
+ copyright = temp[0]
+ elif copyright.find(u'c)') != -1:
+ temp = copyright.partition(u'c)')
+ copyright = temp[0]
+ elif copyright.find(u'C)') != -1:
+ temp = copyright.partition(u'C)')
+ copyright = temp[0]
+ elif copyright.find(u'C:') != -1:
+ temp = copyright.partition(u'C:')
+ copyright = temp[0]
+ elif copyright.find(u'C,)') != -1:
+ temp = copyright.partition(u'C,)')
+ copyright = temp[0]
+ copyright = re.compile(u'\\n').sub(u' ', copyright)
+ copyright = re.compile(u'\(.*\)').sub(u'', copyright)
+ if copyright.find(u'Rechte') != -1:
+ temp = copyright.partition(u'Rechte')
+ copyright = temp[0]
+ markers = [u'Text +u\.?n?d? +Melodie[a-zA-Z0-9\,\. ]*:',
+ u'Text +u\.?n?d? +Musik', u'T & M', u'Melodie und Satz',
+ u'Text[a-zA-Z0-9\,\. ]*:', u'Melodie', u'Musik', u'Satz',
+ u'Weise', u'[dD]eutsch', u'[dD]t[\.\:]', u'Englisch',
+ u'[oO]riginal', u'Bearbeitung', u'[R|r]efrain']
+ for marker in markers:
+ copyright = re.compile(marker).sub(u'', copyright)
+ copyright = re.compile(u'(?<=) *:').sub(u'', copyright)
+ i = 0
+ x = 0
+ while i != 1:
+ if copyright.find(u'') != -1:
+ temp = copyright.partition(u'')
+ if (temp[0].strip() != u'') & (x > 0):
+ strings.append(temp[0])
+ copyright = temp[2]
+ x += 1
+ elif x > 0:
+ strings.append(copyright)
+ i = 1
+ else:
+ i = 1
+ for author in strings:
+ temp = re.split(u',(?=\D{2})|(?<=\D),|\/(?=\D{3,})|(?<=\D);',
+ author)
+ for tempx in temp:
+ author_temp.append(tempx)
+ for author in author_temp:
+ regex = u'^[\/,;\-\s]+|[\/,;\-\s]+$|'\
+ '\s*[0-9]{4}\s*[\-\/]?\s*([0-9]{4})?[\/,;\-\s]*$'
+ author = re.compile(regex).sub(u'', author)
+ author = re.compile(
+ u'[0-9]{1,2}\.\s?J(ahr)?h\.|um\s*$|vor\s*$').sub(u'',
+ author)
+ author = re.compile(u'[N|n]ach.*$').sub(u'', author)
+ author = author.strip()
+ if re.search(
+ u'\w+\.?\s+\w{3,}\s+[a|u]nd\s|\w+\.?\s+\w{3,}\s+&\s',
+ author, re.U) != None:
+ temp = re.split(u'\s[a|u]nd\s|\s&\s', author)
+ for tempx in temp:
+ tempx = tempx.strip()
+ authors.append(tempx)
+ elif (len(author) > 2):
+ authors.append(author)
+ if not authors:
+ authors.append(SongStrings.AuthorUnknownUnT)
+ for display_name in authors:
+ author = self.manager.get_object_filtered(Author,
+ Author.display_name == display_name)
+ if author is None:
+ # We need to create a new author, as the author does not exist.
+ author = Author.populate(display_name=display_name,
+ last_name = display_name.split(u' ')[-1],
+ first_name = u' '.join(display_name.split(u' ')[:-1]))
+ self.manager.save_object(author)
+ song.authors.append(author)
+
+ def _process_cclinumber(self, foilpresenterfolie, song):
+ """
+ Adds the CCLI number to the song.
+
+ ``foilpresenterfolie``
+ The property object (lxml.objectify.ObjectifiedElement).
+
+ ``song``
+ The song object.
+ """
+ try:
+ song.ccli_number = self._child(foilpresenterfolie.ccliid)
+ except AttributeError:
+ song.ccli_number = u''
+
+ def _process_comments(self, foilpresenterfolie, song):
+ """
+ Joins the comments specified in the XML and add it to the song.
+
+ ``foilpresenterfolie``
+ The property object (lxml.objectify.ObjectifiedElement).
+
+ ``song``
+ The song object.
+ """
+ try:
+ song.comments = self._child(foilpresenterfolie.notiz)
+ except AttributeError:
+ song.comments = u''
+
+ def _process_copyright(self, foilpresenterfolie, song):
+ """
+ Adds the copyright to the song.
+
+ ``foilpresenterfolie``
+ The property object (lxml.objectify.ObjectifiedElement).
+
+ ``song``
+ The song object.
+ """
+ try:
+ song.copyright = self._child(foilpresenterfolie.copyright.text_)
+ except AttributeError:
+ song.copyright = u''
+
+ def _process_lyrics(self, foilpresenterfolie, song):
+ """
+ Processes the verses and search_lyrics for the song.
+
+ ``foilpresenterfolie``
+ The foilpresenterfolie object (lxml.objectify.ObjectifiedElement).
+
+ ``song``
+ The song object.
+ """
+ sxml = SongXML()
+ search_text = u''
+ temp_verse_order = {}
+ temp_verse_order_backup = []
+ temp_verse_sort = []
+ temp_sortnr_backup = 1
+ temp_sortnr_liste = []
+ versenumber = {u'V': 1, u'C': 1, u'B': 1, u'E': 1, u'O': 1, u'I': 1,
+ u'P': 1}
+ for strophe in foilpresenterfolie.strophen.strophe:
+ text = self._child(strophe.text_)
+ verse_name = self._child(strophe.key)
+ children = strophe.getchildren()
+ sortnr = False
+ for child in children:
+ if child.tag == u'sortnr':
+ verse_sortnr = self._child(strophe.sortnr)
+ sortnr = True
+ # In older Version there is no sortnr, but we need one
+ if sortnr == False:
+ verse_sortnr = unicode(temp_sortnr_backup)
+ temp_sortnr_backup += 1
+ # Foilpresenter allows e. g. "Ref" or "1", but we need "C1" or "V1".
+ temp_sortnr_liste.append(verse_sortnr)
+ temp_verse_name = re.compile(u'[0-9].*').sub(u'', verse_name)
+ temp_verse_name = temp_verse_name[:3].lower()
+ if temp_verse_name == u'ref':
+ verse_type = u'C'
+ elif temp_verse_name == u'r':
+ verse_type = u'C'
+ elif temp_verse_name == u'':
+ verse_type = u'V'
+ elif temp_verse_name == u'v':
+ verse_type = u'V'
+ elif temp_verse_name == u'bri':
+ verse_type = u'B'
+ elif temp_verse_name == u'cod':
+ verse_type = u'E'
+ elif temp_verse_name == u'sch':
+ verse_type = u'E'
+ elif temp_verse_name == u'pre':
+ verse_type = u'P'
+ elif temp_verse_name == u'int':
+ verse_type = u'I'
+ else:
+ verse_type = u'O'
+ verse_number = re.compile(u'[a-zA-Z.+-_ ]*').sub(u'', verse_name)
+ verse_part = re.compile(u'[0-9]*').sub(u'', verse_name[1:])
+ # Foilpresenter allows e. g. "C", but we need "C1".
+ if not verse_number:
+ verse_number = unicode(versenumber[verse_type])
+ versenumber[verse_type] += 1
+ else:
+ # test if foilpresenter have the same versenumber two times with
+ # different parts raise the verse number
+ for value in temp_verse_order_backup:
+ if value == (u''.join((verse_type, verse_number))):
+ verse_number = unicode(int(verse_number) + 1)
+ verse_type_index = VerseType.from_tag(verse_type[0])
+ verse_type = VerseType.Names[verse_type_index]
+ temp_verse_order[verse_sortnr] = (u''.join((verse_type[0],
+ verse_number)))
+ temp_verse_order_backup.append(u''.join((verse_type[0],
+ verse_number)))
+ sxml.add_verse_to_lyrics(verse_type, verse_number, text)
+ search_text = search_text + text
+ song.search_lyrics = search_text.lower()
+ song.lyrics = unicode(sxml.extract_xml(), u'utf-8')
+ # Process verse order
+ verse_order = []
+ verse_strophenr = []
+ for strophennummer in foilpresenterfolie.reihenfolge.strophennummer:
+ verse_strophenr.append(strophennummer)
+ # Currently we do not support different "parts"!
+ if u'0' in temp_verse_order:
+ for vers in temp_verse_order_backup:
+ verse_order.append(vers)
+ else:
+ for number in verse_strophenr:
+ numberx = temp_sortnr_liste[int(number)]
+ verse_order.append(temp_verse_order[unicode(numberx)])
+ song.verse_order = u' '.join(verse_order)
+
+ def _process_songbooks(self, foilpresenterfolie, song):
+ """
+ Adds the song book and song number specified in the XML to the song.
+
+ ``foilpresenterfolie``
+ The property object (lxml.objectify.ObjectifiedElement).
+
+ ``song``
+ The song object.
+ """
+ song.song_book_id = 0
+ song.song_number = u''
+ try:
+ for bucheintrag in foilpresenterfolie.buch.bucheintrag:
+ bookname = self._child(bucheintrag.name)
+ if bookname:
+ book = self.manager.get_object_filtered(Book,
+ Book.name == bookname)
+ if book is None:
+ # We need to create a book, because it does not exist.
+ book = Book.populate(name=bookname, publisher=u'')
+ self.manager.save_object(book)
+ song.song_book_id = book.id
+ try:
+ if self._child(bucheintrag.nummer):
+ song.song_number = self._child(bucheintrag.nummer)
+ except AttributeError:
+ pass
+ # We only support one song book, so take the first one.
+ break
+ except AttributeError:
+ pass
+
+ def _process_titles(self, foilpresenterfolie, song):
+ """
+ Processes the titles specified in the song's XML.
+
+ ``foilpresenterfolie``
+ The property object (lxml.objectify.ObjectifiedElement).
+
+ ``song``
+ The song object.
+ """
+ for titelstring in foilpresenterfolie.titel.titelstring:
+ if not song.title:
+ song.title = self._child(titelstring)
+ song.search_title = unicode(song.title)
+ song.alternate_title = u''
+ else:
+ song.alternate_title = self._child(titelstring)
+ song.search_title += u'@' + song.alternate_title
+ song.search_title = re.sub(r'[\'"`,;:(){}?]+', u'',
+ unicode(song.search_title)).lower()
+
+ def _process_topics(self, foilpresenterfolie, song):
+ """
+ Adds the topics to the song.
+
+ ``foilpresenterfolie``
+ The property object (lxml.objectify.ObjectifiedElement).
+
+ ``song``
+ The song object.
+ """
+ try:
+ for name in foilpresenterfolie.kategorien.name:
+ topictext = self._child(name)
+ if topictext:
+ topic = self.manager.get_object_filtered(Topic,
+ Topic.name == topictext)
+ if topic is None:
+ # We need to create a topic, because it does not exist.
+ topic = Topic.populate(name=topictext)
+ self.manager.save_object(topic)
+ 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)
diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py
index 230dcd8d0..f3a64a998 100644
--- a/openlp/plugins/songs/lib/importer.py
+++ b/openlp/plugins/songs/lib/importer.py
@@ -35,6 +35,7 @@ from cclifileimport import CCLIFileImport
from ewimport import EasyWorshipSongImport
from songbeamerimport import SongBeamerImport
from songshowplusimport import SongShowPlusImport
+from foilpresenterimport import FoilPresenterImport
# Imports that might fail
try:
from olp1import import OpenLP1SongImport
@@ -72,7 +73,8 @@ class SongFormat(object):
EasyWorship = 9
SongBeamer = 10
SongShowPlus = 11
- #CSV = 12
+ FoilPresenter = 12
+ #CSV = 13
@staticmethod
def get_class(format):
@@ -106,6 +108,8 @@ class SongFormat(object):
return SongBeamerImport
elif format == SongFormat.SongShowPlus:
return SongShowPlusImport
+ elif format == SongFormat.FoilPresenter:
+ return FoilPresenterImport
return None
@staticmethod
@@ -125,7 +129,8 @@ class SongFormat(object):
SongFormat.EasiSlides,
SongFormat.EasyWorship,
SongFormat.SongBeamer,
- SongFormat.SongShowPlus
+ SongFormat.SongShowPlus,
+ SongFormat.FoilPresenter
]
@staticmethod
diff --git a/openlp/plugins/songs/lib/olpimport.py b/openlp/plugins/songs/lib/olpimport.py
index b3f03b951..fba518772 100644
--- a/openlp/plugins/songs/lib/olpimport.py
+++ b/openlp/plugins/songs/lib/olpimport.py
@@ -36,6 +36,7 @@ from sqlalchemy.orm.exc import UnmappedClassError
from openlp.core.lib import translate
from openlp.core.lib.db import BaseModel
+from openlp.plugins.songs.lib import add_author_unknown
from openlp.plugins.songs.lib.db import Author, Book, Song, Topic #, MediaFile
from songimport import SongImport
@@ -47,30 +48,35 @@ class OldAuthor(BaseModel):
"""
pass
+
class OldBook(BaseModel):
"""
Book model
"""
pass
+
class OldMediaFile(BaseModel):
"""
MediaFile model
"""
pass
+
class OldSong(BaseModel):
"""
Song model
"""
pass
+
class OldTopic(BaseModel):
"""
Topic model
"""
pass
+
class OpenLPSongImport(SongImport):
"""
The :class:`OpenLPSongImport` class provides OpenLP with the ability to
@@ -170,25 +176,18 @@ class OpenLPSongImport(SongImport):
new_song.comments = song.comments
new_song.theme_name = song.theme_name
new_song.ccli_number = song.ccli_number
- if song.authors:
- for author in song.authors:
- existing_author = self.manager.get_object_filtered(
- Author, Author.display_name == author.display_name)
- if existing_author:
- new_song.authors.append(existing_author)
- else:
- new_song.authors.append(Author.populate(
- first_name=author.first_name,
- last_name=author.last_name,
- display_name=author.display_name))
- else:
- au = self.manager.get_object_filtered(Author,
- Author.display_name == u'Author Unknown')
- if au:
- new_song.authors.append(au)
+ for author in song.authors:
+ existing_author = self.manager.get_object_filtered(
+ Author, Author.display_name == author.display_name)
+ if existing_author:
+ new_song.authors.append(existing_author)
else:
new_song.authors.append(Author.populate(
- display_name=u'Author Unknown'))
+ first_name=author.first_name,
+ last_name=author.last_name,
+ display_name=author.display_name))
+ if not new_song.authors:
+ add_author_unknown(self.manager, new_song)
if song.book:
existing_song_book = self.manager.get_object_filtered(
Book, Book.name == song.book.name)
diff --git a/openlp/plugins/songs/lib/songimport.py b/openlp/plugins/songs/lib/songimport.py
index 40be1675e..36f2e3504 100644
--- a/openlp/plugins/songs/lib/songimport.py
+++ b/openlp/plugins/songs/lib/songimport.py
@@ -29,7 +29,7 @@ import re
from PyQt4 import QtCore
from openlp.core.lib import Receiver, translate
-from openlp.plugins.songs.lib import VerseType
+from openlp.plugins.songs.lib import add_author_unknown, VerseType
from openlp.plugins.songs.lib.db import Song, Author, Topic, Book, MediaFile
from openlp.plugins.songs.lib.ui import SongStrings
from openlp.plugins.songs.lib.xml import SongXML
@@ -270,8 +270,6 @@ class SongImport(QtCore.QObject):
"""
All fields have been set to this song. Write the song to disk.
"""
- if not self.authors:
- self.authors.append(SongStrings.AuthorUnknownUnT)
log.info(u'committing song %s to database', self.title)
song = Song()
song.title = self.title
@@ -315,10 +313,13 @@ class SongImport(QtCore.QObject):
author = self.manager.get_object_filtered(Author,
Author.display_name == authortext)
if not author:
- author = Author.populate(display_name = authortext,
+ author = Author.populate(display_name=authortext,
last_name=authortext.split(u' ')[-1],
first_name=u' '.join(authortext.split(u' ')[:-1]))
song.authors.append(author)
+ # No author, add the default author.
+ if not song.authors:
+ add_author_unknown(self.manager, song)
for filename in self.media_files:
media_file = self.manager.get_object_filtered(MediaFile,
MediaFile.file_name == filename)
diff --git a/openlp/plugins/songs/lib/ui.py b/openlp/plugins/songs/lib/ui.py
index 65f473e63..6415c48c9 100644
--- a/openlp/plugins/songs/lib/ui.py
+++ b/openlp/plugins/songs/lib/ui.py
@@ -36,8 +36,7 @@ class SongStrings(object):
# These strings should need a good reason to be retranslated elsewhere.
Author = translate('OpenLP.Ui', 'Author', 'Singular')
Authors = translate('OpenLP.Ui', 'Authors', 'Plural')
- AuthorUnknown = translate('OpenLP.Ui', 'Author Unknown') # Used in the UI.
- AuthorUnknownUnT = u'Author Unknown' # Used to populate the database.
+ AuthorUnknown = u'Author Unknown' # Used to populate the database.
CopyrightSymbol = translate('OpenLP.Ui', '\xa9', 'Copyright symbol.')
SongBook = translate('OpenLP.Ui', 'Song Book', 'Singular')
SongBooks = translate('OpenLP.Ui', 'Song Books', 'Plural')
diff --git a/openlp/plugins/songs/lib/xml.py b/openlp/plugins/songs/lib/xml.py
index a552a42a1..8f5c35c0a 100644
--- a/openlp/plugins/songs/lib/xml.py
+++ b/openlp/plugins/songs/lib/xml.py
@@ -66,7 +66,7 @@ import re
from lxml import etree, objectify
-from openlp.plugins.songs.lib import VerseType
+from openlp.plugins.songs.lib import add_author_unknown, VerseType
from openlp.plugins.songs.lib.db import Author, Book, Song, Topic
from openlp.plugins.songs.lib.ui import SongStrings
@@ -374,8 +374,6 @@ class OpenLyrics(object):
display_name = self._text(author)
if display_name:
authors.append(display_name)
- if not authors:
- authors.append(SongStrings.AuthorUnknownUnT)
for display_name in authors:
author = self.manager.get_object_filtered(Author,
Author.display_name == display_name)
@@ -384,8 +382,8 @@ class OpenLyrics(object):
author = Author.populate(display_name=display_name,
last_name=display_name.split(u' ')[-1],
first_name=u' '.join(display_name.split(u' ')[:-1]))
- self.manager.save_object(author)
- song.authors.append(author)
+ if not song.authors:
+ add_author_unknown(self.manager, song)
def _process_cclinumber(self, properties, song):
"""
diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py
index bf33cd56e..609c1990d 100644
--- a/openlp/plugins/songs/songsplugin.py
+++ b/openlp/plugins/songs/songsplugin.py
@@ -32,7 +32,8 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import Plugin, StringContent, build_icon, translate
from openlp.core.lib.db import Manager
from openlp.core.lib.ui import UiStrings
-from openlp.plugins.songs.lib import SongMediaItem, SongsTab, SongXML
+from openlp.plugins.songs.lib import add_author_unknown, SongMediaItem, \
+ SongsTab, SongXML
from openlp.plugins.songs.lib.db import init_schema, Song
from openlp.plugins.songs.lib.importer import SongFormat
@@ -145,6 +146,9 @@ class SongsPlugin(Plugin):
counter = 0
for song in songs:
counter += 1
+ # The song does not have any author, add one.
+ if not song.authors:
+ add_author_unknown(self.manager, song)
if song.title is None:
song.title = u''
if song.alternate_title is None: