forked from openlp/openlp
r1328
This commit is contained in:
commit
2b41cf545a
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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,
|
||||
|
@ -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'
|
||||
|
@ -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)
|
||||
|
@ -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', '<strong>Media Plugin</strong>'
|
||||
|
@ -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)
|
||||
self.parent.close_connection(self)
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
576
openlp/plugins/songs/lib/foilpresenterimport.py
Normal file
576
openlp/plugins/songs/lib/foilpresenterimport.py
Normal 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)
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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')
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user