This commit is contained in:
Andreas Preikschat 2011-02-24 13:53:02 +01:00
commit 2b41cf545a
18 changed files with 816 additions and 134 deletions

View File

@ -63,7 +63,6 @@ from splashscreen import SplashScreen
from generaltab import GeneralTab from generaltab import GeneralTab
from themestab import ThemesTab from themestab import ThemesTab
from advancedtab import AdvancedTab from advancedtab import AdvancedTab
from displaytagtab import DisplayTagTab
from aboutform import AboutForm from aboutform import AboutForm
from pluginform import PluginForm from pluginform import PluginForm
from settingsform import SettingsForm from settingsform import SettingsForm

View File

@ -28,8 +28,9 @@ The :mod:`advancedtab` provides an advanced settings facility.
""" """
from PyQt4 import QtCore, QtGui 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.lib.ui import UiStrings
from openlp.core.utils import get_images_filter
class AdvancedTab(SettingsTab): class AdvancedTab(SettingsTab):
""" """
@ -41,6 +42,8 @@ class AdvancedTab(SettingsTab):
Initialise the settings tab Initialise the settings tab
""" """
SettingsTab.__init__(self, u'Advanced') SettingsTab.__init__(self, u'Advanced')
self.default_image = u':/graphics/openlp-splash-screen.png'
self.default_color = u'#ffffff'
def setupUi(self): def setupUi(self):
""" """
@ -81,33 +84,38 @@ class AdvancedTab(SettingsTab):
self.hideMouseCheckBox.setObjectName(u'hideMouseCheckBox') self.hideMouseCheckBox.setObjectName(u'hideMouseCheckBox')
self.hideMouseLayout.addWidget(self.hideMouseCheckBox) self.hideMouseLayout.addWidget(self.hideMouseCheckBox)
self.leftLayout.addWidget(self.hideMouseGroupBox) 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.leftLayout.addStretch()
# self.databaseGroupBox = QtGui.QGroupBox(self.rightColumn) self.defaultImageGroupBox = QtGui.QGroupBox(self.rightColumn)
# self.databaseGroupBox.setObjectName(u'databaseGroupBox') self.defaultImageGroupBox.setObjectName(u'defaultImageGroupBox')
# self.databaseGroupBox.setEnabled(False) self.defaultImageLayout = QtGui.QFormLayout(self.defaultImageGroupBox)
# self.databaseLayout = QtGui.QVBoxLayout(self.databaseGroupBox) self.defaultImageLayout.setObjectName(u'defaultImageLayout')
# self.rightLayout.addWidget(self.databaseGroupBox) 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() 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): def retranslateUi(self):
""" """
@ -129,14 +137,13 @@ class AdvancedTab(SettingsTab):
self.hideMouseGroupBox.setTitle(translate('OpenLP.AdvancedTab', self.hideMouseGroupBox.setTitle(translate('OpenLP.AdvancedTab',
'Mouse Cursor')) 'Mouse Cursor'))
self.hideMouseCheckBox.setText(translate('OpenLP.AdvancedTab', self.hideMouseCheckBox.setText(translate('OpenLP.AdvancedTab',
'Hide the mouse cursor when moved over the display window')) 'Hide mouse cursor when over display window'))
# self.sharedDirGroupBox.setTitle( self.defaultImageGroupBox.setTitle(translate('OpenLP.AdvancedTab',
# translate('AdvancedTab', 'Central Data Store')) 'Default Image'))
# self.sharedCheckBox.setText( self.defaultColorLabel.setText(translate('OpenLP.AdvancedTab',
# translate('AdvancedTab', 'Enable a shared data location')) 'Background color:'))
# self.sharedLabel.setText(translate('AdvancedTab', 'Store location:')) self.defaultFileLabel.setText(translate('OpenLP.AdvancedTab',
# self.sharedPushButton.setText(UiStrings.Browse) 'Image file:'))
# self.databaseGroupBox.setTitle(translate('AdvancedTab', 'Databases'))
def load(self): def load(self):
""" """
@ -165,7 +172,14 @@ class AdvancedTab(SettingsTab):
QtCore.QVariant(True)).toBool()) QtCore.QVariant(True)).toBool())
self.hideMouseCheckBox.setChecked( self.hideMouseCheckBox.setChecked(
settings.value(u'hide mouse', QtCore.QVariant(False)).toBool()) 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() settings.endGroup()
self.defaultColorButton.setStyleSheet(
u'background-color: %s' % self.default_color)
def save(self): def save(self):
""" """
@ -185,12 +199,24 @@ class AdvancedTab(SettingsTab):
QtCore.QVariant(self.enableAutoCloseCheckBox.isChecked())) QtCore.QVariant(self.enableAutoCloseCheckBox.isChecked()))
settings.setValue(u'hide mouse', settings.setValue(u'hide mouse',
QtCore.QVariant(self.hideMouseCheckBox.isChecked())) QtCore.QVariant(self.hideMouseCheckBox.isChecked()))
settings.setValue(u'default color', self.default_color)
settings.setValue(u'default image', self.defaultFileEdit.text())
settings.endGroup() settings.endGroup()
# def onSharedCheckBoxChanged(self, checked): def onDefaultColorButtonPressed(self):
# """ new_color = QtGui.QColorDialog.getColor(
# Enables the widgets to allow a shared data location QtGui.QColor(self.default_color), self)
# """ if new_color.isValid():
# self.sharedLabel.setEnabled(checked) self.default_color = new_color.name()
# self.sharedTextEdit.setEnabled(checked) self.defaultColorButton.setStyleSheet(
# self.sharedPushButton.setEnabled(checked) 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()

View File

@ -123,30 +123,30 @@ class Ui_DisplayTagDialog(object):
QtCore.QMetaObject.connectSlotsByName(displayTagDialog) QtCore.QMetaObject.connectSlotsByName(displayTagDialog)
def retranslateUi(self, displayTagDialog): def retranslateUi(self, displayTagDialog):
displayTagDialog.setWindowTitle(translate('OpenLP.displayTagForm', displayTagDialog.setWindowTitle(translate('OpenLP.displayTagDialog',
'Configure Display Tags')) 'Configure Display Tags'))
self.editGroupBox.setTitle( self.editGroupBox.setTitle(
translate('OpenLP.DisplayTagTab', 'Edit Selection')) translate('OpenLP.DisplayTagDialog', 'Edit Selection'))
self.updatePushButton.setText( self.updatePushButton.setText(
translate('OpenLP.DisplayTagTab', 'Update')) translate('OpenLP.DisplayTagDialog', 'Update'))
self.descriptionLabel.setText( self.descriptionLabel.setText(
translate('OpenLP.DisplayTagTab', 'Description')) translate('OpenLP.DisplayTagDialog', 'Description'))
self.tagLabel.setText(translate('OpenLP.DisplayTagTab', 'Tag')) self.tagLabel.setText(translate('OpenLP.DisplayTagDialog', 'Tag'))
self.startTagLabel.setText( self.startTagLabel.setText(
translate('OpenLP.DisplayTagTab', 'Start tag')) translate('OpenLP.DisplayTagDialog', 'Start tag'))
self.endTagLabel.setText(translate('OpenLP.DisplayTagTab', 'End tag')) self.endTagLabel.setText(translate('OpenLP.DisplayTagDialog', 'End tag'))
self.deletePushButton.setText(UiStrings.Delete) self.deletePushButton.setText(UiStrings.Delete)
self.defaultPushButton.setText( self.defaultPushButton.setText(
translate('OpenLP.DisplayTagTab', 'Default')) translate('OpenLP.DisplayTagDialog', 'Default'))
self.newPushButton.setText(UiStrings.New) self.newPushButton.setText(UiStrings.New)
self.tagTableWidget.horizontalHeaderItem(0).setText( self.tagTableWidget.horizontalHeaderItem(0).setText(
translate('OpenLP.DisplayTagTab', 'Description')) translate('OpenLP.DisplayTagDialog', 'Description'))
self.tagTableWidget.horizontalHeaderItem(1).setText( self.tagTableWidget.horizontalHeaderItem(1).setText(
translate('OpenLP.DisplayTagTab', 'Tag id')) translate('OpenLP.DisplayTagDialog', 'Tag id'))
self.tagTableWidget.horizontalHeaderItem(2).setText( self.tagTableWidget.horizontalHeaderItem(2).setText(
translate('OpenLP.DisplayTagTab', 'Start Html')) translate('OpenLP.DisplayTagDialog', 'Start Html'))
self.tagTableWidget.horizontalHeaderItem(3).setText( self.tagTableWidget.horizontalHeaderItem(3).setText(
translate('OpenLP.DisplayTagTab', 'End Html')) translate('OpenLP.DisplayTagDialog', 'End Html'))
self.tagTableWidget.setColumnWidth(0, 120) self.tagTableWidget.setColumnWidth(0, 120)
self.tagTableWidget.setColumnWidth(1, 40) self.tagTableWidget.setColumnWidth(1, 40)
self.tagTableWidget.setColumnWidth(2, 240) self.tagTableWidget.setColumnWidth(2, 240)

View File

@ -47,6 +47,7 @@ class DisplayTagForm(QtGui.QDialog, Ui_DisplayTagDialog):
""" """
QtGui.QDialog.__init__(self, parent) QtGui.QDialog.__init__(self, parent)
self.setupUi(self) self.setupUi(self)
self.preLoad()
QtCore.QObject.connect(self.tagTableWidget, QtCore.QObject.connect(self.tagTableWidget,
QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onRowSelected) QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onRowSelected)
QtCore.QObject.connect(self.defaultPushButton, QtCore.QObject.connect(self.defaultPushButton,
@ -63,7 +64,18 @@ class DisplayTagForm(QtGui.QDialog, Ui_DisplayTagDialog):
Load Display and set field state. Load Display and set field state.
""" """
# Create initial copy from master # Create initial copy from master
self.preLoad()
self._resetTable() 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() DisplayTags.reset_html_tags()
user_expands = QtCore.QSettings().value(u'displayTags/html_tags', user_expands = QtCore.QSettings().value(u'displayTags/html_tags',
QtCore.QVariant(u'')).toString() QtCore.QVariant(u'')).toString()
@ -74,37 +86,6 @@ class DisplayTagForm(QtGui.QDialog, Ui_DisplayTagDialog):
# If we have some user ones added them as well # If we have some user ones added them as well
for t in user_tags: for t in user_tags:
DisplayTags.add_html_tag(t) 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): def accept(self):
""" """
@ -223,6 +204,29 @@ class DisplayTagForm(QtGui.QDialog, Ui_DisplayTagDialog):
""" """
self.tagTableWidget.clearContents() self.tagTableWidget.clearContents()
self.tagTableWidget.setRowCount(0) 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): def _strip(self, tag):
""" """

View File

@ -132,14 +132,22 @@ class MainDisplay(DisplayWidget):
painter_image.begin(self.black) painter_image.begin(self.black)
painter_image.fillRect(self.black.rect(), QtCore.Qt.black) painter_image.fillRect(self.black.rect(), QtCore.Qt.black)
# Build the initial frame. # 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( initialFrame = QtGui.QImage(
self.screens.current[u'size'].width(), self.screens.current[u'size'].width(),
self.screens.current[u'size'].height(), self.screens.current[u'size'].height(),
QtGui.QImage.Format_ARGB32_Premultiplied) QtGui.QImage.Format_ARGB32_Premultiplied)
splash_image = QtGui.QImage(u':/graphics/openlp-splash-screen.png')
painter_image = QtGui.QPainter() painter_image = QtGui.QPainter()
painter_image.begin(initialFrame) painter_image.begin(initialFrame)
painter_image.fillRect(initialFrame.rect(), QtCore.Qt.white) painter_image.fillRect(initialFrame.rect(), background_color)
painter_image.drawImage( painter_image.drawImage(
(self.screens.current[u'size'].width() - (self.screens.current[u'size'].width() -
splash_image.width()) / 2, splash_image.width()) / 2,

View File

@ -47,6 +47,7 @@ class WizardStrings(object):
CSV = u'CSV' CSV = u'CSV'
EW = u'EasyWorship' EW = u'EasyWorship'
ES = u'EasiSlides' ES = u'EasiSlides'
FP = u'Foilpresenter'
OL = u'OpenLyrics' OL = u'OpenLyrics'
OS = u'OpenSong' OS = u'OpenSong'
OSIS = u'OSIS' OSIS = u'OSIS'

View File

@ -61,8 +61,8 @@ class MediaMediaItem(MediaManagerItem):
self.onNewPrompt = translate('MediaPlugin.MediaItem', 'Select Media') self.onNewPrompt = translate('MediaPlugin.MediaItem', 'Select Media')
self.onNewFileMasks = unicode(translate('MediaPlugin.MediaItem', self.onNewFileMasks = unicode(translate('MediaPlugin.MediaItem',
'Videos (%s);;Audio (%s);;%s (*)')) % ( 'Videos (%s);;Audio (%s);;%s (*)')) % (
u' '.join(self.parent.video_list), u' '.join(self.parent.video_extensions_list),
u' '.join(self.parent.audio_list), UiStrings.AllFiles) u' '.join(self.parent.audio_extensions_list), UiStrings.AllFiles)
self.replaceAction.setText(UiStrings.ReplaceBG) self.replaceAction.setText(UiStrings.ReplaceBG)
self.replaceAction.setToolTip(UiStrings.ReplaceLiveBG) self.replaceAction.setToolTip(UiStrings.ReplaceLiveBG)
self.resetAction.setText(UiStrings.ResetBG) self.resetAction.setText(UiStrings.ResetBG)

View File

@ -45,28 +45,26 @@ class MediaPlugin(Plugin):
self.icon = build_icon(self.icon_path) self.icon = build_icon(self.icon_path)
# passed with drag and drop messages # passed with drag and drop messages
self.dnd_id = u'Media' self.dnd_id = u'Media'
self.audio_list = [] self.audio_extensions_list = []
self.video_list = [] self.video_extensions_list = []
mimetypes.init() mimetypes.init()
for mimetype in Phonon.BackendCapabilities.availableMimeTypes(): for mimetype in Phonon.BackendCapabilities.availableMimeTypes():
mimetype = unicode(mimetype) mimetype = unicode(mimetype)
if mimetype.startswith(u'audio/'): if mimetype.startswith(u'audio/'):
self._addToList(self.audio_list, mimetype) self._addToList(self.audio_extensions_list, mimetype)
elif mimetype.startswith(u'video/'): elif mimetype.startswith(u'video/'):
self._addToList(self.video_list, mimetype) self._addToList(self.video_extensions_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))
def _addToList(self, 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)) extensions = mimetypes.guess_all_extensions(unicode(mimetype))
for extension in extensions: for extension in extensions:
ext = u'*%s' % extension ext = u'*%s' % extension
if ext not in list: if ext not in list:
list.append(ext) list.append(ext)
self.serviceManager.supportedSuffixes(extension[1:]) self.serviceManager.supportedSuffixes(extension[1:])
log.info(u'MediaPlugin: %s extensions: %s' % (mimetype,
u' '.join(extensions)))
def about(self): def about(self):
about_text = translate('MediaPlugin', '<strong>Media Plugin</strong>' about_text = translate('MediaPlugin', '<strong>Media Plugin</strong>'

View File

@ -68,11 +68,13 @@ class HttpServer(object):
""" """
log.debug(u'Start TCP server') log.debug(u'Start TCP server')
port = QtCore.QSettings().value( port = QtCore.QSettings().value(
self.parent.settingsSection + u'/remote port', self.parent.settingsSection + u'/port',
QtCore.QVariant(4316)).toInt()[0] 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 = QtNetwork.QTcpServer()
self.server.listen(QtNetwork.QHostAddress(QtNetwork.QHostAddress.Any), self.server.listen(QtNetwork.QHostAddress(address), port)
port)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'slidecontroller_live_changed'), QtCore.SIGNAL(u'slidecontroller_live_changed'),
self.slide_change) self.slide_change)
@ -347,4 +349,4 @@ class HttpConnection(object):
log.debug(u'close socket') log.debug(u'close socket')
self.socket.close() self.socket.close()
self.socket = None self.socket = None
self.parent.close_connection(self) self.parent.close_connection(self)

View File

@ -146,6 +146,12 @@ class SongImportForm(OpenLPWizard):
QtCore.QObject.connect(self.songShowPlusRemoveButton, QtCore.QObject.connect(self.songShowPlusRemoveButton,
QtCore.SIGNAL(u'clicked()'), QtCore.SIGNAL(u'clicked()'),
self.onSongShowPlusRemoveButtonClicked) 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): def addCustomPages(self):
""" """
@ -196,6 +202,8 @@ class SongImportForm(OpenLPWizard):
self.addFileSelectItem(u'songBeamer') self.addFileSelectItem(u'songBeamer')
# Song Show Plus # Song Show Plus
self.addFileSelectItem(u'songShowPlus') self.addFileSelectItem(u'songShowPlus')
# Foilpresenter
self.addFileSelectItem(u'foilPresenter')
# Commented out for future use. # Commented out for future use.
# self.addFileSelectItem(u'csv', u'CSV', single_select=True) # self.addFileSelectItem(u'csv', u'CSV', single_select=True)
self.sourceLayout.addLayout(self.formatStack) self.sourceLayout.addLayout(self.formatStack)
@ -238,6 +246,8 @@ class SongImportForm(OpenLPWizard):
SongFormat.SongBeamer, WizardStrings.SB) SongFormat.SongBeamer, WizardStrings.SB)
self.formatComboBox.setItemText( self.formatComboBox.setItemText(
SongFormat.SongShowPlus, WizardStrings.SSP) SongFormat.SongShowPlus, WizardStrings.SSP)
self.formatComboBox.setItemText(
SongFormat.FoilPresenter, WizardStrings.FP)
# self.formatComboBox.setItemText(SongFormat.CSV, WizardStrings.CSV) # self.formatComboBox.setItemText(SongFormat.CSV, WizardStrings.CSV)
self.openLP2FilenameLabel.setText( self.openLP2FilenameLabel.setText(
translate('SongsPlugin.ImportWizardForm', 'Filename:')) translate('SongsPlugin.ImportWizardForm', 'Filename:'))
@ -297,6 +307,10 @@ class SongImportForm(OpenLPWizard):
translate('SongsPlugin.ImportWizardForm', 'Add Files...')) translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
self.songShowPlusRemoveButton.setText( self.songShowPlusRemoveButton.setText(
translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) 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( # self.csvFilenameLabel.setText(
# translate('SongsPlugin.ImportWizardForm', 'Filename:')) # translate('SongsPlugin.ImportWizardForm', 'Filename:'))
# self.csvBrowseButton.setText(UiStrings.Browse) # self.csvBrowseButton.setText(UiStrings.Browse)
@ -394,6 +408,12 @@ class SongImportForm(OpenLPWizard):
WizardStrings.YouSpecifyFile % WizardStrings.SSP) WizardStrings.YouSpecifyFile % WizardStrings.SSP)
self.wordsOfWorshipAddButton.setFocus() self.wordsOfWorshipAddButton.setFocus()
return False 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 return True
elif self.currentPage() == self.progressPage: elif self.currentPage() == self.progressPage:
return True return True
@ -574,7 +594,7 @@ class SongImportForm(OpenLPWizard):
Remove selected SongBeamer files from the import list Remove selected SongBeamer files from the import list
""" """
self.removeSelectedItems(self.songBeamerFileListWidget) self.removeSelectedItems(self.songBeamerFileListWidget)
def onSongShowPlusAddButtonClicked(self): def onSongShowPlusAddButtonClicked(self):
""" """
Get SongShow Plus song database files Get SongShow Plus song database files
@ -591,6 +611,22 @@ class SongImportForm(OpenLPWizard):
""" """
self.removeSelectedItems(self.songShowPlusFileListWidget) 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): def setDefaults(self):
""" """
Set default form values for the song import wizard. Set default form values for the song import wizard.
@ -611,6 +647,7 @@ class SongImportForm(OpenLPWizard):
self.ewFilenameEdit.setText(u'') self.ewFilenameEdit.setText(u'')
self.songBeamerFileListWidget.clear() self.songBeamerFileListWidget.clear()
self.songShowPlusFileListWidget.clear() self.songShowPlusFileListWidget.clear()
self.foilPresenterFileListWidget.clear()
#self.csvFilenameEdit.setText(u'') #self.csvFilenameEdit.setText(u'')
def preWizard(self): def preWizard(self):
@ -691,6 +728,11 @@ class SongImportForm(OpenLPWizard):
importer = self.plugin.importSongs(SongFormat.SongShowPlus, importer = self.plugin.importSongs(SongFormat.SongShowPlus,
filenames=self.getListOfFiles(self.songShowPlusFileListWidget) 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(): if importer.do_import():
self.progressLabel.setText(WizardStrings.FinishedImport) self.progressLabel.setText(WizardStrings.FinishedImport)
else: else:

View File

@ -25,7 +25,10 @@
############################################################################### ###############################################################################
from PyQt4 import QtGui from PyQt4 import QtGui
from openlp.core.lib import translate from openlp.core.lib import translate
from db import Author
from ui import SongStrings
class VerseType(object): class VerseType(object):
""" """
@ -241,6 +244,23 @@ def retrieve_windows_encoding(recommendation=None):
return None return None
return filter(lambda item: item[1] == choice[0], encodings)[0][0] 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 xml import OpenLyrics, SongXML
from songstab import SongsTab from songstab import SongsTab
from mediaitem import SongMediaItem from mediaitem import SongMediaItem

View File

@ -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 <http://foilpresenter.de/>`_ songs is of the format::
<?xml version="1.0" encoding="UTF-8"?>
<foilpresenterfolie version="00300.000092">
<id>2004.6.18.18.44.37.0767</id>
<lastchanged>2011.1.21.8.53.5</lastchanged>
<titel>
<titelstring>Above all</titelstring>
</titel>
<sprache>1</sprache>
<ccliid></ccliid>
<tonart></tonart>
<valign>0</valign>
<notiz>Notiz</notiz>
<versionsinfo>1.0</versionsinfo>
<farben>
<cback>0,0,0</cback>
<ctext>255,255,255</ctext>
</farben>
<reihenfolge>
<name>Standard</name>
<strophennummer>0</strophennummer>
</reihenfolge>
<strophen>
<strophe>
<align>0</align>
<font>Verdana</font>
<textsize>14</textsize>
<bold>0</bold>
<italic>0</italic>
<underline>0</underline>
<key>1</key>
<text>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.</text>
<sortnr>1</sortnr>
</strophe>
</strophen>
<verkn>
<filename>Herr du bist maechtig.foil</filename>
</verkn>
<copyright>
<font>Arial</font>
<textsize>7</textsize>
<anzeigedauer>3</anzeigedauer>
<bold>0</bold>
<italic>1</italic>
<underline>0</underline>
<text>Text und Musik: Lenny LeBlanc/Paul Baloche</text>
</copyright>
<buch>
<bucheintrag>
<name>Feiert Jesus 3</name>
<nummer>10</nummer>
</bucheintrag>
</buch>
<kategorien>
<name>Worship</name>
</kategorien>
</foilpresenterfolie>
"""
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"
*<lastchanged>*
This property is currently not supported.
*<title>*
As OpenLP does only support one title, the first titlestring becomes
title, all other titlestrings will be alternate titles
*<sprache>*
This property is not supported.
*<ccliid>*
The *<ccliid>* property is fully supported.
*<tonart>*
This property is currently not supported.
*<valign>*
This property is not supported.
*<notiz>*
The *<notiz>* property is fully supported.
*<versionsinfo>*
This property is not supported.
*<farben>*
This property is not supported.
*<reihenfolge>* = verseOrder
OpenLP supports this property.
*<strophen>*
Only the attributes *key* and *text* are supported.
*<verkn>*
This property is not supported.
*<verkn>*
This property is not supported.
*<copyright>*
Only the attribute *text* is supported. => Done
*<buch>* = songbooks
As OpenLP does only support one songbook, we cannot consider more than
one songbook.
*<kategorien>*
This property is not supported.
The tag *<author>* is not support by foilpresenter, mostly the author is
named in the <copyright> tag. We try to extract the authors from the
<copyright> 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'<?xml':
xml = xml[38:]
# Because "text" seems to be an reserverd word, we have to recompile it.
xml = re.compile(u'<text>').sub(u'<text_>', xml)
xml = re.compile(u'</text>').sub(u'</text_>', 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'<marker>', copyright)
copyright = re.compile(u'(?<=<marker>) *:').sub(u'', copyright)
i = 0
x = 0
while i != 1:
if copyright.find(u'<marker>') != -1:
temp = copyright.partition(u'<marker>')
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)

View File

@ -35,6 +35,7 @@ from cclifileimport import CCLIFileImport
from ewimport import EasyWorshipSongImport from ewimport import EasyWorshipSongImport
from songbeamerimport import SongBeamerImport from songbeamerimport import SongBeamerImport
from songshowplusimport import SongShowPlusImport from songshowplusimport import SongShowPlusImport
from foilpresenterimport import FoilPresenterImport
# Imports that might fail # Imports that might fail
try: try:
from olp1import import OpenLP1SongImport from olp1import import OpenLP1SongImport
@ -72,7 +73,8 @@ class SongFormat(object):
EasyWorship = 9 EasyWorship = 9
SongBeamer = 10 SongBeamer = 10
SongShowPlus = 11 SongShowPlus = 11
#CSV = 12 FoilPresenter = 12
#CSV = 13
@staticmethod @staticmethod
def get_class(format): def get_class(format):
@ -106,6 +108,8 @@ class SongFormat(object):
return SongBeamerImport return SongBeamerImport
elif format == SongFormat.SongShowPlus: elif format == SongFormat.SongShowPlus:
return SongShowPlusImport return SongShowPlusImport
elif format == SongFormat.FoilPresenter:
return FoilPresenterImport
return None return None
@staticmethod @staticmethod
@ -125,7 +129,8 @@ class SongFormat(object):
SongFormat.EasiSlides, SongFormat.EasiSlides,
SongFormat.EasyWorship, SongFormat.EasyWorship,
SongFormat.SongBeamer, SongFormat.SongBeamer,
SongFormat.SongShowPlus SongFormat.SongShowPlus,
SongFormat.FoilPresenter
] ]
@staticmethod @staticmethod

View File

@ -36,6 +36,7 @@ from sqlalchemy.orm.exc import UnmappedClassError
from openlp.core.lib import translate from openlp.core.lib import translate
from openlp.core.lib.db import BaseModel 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 openlp.plugins.songs.lib.db import Author, Book, Song, Topic #, MediaFile
from songimport import SongImport from songimport import SongImport
@ -47,30 +48,35 @@ class OldAuthor(BaseModel):
""" """
pass pass
class OldBook(BaseModel): class OldBook(BaseModel):
""" """
Book model Book model
""" """
pass pass
class OldMediaFile(BaseModel): class OldMediaFile(BaseModel):
""" """
MediaFile model MediaFile model
""" """
pass pass
class OldSong(BaseModel): class OldSong(BaseModel):
""" """
Song model Song model
""" """
pass pass
class OldTopic(BaseModel): class OldTopic(BaseModel):
""" """
Topic model Topic model
""" """
pass pass
class OpenLPSongImport(SongImport): class OpenLPSongImport(SongImport):
""" """
The :class:`OpenLPSongImport` class provides OpenLP with the ability to The :class:`OpenLPSongImport` class provides OpenLP with the ability to
@ -170,25 +176,18 @@ class OpenLPSongImport(SongImport):
new_song.comments = song.comments new_song.comments = song.comments
new_song.theme_name = song.theme_name new_song.theme_name = song.theme_name
new_song.ccli_number = song.ccli_number new_song.ccli_number = song.ccli_number
if song.authors: for author in song.authors:
for author in song.authors: existing_author = self.manager.get_object_filtered(
existing_author = self.manager.get_object_filtered( Author, Author.display_name == author.display_name)
Author, Author.display_name == author.display_name) if existing_author:
if existing_author: new_song.authors.append(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)
else: else:
new_song.authors.append(Author.populate( 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: if song.book:
existing_song_book = self.manager.get_object_filtered( existing_song_book = self.manager.get_object_filtered(
Book, Book.name == song.book.name) Book, Book.name == song.book.name)

View File

@ -29,7 +29,7 @@ import re
from PyQt4 import QtCore from PyQt4 import QtCore
from openlp.core.lib import Receiver, translate 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.db import Song, Author, Topic, Book, MediaFile
from openlp.plugins.songs.lib.ui import SongStrings from openlp.plugins.songs.lib.ui import SongStrings
from openlp.plugins.songs.lib.xml import SongXML 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. 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) log.info(u'committing song %s to database', self.title)
song = Song() song = Song()
song.title = self.title song.title = self.title
@ -315,10 +313,13 @@ class SongImport(QtCore.QObject):
author = self.manager.get_object_filtered(Author, author = self.manager.get_object_filtered(Author,
Author.display_name == authortext) Author.display_name == authortext)
if not author: if not author:
author = Author.populate(display_name = authortext, author = Author.populate(display_name=authortext,
last_name=authortext.split(u' ')[-1], last_name=authortext.split(u' ')[-1],
first_name=u' '.join(authortext.split(u' ')[:-1])) first_name=u' '.join(authortext.split(u' ')[:-1]))
song.authors.append(author) 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: for filename in self.media_files:
media_file = self.manager.get_object_filtered(MediaFile, media_file = self.manager.get_object_filtered(MediaFile,
MediaFile.file_name == filename) MediaFile.file_name == filename)

View File

@ -36,8 +36,7 @@ class SongStrings(object):
# These strings should need a good reason to be retranslated elsewhere. # These strings should need a good reason to be retranslated elsewhere.
Author = translate('OpenLP.Ui', 'Author', 'Singular') Author = translate('OpenLP.Ui', 'Author', 'Singular')
Authors = translate('OpenLP.Ui', 'Authors', 'Plural') Authors = translate('OpenLP.Ui', 'Authors', 'Plural')
AuthorUnknown = translate('OpenLP.Ui', 'Author Unknown') # Used in the UI. AuthorUnknown = u'Author Unknown' # Used to populate the database.
AuthorUnknownUnT = u'Author Unknown' # Used to populate the database.
CopyrightSymbol = translate('OpenLP.Ui', '\xa9', 'Copyright symbol.') CopyrightSymbol = translate('OpenLP.Ui', '\xa9', 'Copyright symbol.')
SongBook = translate('OpenLP.Ui', 'Song Book', 'Singular') SongBook = translate('OpenLP.Ui', 'Song Book', 'Singular')
SongBooks = translate('OpenLP.Ui', 'Song Books', 'Plural') SongBooks = translate('OpenLP.Ui', 'Song Books', 'Plural')

View File

@ -66,7 +66,7 @@ import re
from lxml import etree, objectify 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.db import Author, Book, Song, Topic
from openlp.plugins.songs.lib.ui import SongStrings from openlp.plugins.songs.lib.ui import SongStrings
@ -374,8 +374,6 @@ class OpenLyrics(object):
display_name = self._text(author) display_name = self._text(author)
if display_name: if display_name:
authors.append(display_name) authors.append(display_name)
if not authors:
authors.append(SongStrings.AuthorUnknownUnT)
for display_name in authors: for display_name in authors:
author = self.manager.get_object_filtered(Author, author = self.manager.get_object_filtered(Author,
Author.display_name == display_name) Author.display_name == display_name)
@ -384,8 +382,8 @@ class OpenLyrics(object):
author = Author.populate(display_name=display_name, author = Author.populate(display_name=display_name,
last_name=display_name.split(u' ')[-1], last_name=display_name.split(u' ')[-1],
first_name=u' '.join(display_name.split(u' ')[:-1])) first_name=u' '.join(display_name.split(u' ')[:-1]))
self.manager.save_object(author) if not song.authors:
song.authors.append(author) add_author_unknown(self.manager, song)
def _process_cclinumber(self, properties, song): def _process_cclinumber(self, properties, song):
""" """

View File

@ -32,7 +32,8 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import Plugin, StringContent, build_icon, translate from openlp.core.lib import Plugin, StringContent, build_icon, translate
from openlp.core.lib.db import Manager from openlp.core.lib.db import Manager
from openlp.core.lib.ui import UiStrings 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.db import init_schema, Song
from openlp.plugins.songs.lib.importer import SongFormat from openlp.plugins.songs.lib.importer import SongFormat
@ -145,6 +146,9 @@ class SongsPlugin(Plugin):
counter = 0 counter = 0
for song in songs: for song in songs:
counter += 1 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: if song.title is None:
song.title = u'' song.title = u''
if song.alternate_title is None: if song.alternate_title is None: