mirror of https://gitlab.com/openlp/openlp.git
r1230
This commit is contained in:
commit
fca78af3df
|
@ -169,8 +169,9 @@ class MediaManagerItem(QtGui.QWidget):
|
|||
``slot``
|
||||
The method to call when the button is clicked.
|
||||
|
||||
``objectname``
|
||||
The name of the button.
|
||||
``checkable``
|
||||
If *True* the button has two, *off* and *on*, states. Default is
|
||||
*False*, which means the buttons has only one state.
|
||||
"""
|
||||
# NB different order (when I broke this out, I didn't want to
|
||||
# break compatability), but it makes sense for the icon to
|
||||
|
@ -193,13 +194,13 @@ class MediaManagerItem(QtGui.QWidget):
|
|||
"""
|
||||
# Add a toolbar
|
||||
self.addToolbar()
|
||||
#Allow the plugin to define buttons at start of bar
|
||||
# Allow the plugin to define buttons at start of bar
|
||||
self.addStartHeaderBar()
|
||||
#Add the middle of the tool bar (pre defined)
|
||||
# Add the middle of the tool bar (pre defined)
|
||||
self.addMiddleHeaderBar()
|
||||
#Allow the plugin to define buttons at end of bar
|
||||
# Allow the plugin to define buttons at end of bar
|
||||
self.addEndHeaderBar()
|
||||
#Add the list view
|
||||
# Add the list view
|
||||
self.addListViewToToolBar()
|
||||
|
||||
def addMiddleHeaderBar(self):
|
||||
|
|
|
@ -69,8 +69,9 @@ class OpenLPToolbar(QtGui.QToolBar):
|
|||
``slot``
|
||||
The method to run when this button is clicked.
|
||||
|
||||
``objectname``
|
||||
The name of the object, as used in `<button>.setObjectName()`.
|
||||
``checkable``
|
||||
If *True* the button has two, *off* and *on*, states. Default is
|
||||
*False*, which means the buttons has only one state.
|
||||
"""
|
||||
newAction = None
|
||||
if icon:
|
||||
|
|
|
@ -437,7 +437,8 @@ class MainDisplay(DisplayWidget):
|
|||
self.hideDisplay(self.hideMode)
|
||||
# Hide mouse cursor when moved over display if enabled in settings
|
||||
settings = QtCore.QSettings()
|
||||
if settings.value(u'advanced/hide mouse', QtCore.QVariant(False)).toBool():
|
||||
if settings.value(u'advanced/hide mouse',
|
||||
QtCore.QVariant(False)).toBool():
|
||||
self.setCursor(QtCore.Qt.BlankCursor)
|
||||
self.frame.evaluateJavaScript('document.body.style.cursor = "none"')
|
||||
else:
|
||||
|
|
|
@ -85,7 +85,7 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog):
|
|||
item.setIcon(plugin.icon)
|
||||
self.pluginListWidget.addItem(item)
|
||||
pluginListWidth = max(pluginListWidth, self.fontMetrics().width(
|
||||
unicode(translate('OpenLP.PluginForm', '%s (Inactive)')) %
|
||||
unicode(translate('OpenLP.PluginForm', '%s (Inactive)')) %
|
||||
name_string[u'singular']))
|
||||
self.pluginListWidget.setFixedWidth(pluginListWidth +
|
||||
self.pluginListWidget.iconSize().width() + 48)
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
###############################################################################
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from serviceitemeditdialog import Ui_ServiceItemEditDialog
|
||||
|
||||
class ServiceItemEditForm(QtGui.QDialog, Ui_ServiceItemEditDialog):
|
||||
|
@ -39,16 +40,18 @@ class ServiceItemEditForm(QtGui.QDialog, Ui_ServiceItemEditDialog):
|
|||
self.setupUi(self)
|
||||
self.itemList = []
|
||||
# enable drop
|
||||
QtCore.QObject.connect(self.upButton, QtCore.SIGNAL(u'clicked()'),
|
||||
self.onItemUp)
|
||||
QtCore.QObject.connect(self.downButton, QtCore.SIGNAL(u'clicked()'),
|
||||
self.onItemDown)
|
||||
QtCore.QObject.connect(self.deleteButton, QtCore.SIGNAL(u'clicked()'),
|
||||
self.onItemDelete)
|
||||
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(u'accepted()'),
|
||||
self.accept)
|
||||
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(u'rejected()'),
|
||||
self.reject)
|
||||
QtCore.QObject.connect(self.upButton,
|
||||
QtCore.SIGNAL(u'clicked()'), self.onItemUp)
|
||||
QtCore.QObject.connect(self.downButton,
|
||||
QtCore.SIGNAL(u'clicked()'), self.onItemDown)
|
||||
QtCore.QObject.connect(self.deleteButton,
|
||||
QtCore.SIGNAL(u'clicked()'), self.onItemDelete)
|
||||
QtCore.QObject.connect(self.buttonBox,
|
||||
QtCore.SIGNAL(u'accepted()'), self.accept)
|
||||
QtCore.QObject.connect(self.buttonBox,
|
||||
QtCore.SIGNAL(u'rejected()'), self.reject)
|
||||
QtCore.QObject.connect(self.listWidget,
|
||||
QtCore.SIGNAL(u'currentRowChanged(int)'), self.onCurrentRowChanged)
|
||||
|
||||
def setServiceItem(self, item):
|
||||
self.item = item
|
||||
|
@ -58,6 +61,7 @@ class ServiceItemEditForm(QtGui.QDialog, Ui_ServiceItemEditDialog):
|
|||
for frame in self.item._raw_frames:
|
||||
self.itemList.append(frame)
|
||||
self.loadData()
|
||||
self.listWidget.setCurrentItem(self.listWidget.currentItem())
|
||||
|
||||
def getServiceItem(self):
|
||||
if self.data:
|
||||
|
@ -69,57 +73,79 @@ class ServiceItemEditForm(QtGui.QDialog, Ui_ServiceItemEditDialog):
|
|||
return self.item
|
||||
|
||||
def loadData(self):
|
||||
"""
|
||||
Loads the image list.
|
||||
"""
|
||||
self.listWidget.clear()
|
||||
for frame in self.itemList:
|
||||
item_name = QtGui.QListWidgetItem(frame[u'title'])
|
||||
self.listWidget.addItem(item_name)
|
||||
if self.listWidget.count() == 1:
|
||||
|
||||
def onItemDelete(self):
|
||||
"""
|
||||
Delete the current row.
|
||||
"""
|
||||
item = self.listWidget.currentItem()
|
||||
if not item:
|
||||
return
|
||||
row = self.listWidget.row(item)
|
||||
self.itemList.remove(self.itemList[row])
|
||||
self.loadData()
|
||||
if row == self.listWidget.count():
|
||||
self.listWidget.setCurrentRow(row - 1)
|
||||
else:
|
||||
self.listWidget.setCurrentRow(row)
|
||||
|
||||
def onItemUp(self):
|
||||
"""
|
||||
Move the current row up in the list.
|
||||
"""
|
||||
item = self.listWidget.currentItem()
|
||||
if not item:
|
||||
return
|
||||
row = self.listWidget.row(item)
|
||||
temp = self.itemList[row]
|
||||
self.itemList.remove(self.itemList[row])
|
||||
self.itemList.insert(row - 1, temp)
|
||||
self.loadData()
|
||||
self.listWidget.setCurrentRow(row - 1)
|
||||
|
||||
def onItemDown(self):
|
||||
"""
|
||||
Move the current row down in the list
|
||||
"""
|
||||
item = self.listWidget.currentItem()
|
||||
if not item:
|
||||
return
|
||||
row = self.listWidget.row(item)
|
||||
temp = self.itemList[row]
|
||||
self.itemList.remove(self.itemList[row])
|
||||
self.itemList.insert(row + 1, temp)
|
||||
self.loadData()
|
||||
self.listWidget.setCurrentRow(row + 1)
|
||||
|
||||
def onCurrentRowChanged(self, row):
|
||||
"""
|
||||
Called when the currentRow has changed.
|
||||
|
||||
``row``
|
||||
The row number (int).
|
||||
"""
|
||||
# Disable all buttons, as no row is selected or only one image is left.
|
||||
if row == -1 or self.listWidget.count() == 1:
|
||||
self.downButton.setEnabled(False)
|
||||
self.upButton.setEnabled(False)
|
||||
self.deleteButton.setEnabled(False)
|
||||
else:
|
||||
self.downButton.setEnabled(True)
|
||||
self.upButton.setEnabled(True)
|
||||
# Check if we are at the end of the list.
|
||||
if self.listWidget.count() == row + 1:
|
||||
self.downButton.setEnabled(False)
|
||||
else:
|
||||
self.downButton.setEnabled(True)
|
||||
# Check if we are at the beginning of the list.
|
||||
if row == 0:
|
||||
self.upButton.setEnabled(False)
|
||||
else:
|
||||
self.upButton.setEnabled(True)
|
||||
self.deleteButton.setEnabled(True)
|
||||
|
||||
def onItemDelete(self):
|
||||
"""
|
||||
Delete the selected row
|
||||
"""
|
||||
items = self.listWidget.selectedItems()
|
||||
for item in items:
|
||||
row = self.listWidget.row(item)
|
||||
self.itemList.remove(self.itemList[row])
|
||||
self.loadData()
|
||||
if row == self.listWidget.count():
|
||||
self.listWidget.setCurrentRow(row - 1)
|
||||
else:
|
||||
self.listWidget.setCurrentRow(row)
|
||||
|
||||
def onItemUp(self):
|
||||
"""
|
||||
Move the selected row up in the list
|
||||
"""
|
||||
items = self.listWidget.selectedItems()
|
||||
for item in items:
|
||||
row = self.listWidget.row(item)
|
||||
if row > 0:
|
||||
temp = self.itemList[row]
|
||||
self.itemList.remove(self.itemList[row])
|
||||
self.itemList.insert(row - 1, temp)
|
||||
self.loadData()
|
||||
self.listWidget.setCurrentRow(row - 1)
|
||||
|
||||
def onItemDown(self):
|
||||
"""
|
||||
Move the selected row down in the list
|
||||
"""
|
||||
items = self.listWidget.selectedItems()
|
||||
for item in items:
|
||||
row = self.listWidget.row(item)
|
||||
if row < len(self.itemList) and row is not -1:
|
||||
temp = self.itemList[row]
|
||||
self.itemList.remove(self.itemList[row])
|
||||
self.itemList.insert(row + 1, temp)
|
||||
self.loadData()
|
||||
self.listWidget.setCurrentRow(row + 1)
|
|
@ -245,6 +245,9 @@ class ServiceManager(QtGui.QWidget):
|
|||
QtCore.SIGNAL(u'servicemanager_list_request'), self.listRequest)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'config_updated'), self.configUpdated)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'config_screen_changed'),
|
||||
self.regenerateServiceItems)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'theme_update_global'), self.themeChange)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
|
@ -289,7 +292,7 @@ class ServiceManager(QtGui.QWidget):
|
|||
self.themeMenu = QtGui.QMenu(
|
||||
translate('OpenLP.ServiceManager', '&Change Item Theme'))
|
||||
self.menu.addMenu(self.themeMenu)
|
||||
self.configUpdated(True)
|
||||
self.configUpdated()
|
||||
|
||||
def setModified(self, modified=True):
|
||||
"""
|
||||
|
@ -328,15 +331,13 @@ class ServiceManager(QtGui.QWidget):
|
|||
"""
|
||||
return split_filename(self._fileName)[1]
|
||||
|
||||
def configUpdated(self, firstTime=False):
|
||||
def configUpdated(self):
|
||||
"""
|
||||
Triggered when Config dialog is updated.
|
||||
"""
|
||||
self.expandTabs = QtCore.QSettings().value(
|
||||
u'advanced/expand service item',
|
||||
QtCore.QVariant(u'False')).toBool()
|
||||
if not firstTime:
|
||||
self.regenerateServiceItems()
|
||||
|
||||
def supportedSuffixes(self, suffix):
|
||||
self.suffixes.append(suffix)
|
||||
|
|
|
@ -376,8 +376,6 @@ class SlideController(QtGui.QWidget):
|
|||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'slidecontroller_%s_text_request' % self.typePrefix),
|
||||
self.onTextRequest)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'config_updated'), self.refreshServiceItem)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'config_screen_changed'), self.screenSizeChanged)
|
||||
|
||||
|
@ -395,6 +393,8 @@ class SlideController(QtGui.QWidget):
|
|||
self.ratio = float(self.screens.current[u'size'].width()) / \
|
||||
float(self.screens.current[u'size'].height())
|
||||
self.previewSizeChanged()
|
||||
if self.serviceItem:
|
||||
self.refreshServiceItem()
|
||||
|
||||
def previewSizeChanged(self):
|
||||
"""
|
||||
|
@ -493,11 +493,10 @@ class SlideController(QtGui.QWidget):
|
|||
Method to update the service item if the screen has changed
|
||||
"""
|
||||
log.debug(u'refreshServiceItem live = %s' % self.isLive)
|
||||
if self.serviceItem:
|
||||
if self.serviceItem.is_text() or self.serviceItem.is_image():
|
||||
item = self.serviceItem
|
||||
item.render()
|
||||
self._processItem(item, self.selectedRow)
|
||||
if self.serviceItem.is_text() or self.serviceItem.is_image():
|
||||
item = self.serviceItem
|
||||
item.render()
|
||||
self._processItem(item, self.selectedRow)
|
||||
|
||||
def addServiceItem(self, item):
|
||||
"""
|
||||
|
|
|
@ -95,7 +95,7 @@ class OpenLPWizard(QtGui.QWizard):
|
|||
|
||||
def addProgressPage(self):
|
||||
"""
|
||||
Add the progress page for the wizard. This page informs the user how
|
||||
Add the progress page for the wizard. This page informs the user how
|
||||
the wizard is progressing with its task.
|
||||
"""
|
||||
self.progressPage = QtGui.QWizardPage()
|
||||
|
@ -125,7 +125,7 @@ class OpenLPWizard(QtGui.QWizard):
|
|||
log.debug(u'Wizard cancelled by user.')
|
||||
if self.currentPage() == self.progressPage:
|
||||
Receiver.send_message(u'openlp_stop_wizard')
|
||||
self.done(QtGui.QDialog.Rejected)
|
||||
self.done(QtGui.QDialog.Rejected)
|
||||
|
||||
def onCurrentIdChanged(self, pageId):
|
||||
"""
|
||||
|
|
|
@ -553,7 +553,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
|||
return False
|
||||
if self.verseOrderEdit.text():
|
||||
order = []
|
||||
order_names = self.verseOrderEdit.text().split()
|
||||
order_names = unicode(self.verseOrderEdit.text()).split()
|
||||
for item in order_names:
|
||||
if len(item) == 1:
|
||||
order.append(item.lower() + u'1')
|
||||
|
|
|
@ -128,6 +128,9 @@ class SongImportForm(OpenLPWizard):
|
|||
QtCore.QObject.connect(self.genericRemoveButton,
|
||||
QtCore.SIGNAL(u'clicked()'),
|
||||
self.onGenericRemoveButtonClicked)
|
||||
QtCore.QObject.connect(self.easiSlidesBrowseButton,
|
||||
QtCore.SIGNAL(u'clicked()'),
|
||||
self.onEasiSlidesBrowseButtonClicked)
|
||||
QtCore.QObject.connect(self.ewBrowseButton,
|
||||
QtCore.SIGNAL(u'clicked()'),
|
||||
self.onEWBrowseButtonClicked)
|
||||
|
@ -177,6 +180,8 @@ class SongImportForm(OpenLPWizard):
|
|||
self.addMultiFileSelectItem(u'songsOfFellowship', None, True)
|
||||
# Generic Document/Presentation import
|
||||
self.addMultiFileSelectItem(u'generic', None, True)
|
||||
# EasySlides
|
||||
self.addSingleFileSelectItem(u'easiSlides')
|
||||
# EasyWorship
|
||||
self.addSingleFileSelectItem(u'ew')
|
||||
# Words of Worship
|
||||
|
@ -226,10 +231,12 @@ class SongImportForm(OpenLPWizard):
|
|||
translate('SongsPlugin.ImportWizardForm',
|
||||
'Generic Document/Presentation'))
|
||||
self.formatComboBox.setItemText(8,
|
||||
translate('SongsPlugin.ImportWizardForm', 'EasyWorship'))
|
||||
translate('SongsPlugin.ImportWizardForm', 'EasiSlides'))
|
||||
self.formatComboBox.setItemText(9,
|
||||
translate('SongsPlugin.ImportWizardForm', 'EasyWorship'))
|
||||
self.formatComboBox.setItemText(10,
|
||||
translate('SongsPlugin.ImportWizardForm', 'SongBeamer'))
|
||||
# self.formatComboBox.setItemText(9,
|
||||
# self.formatComboBox.setItemText(11,
|
||||
# translate('SongsPlugin.ImportWizardForm', 'CSV'))
|
||||
self.openLP2FilenameLabel.setText(
|
||||
translate('SongsPlugin.ImportWizardForm', 'Filename:'))
|
||||
|
@ -281,6 +288,10 @@ class SongImportForm(OpenLPWizard):
|
|||
translate('SongsPlugin.ImportWizardForm', 'The generic document/'
|
||||
'presentation importer has been disabled because OpenLP cannot '
|
||||
'find OpenOffice.org on your computer.'))
|
||||
self.easiSlidesFilenameLabel.setText(
|
||||
translate('SongsPlugin.ImportWizardForm', 'Filename:'))
|
||||
self.easiSlidesBrowseButton.setText(
|
||||
translate('SongsPlugin.ImportWizardForm', 'Browse...'))
|
||||
self.ewFilenameLabel.setText(
|
||||
translate('SongsPlugin.ImportWizardForm', 'Filename:'))
|
||||
self.ewBrowseButton.setText(
|
||||
|
@ -311,6 +322,8 @@ class SongImportForm(OpenLPWizard):
|
|||
QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
|
||||
self.openLP1FormLabelSpacer.changeSize(width, 0,
|
||||
QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
|
||||
self.easiSlidesFormLabelSpacer.changeSize(width, 0,
|
||||
QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
|
||||
self.ewFormLabelSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed,
|
||||
QtGui.QSizePolicy.Fixed)
|
||||
# self.csvFormLabelSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed,
|
||||
|
@ -404,6 +417,16 @@ class SongImportForm(OpenLPWizard):
|
|||
'presentation file to import from.'))
|
||||
self.genericAddButton.setFocus()
|
||||
return False
|
||||
elif source_format == SongFormat.EasiSlides:
|
||||
if self.easiSlidesFilenameEdit.text().isEmpty():
|
||||
criticalErrorMessageBox(
|
||||
translate('SongsPlugin.ImportWizardForm',
|
||||
'No Easislides Songs file selected'),
|
||||
translate('SongsPlugin.ImportWizardForm',
|
||||
'You need to select an xml song file exported from '
|
||||
'EasiSlides, to import from.'))
|
||||
self.easiSlidesBrowseButton.setFocus()
|
||||
return False
|
||||
elif source_format == SongFormat.EasyWorship:
|
||||
if self.ewFilenameEdit.text().isEmpty():
|
||||
criticalErrorMessageBox(
|
||||
|
@ -625,6 +648,13 @@ class SongImportForm(OpenLPWizard):
|
|||
"""
|
||||
self.removeSelectedItems(self.genericFileListWidget)
|
||||
|
||||
def onEasiSlidesBrowseButtonClicked(self):
|
||||
self.getFileName(
|
||||
translate('SongsPlugin.ImportWizardForm',
|
||||
'Select EasiSlides songfile'),
|
||||
self.easiSlidesFilenameEdit
|
||||
)
|
||||
|
||||
def onEWBrowseButtonClicked(self):
|
||||
"""
|
||||
Get EasyWorship song database files
|
||||
|
@ -674,6 +704,7 @@ class SongImportForm(OpenLPWizard):
|
|||
self.ccliFileListWidget.clear()
|
||||
self.songsOfFellowshipFileListWidget.clear()
|
||||
self.genericFileListWidget.clear()
|
||||
self.easiSlidesFilenameEdit.setText(u'')
|
||||
self.ewFilenameEdit.setText(u'')
|
||||
self.songBeamerFileListWidget.clear()
|
||||
#self.csvFilenameEdit.setText(u'')
|
||||
|
@ -737,8 +768,13 @@ class SongImportForm(OpenLPWizard):
|
|||
importer = self.plugin.importSongs(SongFormat.Generic,
|
||||
filenames=self.getListOfFiles(self.genericFileListWidget)
|
||||
)
|
||||
elif source_format == SongFormat.EasiSlides:
|
||||
# Import an EasiSlides export file
|
||||
importer = self.plugin.importSongs(SongFormat.EasiSlides,
|
||||
filename=unicode(self.easiSlidesFilenameEdit.text())
|
||||
)
|
||||
elif source_format == SongFormat.EasyWorship:
|
||||
# Import an OpenLP 2.0 database
|
||||
# Import an EasyWorship database
|
||||
importer = self.plugin.importSongs(SongFormat.EasyWorship,
|
||||
filename=unicode(self.ewFilenameEdit.text())
|
||||
)
|
||||
|
|
|
@ -171,10 +171,10 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
|||
# not return False when nothing has changed (because this would
|
||||
# cause an error message later on).
|
||||
if edit:
|
||||
if authors[0].id == new_author.id:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
for author in authors:
|
||||
if author.id != new_author.id:
|
||||
return False
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
|
@ -191,10 +191,10 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
|||
# not return False when nothing has changed (because this would
|
||||
# cause an error message later on).
|
||||
if edit:
|
||||
if topics[0].id == new_topic.id:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
for topic in topics:
|
||||
if topic.id != new_topic.id:
|
||||
return False
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
|
@ -212,10 +212,10 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
|
|||
# not return False when nothing has changed (because this would
|
||||
# cause an error message later on).
|
||||
if edit:
|
||||
if books[0].id == new_book.id:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
for book in books:
|
||||
if book.id != new_book.id:
|
||||
return False
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
|
|
|
@ -0,0 +1,341 @@
|
|||
# -*- 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 #
|
||||
###############################################################################
|
||||
|
||||
import logging
|
||||
import os
|
||||
from lxml import etree, objectify
|
||||
from lxml.etree import Error, LxmlError
|
||||
import re
|
||||
|
||||
from openlp.core.lib import translate
|
||||
from openlp.plugins.songs.lib.songimport import SongImport
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
class EasiSlidesImport(SongImport):
|
||||
"""
|
||||
Import songs exported from EasiSlides
|
||||
|
||||
The format example is here:
|
||||
http://wiki.openlp.org/Development:EasiSlides_-_Song_Data_Format
|
||||
"""
|
||||
def __init__(self, manager, **kwargs):
|
||||
"""
|
||||
Initialise the class.
|
||||
"""
|
||||
SongImport.__init__(self, manager)
|
||||
self.filename = kwargs[u'filename']
|
||||
self.song = None
|
||||
self.commit = True
|
||||
|
||||
def do_import(self):
|
||||
"""
|
||||
Import either each of the files in self.filenames - each element of
|
||||
which can be either a single opensong file, or a zipfile containing
|
||||
multiple opensong files. If `self.commit` is set False, the
|
||||
import will not be committed to the database (useful for test scripts).
|
||||
"""
|
||||
self.import_wizard.progressBar.setMaximum(1)
|
||||
log.info(u'Importing EasiSlides XML file %s', self.filename)
|
||||
parser = etree.XMLParser(remove_blank_text=True)
|
||||
file = etree.parse(self.filename, parser)
|
||||
xml = unicode(etree.tostring(file))
|
||||
song_xml = objectify.fromstring(xml)
|
||||
self.import_wizard.incrementProgressBar(
|
||||
unicode(translate('SongsPlugin.ImportWizardForm',
|
||||
u'Importing %s...')) % os.path.split(self.filename)[-1])
|
||||
self.import_wizard.progressBar.setMaximum(len(song_xml.Item))
|
||||
for song in song_xml.Item:
|
||||
self.import_wizard.incrementProgressBar(
|
||||
unicode(translate('SongsPlugin.ImportWizardForm',
|
||||
u'Importing %s, song %s...')) %
|
||||
(os.path.split(self.filename)[-1], song.Title1))
|
||||
success = self._parse_song(song)
|
||||
if not success or self.stop_import_flag:
|
||||
return False
|
||||
elif self.commit:
|
||||
self.finish()
|
||||
return True
|
||||
|
||||
def _parse_song(self, song):
|
||||
self._success = True
|
||||
self._add_title(song)
|
||||
self._add_alttitle(song)
|
||||
self._add_number(song)
|
||||
self._add_authors(song)
|
||||
self._add_copyright(song)
|
||||
self._add_book(song)
|
||||
self._parse_and_add_lyrics(song)
|
||||
return self._success
|
||||
|
||||
def _add_title(self, song):
|
||||
try:
|
||||
self.title = unicode(song.Title1).strip()
|
||||
except UnicodeDecodeError:
|
||||
log.exception(u'Unicode decode error while decoding Title1')
|
||||
self._success = False
|
||||
except AttributeError:
|
||||
log.exception(u'no Title1')
|
||||
self._success = False
|
||||
|
||||
def _add_alttitle(self, song):
|
||||
try:
|
||||
self.alternate_title = unicode(song.Title2).strip()
|
||||
except UnicodeDecodeError:
|
||||
log.exception(u'Unicode decode error while decoding Title2')
|
||||
self._success = False
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def _add_number(self, song):
|
||||
try:
|
||||
number = unicode(song.SongNumber)
|
||||
if number != u'0':
|
||||
self.song_number = number
|
||||
except UnicodeDecodeError:
|
||||
log.exception(u'Unicode decode error while decoding SongNumber')
|
||||
self._success = False
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def _add_authors(self, song):
|
||||
try:
|
||||
authors = unicode(song.Writer).split(u',')
|
||||
for author in authors:
|
||||
author = author.strip()
|
||||
if len(author) > 0:
|
||||
self.authors.append(author)
|
||||
except UnicodeDecodeError:
|
||||
log.exception(u'Unicode decode error while decoding Writer')
|
||||
self._success = False
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def _add_copyright(self, song):
|
||||
copyright = []
|
||||
try:
|
||||
copyright.append(unicode(song.Copyright).strip())
|
||||
except UnicodeDecodeError:
|
||||
log.exception(u'Unicode decode error while decoding Copyright')
|
||||
self._success = False
|
||||
except AttributeError:
|
||||
pass
|
||||
try:
|
||||
copyright.append(unicode(song.LicenceAdmin1).strip())
|
||||
except UnicodeDecodeError:
|
||||
log.exception(u'Unicode decode error while decoding LicenceAdmin1')
|
||||
self._success = False
|
||||
except AttributeError:
|
||||
pass
|
||||
try:
|
||||
copyright.append(unicode(song.LicenceAdmin2).strip())
|
||||
except UnicodeDecodeError:
|
||||
log.exception(u'Unicode decode error while decoding LicenceAdmin2')
|
||||
self._success = False
|
||||
except AttributeError:
|
||||
pass
|
||||
self.add_copyright(u' '.join(copyright))
|
||||
|
||||
def _add_book(self, song):
|
||||
try:
|
||||
self.song_book_name = unicode(song.BookReference).strip()
|
||||
except UnicodeDecodeError:
|
||||
log.exception(u'Unicode decode error while decoding BookReference')
|
||||
self._success = False
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def _parse_and_add_lyrics(self, song):
|
||||
try:
|
||||
lyrics = unicode(song.Contents).strip()
|
||||
except UnicodeDecodeError:
|
||||
log.exception(u'Unicode decode error while decoding Contents')
|
||||
self._success = False
|
||||
except AttributeError:
|
||||
log.exception(u'no Contents')
|
||||
self._success = False
|
||||
lines = lyrics.split(u'\n')
|
||||
# we go over all lines first, to determine information,
|
||||
# which tells us how to parse verses later
|
||||
regionlines = {}
|
||||
separatorlines = 0
|
||||
for line in lines:
|
||||
line = line.strip()
|
||||
if len(line) == 0:
|
||||
continue
|
||||
elif line[1:7] == u'region':
|
||||
# this is region separator, probably [region 2]
|
||||
region = self._extractRegion(line)
|
||||
if regionlines.has_key(region):
|
||||
regionlines[region] = regionlines[region] + 1
|
||||
else:
|
||||
regionlines[region] = 1
|
||||
elif line[0] == u'[':
|
||||
separatorlines = separatorlines + 1
|
||||
# if the song has separators
|
||||
separators = (separatorlines > 0)
|
||||
# the number of different regions in song - 1
|
||||
if len(regionlines) > 1:
|
||||
log.info(u'EasiSlidesImport: the file contained a song named "%s"'
|
||||
u'with more than two regions, but only two regions are',
|
||||
u'tested, encountered regions were: %s',
|
||||
self.title, u','.join(regionlines.keys()))
|
||||
# if the song has regions
|
||||
regions = (len(regionlines) > 0)
|
||||
# if the regions are inside verses
|
||||
regionsInVerses = (regions and regionlines[regionlines.keys()[0]] > 1)
|
||||
MarkTypes = {
|
||||
u'CHORUS': u'C',
|
||||
u'VERSE': u'V',
|
||||
u'INTRO': u'I',
|
||||
u'ENDING': u'E',
|
||||
u'BRIDGE': u'B',
|
||||
u'PRECHORUS': u'P'}
|
||||
verses = {}
|
||||
# list as [region, versetype, versenum, instance]
|
||||
our_verse_order = []
|
||||
defaultregion = u'1'
|
||||
reg = defaultregion
|
||||
verses[reg] = {}
|
||||
# instance differentiates occurrences of same verse tag
|
||||
vt = u'V'
|
||||
vn = u'1'
|
||||
inst = 1
|
||||
|
||||
for line in lines:
|
||||
line = line.strip()
|
||||
if len(line) == 0:
|
||||
if separators:
|
||||
# separators are used, so empty line means slide break
|
||||
# inside verse
|
||||
if self._listHas(verses, [reg, vt, vn, inst]):
|
||||
inst = inst + 1
|
||||
else:
|
||||
# separators are not used, so empty line starts a new verse
|
||||
vt = u'V'
|
||||
if verses[reg].has_key(vt):
|
||||
vn = len(verses[reg][vt].keys())+1
|
||||
else:
|
||||
vn = u'1'
|
||||
inst = 1
|
||||
elif line[0:7] == u'[region':
|
||||
reg = self._extractRegion(line)
|
||||
if not verses.has_key(reg):
|
||||
verses[reg] = {}
|
||||
if not regionsInVerses:
|
||||
vt = u'V'
|
||||
vn = u'1'
|
||||
inst = 1
|
||||
elif line[0] == u'[':
|
||||
# this is a normal section marker
|
||||
marker = line[1:line.find(u']')].upper()
|
||||
vn = u'1'
|
||||
# have we got any digits?
|
||||
# If so, versenumber is everything from the digits to the end
|
||||
match = re.match(u'(.*)(\d+.*)', marker)
|
||||
if match:
|
||||
marker = match.group(1).strip()
|
||||
vn = match.group(2)
|
||||
if len(marker) == 0:
|
||||
vt = u'V'
|
||||
elif MarkTypes.has_key(marker):
|
||||
vt = MarkTypes[marker]
|
||||
else:
|
||||
vt = u'O'
|
||||
if regionsInVerses:
|
||||
region = defaultregion
|
||||
inst = 1
|
||||
if self._listHas(verses, [reg, vt, vn, inst]):
|
||||
inst = len(verses[reg][vt][vn])+1
|
||||
else:
|
||||
if not [reg, vt, vn, inst] in our_verse_order:
|
||||
our_verse_order.append([reg, vt, vn, inst])
|
||||
if not verses[reg].has_key(vt):
|
||||
verses[reg][vt] = {}
|
||||
if not verses[reg][vt].has_key(vn):
|
||||
verses[reg][vt][vn] = {}
|
||||
if not verses[reg][vt][vn].has_key(inst):
|
||||
verses[reg][vt][vn][inst] = []
|
||||
words = self.tidy_text(line)
|
||||
verses[reg][vt][vn][inst].append(words)
|
||||
# done parsing
|
||||
|
||||
versetags = []
|
||||
# we use our_verse_order to ensure, we insert lyrics in the same order
|
||||
# as these appeared originally in the file
|
||||
for [reg, vt, vn, inst] in our_verse_order:
|
||||
if self._listHas(verses, [reg, vt, vn, inst]):
|
||||
versetag = u'%s%s' % (vt, vn)
|
||||
versetags.append(versetag)
|
||||
lines = u'\n'.join(verses[reg][vt][vn][inst])
|
||||
self.verses.append([versetag, lines])
|
||||
|
||||
SeqTypes = {
|
||||
u'p': u'P1',
|
||||
u'q': u'P2',
|
||||
u'c': u'C1',
|
||||
u't': u'C2',
|
||||
u'b': u'B1',
|
||||
u'w': u'B2',
|
||||
u'e': u'E1'}
|
||||
# Make use of Sequence data, determining the order of verses
|
||||
try:
|
||||
order = unicode(song.Sequence).strip().split(u',')
|
||||
for tag in order:
|
||||
if len(tag) == 0:
|
||||
continue
|
||||
elif tag[0].isdigit():
|
||||
tag = u'V' + tag
|
||||
elif SeqTypes.has_key(tag.lower()):
|
||||
tag = SeqTypes[tag.lower()]
|
||||
else:
|
||||
continue
|
||||
|
||||
if tag in versetags:
|
||||
self.verse_order_list.append(tag)
|
||||
else:
|
||||
log.info(u'Got order item %s, which is not in versetags,'
|
||||
u'dropping item from presentation order', tag)
|
||||
except UnicodeDecodeError:
|
||||
log.exception(u'Unicode decode error while decoding Sequence')
|
||||
self._success = False
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def _listHas(self, lst, subitems):
|
||||
for i in subitems:
|
||||
if type(lst) == type({}) and lst.has_key(i):
|
||||
lst = lst[i]
|
||||
elif type(lst) == type([]) and i in lst:
|
||||
lst = lst[i]
|
||||
else:
|
||||
return False
|
||||
return True
|
||||
|
||||
def _extractRegion(self, line):
|
||||
# this was true already: line[0:7] == u'[region':
|
||||
right_bracket = line.find(u']')
|
||||
return line[7:right_bracket].strip()
|
|
@ -27,6 +27,7 @@
|
|||
The :mod:`importer` modules provides the general song import functionality.
|
||||
"""
|
||||
from opensongimport import OpenSongImport
|
||||
from easislidesimport import EasiSlidesImport
|
||||
from olpimport import OpenLPSongImport
|
||||
from openlyricsimport import OpenLyricsImport
|
||||
from wowimport import WowImport
|
||||
|
@ -67,8 +68,9 @@ class SongFormat(object):
|
|||
SongsOfFellowship = 6
|
||||
Generic = 7
|
||||
#CSV = 8
|
||||
EasyWorship = 8
|
||||
SongBeamer = 9
|
||||
EasiSlides = 8
|
||||
EasyWorship = 9
|
||||
SongBeamer = 10
|
||||
|
||||
@staticmethod
|
||||
def get_class(format):
|
||||
|
@ -94,6 +96,8 @@ class SongFormat(object):
|
|||
return OooImport
|
||||
elif format == SongFormat.CCLI:
|
||||
return CCLIFileImport
|
||||
elif format == SongFormat.EasiSlides:
|
||||
return EasiSlidesImport
|
||||
elif format == SongFormat.EasyWorship:
|
||||
return EasyWorshipSongImport
|
||||
elif format == SongFormat.SongBeamer:
|
||||
|
@ -114,6 +118,7 @@ class SongFormat(object):
|
|||
SongFormat.CCLI,
|
||||
SongFormat.SongsOfFellowship,
|
||||
SongFormat.Generic,
|
||||
SongFormat.EasiSlides,
|
||||
SongFormat.EasyWorship,
|
||||
SongFormat.SongBeamer
|
||||
]
|
||||
|
@ -137,3 +142,4 @@ SongFormat.set_availability(SongFormat.SongsOfFellowship, HAS_SOF)
|
|||
SongFormat.set_availability(SongFormat.Generic, HAS_OOO)
|
||||
|
||||
__all__ = [u'SongFormat']
|
||||
|
||||
|
|
|
@ -258,6 +258,7 @@ class SongImport(QtCore.QObject):
|
|||
log.info(u'commiting song %s to database', self.title)
|
||||
song = Song()
|
||||
song.title = self.title
|
||||
song.alternate_title = self.alternate_title
|
||||
song.search_title = self.remove_punctuation(self.title).lower() \
|
||||
+ '@' + self.remove_punctuation(self.alternate_title).lower()
|
||||
song.song_number = self.song_number
|
||||
|
|
2690
resources/i18n/af.ts
2690
resources/i18n/af.ts
File diff suppressed because it is too large
Load Diff
4090
resources/i18n/de.ts
4090
resources/i18n/de.ts
File diff suppressed because it is too large
Load Diff
2525
resources/i18n/en.ts
2525
resources/i18n/en.ts
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
2548
resources/i18n/es.ts
2548
resources/i18n/es.ts
File diff suppressed because it is too large
Load Diff
2957
resources/i18n/et.ts
2957
resources/i18n/et.ts
File diff suppressed because it is too large
Load Diff
2579
resources/i18n/hu.ts
2579
resources/i18n/hu.ts
File diff suppressed because it is too large
Load Diff
3491
resources/i18n/ja.ts
3491
resources/i18n/ja.ts
File diff suppressed because it is too large
Load Diff
2541
resources/i18n/ko.ts
2541
resources/i18n/ko.ts
File diff suppressed because it is too large
Load Diff
2544
resources/i18n/nb.ts
2544
resources/i18n/nb.ts
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
2608
resources/i18n/sv.ts
2608
resources/i18n/sv.ts
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue