mirror of
https://gitlab.com/openlp/openlp.git
synced 2024-09-27 18:37:35 +00:00
Head
This commit is contained in:
commit
cc0af53b85
@ -113,6 +113,14 @@ class ImageManager(QtCore.QObject):
|
||||
time.sleep(0.1)
|
||||
return self._cache[name].image_bytes
|
||||
|
||||
def del_image(self, name):
|
||||
"""
|
||||
Delete the Image from the Cache
|
||||
"""
|
||||
log.debug(u'del_image %s' % name)
|
||||
if name in self._cache:
|
||||
del self._cache[name]
|
||||
|
||||
def add_image(self, name, path):
|
||||
"""
|
||||
Add image to cache if it is not already there
|
||||
@ -125,6 +133,8 @@ class ImageManager(QtCore.QObject):
|
||||
image.image = resize_image(path,
|
||||
self.width, self.height)
|
||||
self._cache[name] = image
|
||||
else:
|
||||
log.debug(u'Image in cache %s:%s' % (name, path))
|
||||
self._cache_dirty = True
|
||||
# only one thread please
|
||||
if not self._thread_running:
|
||||
|
@ -213,6 +213,8 @@ class RenderManager(object):
|
||||
# make big page for theme edit dialog to get line count
|
||||
if self.force_page:
|
||||
verse = verse + verse + verse
|
||||
else:
|
||||
self.image_manager.del_image(self.theme_data.theme_name)
|
||||
footer = []
|
||||
footer.append(u'Arky Arky (Unknown)' )
|
||||
footer.append(u'Public Domain')
|
||||
|
@ -44,6 +44,7 @@ class ServiceItemType(object):
|
||||
Image = 2
|
||||
Command = 3
|
||||
|
||||
|
||||
class ItemCapabilities(object):
|
||||
"""
|
||||
Provides an enumeration of a serviceitem's capabilities
|
||||
|
@ -166,6 +166,17 @@ class Ui_AboutDialog(object):
|
||||
' PyQt4: http://www.riverbankcomputing.co.uk/software/pyqt/'
|
||||
'intro\n'
|
||||
' Oxygen Icons: http://oxygen-icons.org/\n'
|
||||
'\n'
|
||||
'Final Credit\n'
|
||||
' "For God so loved the world that He gave\n'
|
||||
' His one and only Son, so that whoever\n'
|
||||
' believes in Him will not perish but inherit\n'
|
||||
' eternal life." -- John 3:16\n\n'
|
||||
' And last but not least, final credit goes to\n'
|
||||
' God our Father, for sending His Son to die\n'
|
||||
' on the cross, setting us free from sin. We\n'
|
||||
' bring this software to you for free because\n'
|
||||
' He has set us free.'
|
||||
))
|
||||
self.aboutNotebook.setTabText(
|
||||
self.aboutNotebook.indexOf(self.creditsTab),
|
||||
|
@ -23,7 +23,7 @@
|
||||
# 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 re
|
||||
import os
|
||||
import platform
|
||||
@ -59,6 +59,8 @@ from openlp.core.lib.mailto import mailto
|
||||
|
||||
from exceptiondialog import Ui_ExceptionDialog
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
|
||||
"""
|
||||
The exception dialog
|
||||
@ -103,7 +105,8 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
|
||||
filename = QtGui.QFileDialog.getSaveFileName(self,
|
||||
translate('OpenLP.ExceptionForm', 'Save Crash Report'),
|
||||
SettingsManager.get_last_dir(self.settingsSection),
|
||||
translate('OpenLP.ExceptionForm', 'Text files (*.txt *.log *.text)'))
|
||||
translate('OpenLP.ExceptionForm',
|
||||
'Text files (*.txt *.log *.text)'))
|
||||
if filename:
|
||||
filename = unicode(QtCore.QDir.toNativeSeparators(filename))
|
||||
SettingsManager.set_last_dir(self.settingsSection, os.path.dirname(
|
||||
@ -140,4 +143,5 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
|
||||
if u':' in line:
|
||||
exception = line.split(u'\n')[-1].split(u':')[0]
|
||||
subject = u'Bug report: %s in %s' % (exception, source)
|
||||
mailto(address=u'bugs@openlp.org', subject=subject, body=body % content)
|
||||
mailto(address=u'bugs@openlp.org', subject=subject,
|
||||
body=body % content)
|
||||
|
@ -30,24 +30,24 @@ from openlp.core.lib import translate
|
||||
|
||||
class Ui_FileRenameDialog(object):
|
||||
def setupUi(self, FileRenameDialog):
|
||||
FileRenameDialog.setObjectName("FileRenameDialog")
|
||||
FileRenameDialog.setObjectName(u'FileRenameDialog')
|
||||
FileRenameDialog.resize(400, 87)
|
||||
self.buttonBox = QtGui.QDialogButtonBox(FileRenameDialog)
|
||||
self.buttonBox.setGeometry(QtCore.QRect(210, 50, 171, 25))
|
||||
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel |
|
||||
QtGui.QDialogButtonBox.Ok)
|
||||
self.buttonBox.setObjectName("buttonBox")
|
||||
self.buttonBox.setObjectName(u'buttonBox')
|
||||
self.widget = QtGui.QWidget(FileRenameDialog)
|
||||
self.widget.setGeometry(QtCore.QRect(10, 10, 381, 35))
|
||||
self.widget.setObjectName("widget")
|
||||
self.widget.setObjectName(u'widget')
|
||||
self.horizontalLayout = QtGui.QHBoxLayout(self.widget)
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
self.FileRenameLabel = QtGui.QLabel(self.widget)
|
||||
self.FileRenameLabel.setObjectName("FileRenameLabel")
|
||||
self.horizontalLayout.addWidget(self.FileRenameLabel)
|
||||
self.FileNameEdit = QtGui.QLineEdit(self.widget)
|
||||
self.FileNameEdit.setObjectName("FileNameEdit")
|
||||
self.horizontalLayout.addWidget(self.FileNameEdit)
|
||||
self.horizontalLayout.setObjectName(u'horizontalLayout')
|
||||
self.fileRenameLabel = QtGui.QLabel(self.widget)
|
||||
self.fileRenameLabel.setObjectName(u'fileRenameLabel')
|
||||
self.horizontalLayout.addWidget(self.fileRenameLabel)
|
||||
self.fileNameEdit = QtGui.QLineEdit(self.widget)
|
||||
self.fileNameEdit.setObjectName(u'fileNameEdit')
|
||||
self.horizontalLayout.addWidget(self.fileNameEdit)
|
||||
|
||||
self.retranslateUi(FileRenameDialog)
|
||||
QtCore.QMetaObject.connectSlotsByName(FileRenameDialog)
|
||||
@ -55,6 +55,5 @@ class Ui_FileRenameDialog(object):
|
||||
def retranslateUi(self, FileRenameDialog):
|
||||
FileRenameDialog.setWindowTitle(translate('OpenLP.FileRenameForm',
|
||||
'File Rename'))
|
||||
self.FileRenameLabel.setText(translate('OpenLP.FileRenameForm',
|
||||
self.fileRenameLabel.setText(translate('OpenLP.FileRenameForm',
|
||||
'New File Name:'))
|
||||
|
||||
|
@ -148,7 +148,7 @@ class Ui_MainWindow(object):
|
||||
self.MediaManagerDock.setMinimumWidth(
|
||||
self.settingsmanager.mainwindow_left)
|
||||
self.MediaManagerDock.setObjectName(u'MediaManagerDock')
|
||||
self.MediaManagerContents = QtGui.QWidget()
|
||||
self.MediaManagerContents = QtGui.QWidget(MainWindow)
|
||||
self.MediaManagerContents.setObjectName(u'MediaManagerContents')
|
||||
self.MediaManagerLayout = QtGui.QHBoxLayout(self.MediaManagerContents)
|
||||
self.MediaManagerLayout.setContentsMargins(0, 2, 0, 0)
|
||||
|
@ -64,8 +64,7 @@ class ServiceItemEditForm(QtGui.QDialog, Ui_ServiceItemEditDialog):
|
||||
self.item._raw_frames = []
|
||||
if self.item.is_image():
|
||||
for item in self.itemList:
|
||||
self.item.add_from_image(item[u'path'], item[u'title'],
|
||||
item[u'image'])
|
||||
self.item.add_from_image(item[u'path'], item[u'title'])
|
||||
self.item.render()
|
||||
return self.item
|
||||
|
||||
|
@ -332,7 +332,8 @@ class SlideController(QtGui.QWidget):
|
||||
QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onSlideSelected)
|
||||
if not self.isLive:
|
||||
QtCore.QObject.connect(self.PreviewListWidget,
|
||||
QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), self.onGoLiveClick)
|
||||
QtCore.SIGNAL(u'doubleClicked(QModelIndex)'),
|
||||
self.onGoLiveClick)
|
||||
if isLive:
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'slidecontroller_live_spin_delay'),
|
||||
@ -466,7 +467,7 @@ class SlideController(QtGui.QWidget):
|
||||
self.Toolbar.actions[u'Stop Loop'].setVisible(False)
|
||||
if item.is_text():
|
||||
if QtCore.QSettings().value(
|
||||
self.parent.songsSettingsSection + u'/show songbar',
|
||||
self.parent.songsSettingsSection + u'/display songbar',
|
||||
QtCore.QVariant(True)).toBool() and len(self.slideList) > 0:
|
||||
self.Toolbar.makeWidgetsVisible([u'Song Menu'])
|
||||
if item.is_capable(ItemCapabilities.AllowsLoop) and \
|
||||
@ -560,7 +561,7 @@ class SlideController(QtGui.QWidget):
|
||||
[serviceItem, self.isLive, blanked, slideno])
|
||||
self.slideList = {}
|
||||
width = self.parent.ControlSplitter.sizes()[self.split]
|
||||
# Set pointing cursor when we have somthing to point at
|
||||
# Set pointing cursor when we have something to point at
|
||||
self.PreviewListWidget.setCursor(QtCore.Qt.PointingHandCursor)
|
||||
self.serviceItem = serviceItem
|
||||
self.PreviewListWidget.clear()
|
||||
|
@ -289,6 +289,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
|
||||
"""
|
||||
Run the wizard.
|
||||
"""
|
||||
log.debug(u'Editing theme %s' % self.theme.theme_name)
|
||||
self.updateThemeAllowed = False
|
||||
self.setDefaults()
|
||||
self.updateThemeAllowed = True
|
||||
@ -444,7 +445,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
|
||||
|
||||
def setPreviewTabValues(self):
|
||||
self.setField(u'name', QtCore.QVariant(self.theme.theme_name))
|
||||
if len(self.theme.theme_name) > 1:
|
||||
if len(self.theme.theme_name) > 0:
|
||||
self.themeNameEdit.setEnabled(False)
|
||||
else:
|
||||
self.themeNameEdit.setEnabled(True)
|
||||
|
@ -223,12 +223,14 @@ class ThemeManager(QtGui.QWidget):
|
||||
"""
|
||||
Renames an existing theme to a new name
|
||||
"""
|
||||
action = unicode(translate('OpenLP.ThemeManager', 'Rename'))
|
||||
if self._validate_theme_action(action):
|
||||
item = self.themeListWidget.currentItem()
|
||||
oldThemeName = unicode(item.data(QtCore.Qt.UserRole).toString())
|
||||
self.fileRenameForm.FileNameEdit.setText(oldThemeName)
|
||||
self.fileRenameForm.fileNameEdit.setText(oldThemeName)
|
||||
self.saveThemeName = u''
|
||||
if self.fileRenameForm.exec_():
|
||||
newThemeName = unicode(self.fileRenameForm.FileNameEdit.text())
|
||||
newThemeName = unicode(self.fileRenameForm.fileNameEdit.text())
|
||||
oldThemeData = self.getThemeData(oldThemeName)
|
||||
self.deleteTheme(oldThemeName)
|
||||
self.cloneThemeData(oldThemeData, newThemeName)
|
||||
@ -239,10 +241,10 @@ class ThemeManager(QtGui.QWidget):
|
||||
"""
|
||||
item = self.themeListWidget.currentItem()
|
||||
oldThemeName = unicode(item.data(QtCore.Qt.UserRole).toString())
|
||||
self.fileRenameForm.FileNameEdit.setText(oldThemeName)
|
||||
self.fileRenameForm.fileNameEdit.setText(oldThemeName)
|
||||
self.saveThemeName = u''
|
||||
if self.fileRenameForm.exec_():
|
||||
newThemeName = unicode(self.fileRenameForm.FileNameEdit.text())
|
||||
newThemeName = unicode(self.fileRenameForm.fileNameEdit.text())
|
||||
themeData = self.getThemeData(oldThemeName)
|
||||
self.cloneThemeData(themeData, newThemeName)
|
||||
self.loadThemes()
|
||||
@ -286,44 +288,10 @@ class ThemeManager(QtGui.QWidget):
|
||||
"""
|
||||
Delete a theme
|
||||
"""
|
||||
self.global_theme = unicode(QtCore.QSettings().value(
|
||||
self.settingsSection + u'/global theme',
|
||||
QtCore.QVariant(u'')).toString())
|
||||
if check_item_selected(self.themeListWidget,
|
||||
translate('OpenLP.ThemeManager',
|
||||
'You must select a theme to delete.')):
|
||||
action = unicode(translate('OpenLP.ThemeManager', 'Delete'))
|
||||
if self._validate_theme_action(action):
|
||||
item = self.themeListWidget.currentItem()
|
||||
theme = unicode(item.text())
|
||||
# confirm deletion
|
||||
answer = QtGui.QMessageBox.question(self,
|
||||
translate('OpenLP.ThemeManager', 'Delete Confirmation'),
|
||||
unicode(translate('OpenLP.ThemeManager', 'Delete %s theme?'))
|
||||
% theme,
|
||||
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes |
|
||||
QtGui.QMessageBox.No), QtGui.QMessageBox.No)
|
||||
if answer == QtGui.QMessageBox.No:
|
||||
return
|
||||
# should be the same unless default
|
||||
if theme != unicode(item.data(QtCore.Qt.UserRole).toString()):
|
||||
QtGui.QMessageBox.critical(self,
|
||||
translate('OpenLP.ThemeManager', 'Error'),
|
||||
translate('OpenLP.ThemeManager',
|
||||
'You are unable to delete the default theme.'))
|
||||
else:
|
||||
for plugin in self.parent.pluginManager.plugins:
|
||||
if plugin.usesTheme(theme):
|
||||
QtGui.QMessageBox.critical(self,
|
||||
translate('OpenLP.ThemeManager', 'Error'),
|
||||
unicode(translate('OpenLP.ThemeManager',
|
||||
'Theme %s is used in the %s plugin.')) % \
|
||||
(theme, plugin.name))
|
||||
return
|
||||
if unicode(self.serviceComboBox.currentText()) == theme:
|
||||
QtGui.QMessageBox.critical(self,
|
||||
translate('OpenLP.ThemeManager', 'Error'),
|
||||
unicode(translate('OpenLP.ThemeManager',
|
||||
'Theme %s is used by the service manager.')) % theme)
|
||||
return
|
||||
row = self.themeListWidget.row(item)
|
||||
self.themeListWidget.takeItem(row)
|
||||
self.deleteTheme(theme)
|
||||
@ -782,3 +750,49 @@ class ThemeManager(QtGui.QWidget):
|
||||
theme.parse(themeXml)
|
||||
theme.extend_image_filename(path)
|
||||
return theme
|
||||
|
||||
def _validate_theme_action(self, action):
|
||||
"""
|
||||
Check to see if theme has been selected and the destructive action
|
||||
is allowed.
|
||||
"""
|
||||
self.global_theme = unicode(QtCore.QSettings().value(
|
||||
self.settingsSection + u'/global theme',
|
||||
QtCore.QVariant(u'')).toString())
|
||||
if check_item_selected(self.themeListWidget,
|
||||
unicode(translate('OpenLP.ThemeManager',
|
||||
'You must select a theme to %s.')) % action):
|
||||
item = self.themeListWidget.currentItem()
|
||||
theme = unicode(item.text())
|
||||
# confirm deletion
|
||||
answer = QtGui.QMessageBox.question(self,
|
||||
unicode(translate('OpenLP.ThemeManager', '%s Confirmation'))
|
||||
% action,
|
||||
unicode(translate('OpenLP.ThemeManager', '%s %s theme?'))
|
||||
% (action, theme),
|
||||
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes |
|
||||
QtGui.QMessageBox.No), QtGui.QMessageBox.No)
|
||||
if answer == QtGui.QMessageBox.No:
|
||||
return False
|
||||
# should be the same unless default
|
||||
if theme != unicode(item.data(QtCore.Qt.UserRole).toString()):
|
||||
QtGui.QMessageBox.critical(self,
|
||||
translate('OpenLP.ThemeManager', 'Error'),
|
||||
translate('OpenLP.ThemeManager',
|
||||
'You are unable to delete the default theme.'))
|
||||
else:
|
||||
for plugin in self.parent.pluginManager.plugins:
|
||||
if plugin.usesTheme(theme):
|
||||
QtGui.QMessageBox.critical(self,
|
||||
translate('OpenLP.ThemeManager', 'Error'),
|
||||
unicode(translate('OpenLP.ThemeManager',
|
||||
'Theme %s is used in the %s plugin.')) % \
|
||||
(theme, plugin.name))
|
||||
return False
|
||||
if unicode(self.serviceComboBox.currentText()) == theme:
|
||||
QtGui.QMessageBox.critical(self,
|
||||
translate('OpenLP.ThemeManager', 'Error'),
|
||||
unicode(translate('OpenLP.ThemeManager',
|
||||
'Theme %s is used by the service manager.')) % theme)
|
||||
return False
|
||||
return True
|
||||
|
@ -555,7 +555,8 @@ class Ui_ThemeWizard(object):
|
||||
u'footerDefaultPositionCheckBox')
|
||||
self.footerPositionLayout.setWidget(0, QtGui.QFormLayout.FieldRole,
|
||||
self.footerDefaultPositionCheckBox)
|
||||
self.areaPositionLayout.addWidget(self.footerPositionGroupBox, 1, 1, 1, 1)
|
||||
self.areaPositionLayout.addWidget(
|
||||
self.footerPositionGroupBox, 1, 1, 1, 1)
|
||||
ThemeWizard.addPage(self.areaPositionPage)
|
||||
self.previewPage = QtGui.QWizardPage()
|
||||
self.previewPage.setObjectName(u'previewPage')
|
||||
@ -733,18 +734,24 @@ class Ui_ThemeWizard(object):
|
||||
self.mainWidthSpinBox.setSuffix(translate('OpenLP.ThemeWizard', 'px'))
|
||||
self.mainWidthLabel.setText(translate('OpenLP.ThemeWizard', 'Width:'))
|
||||
self.mainHeightSpinBox.setSuffix(translate('OpenLP.ThemeWizard', 'px'))
|
||||
self.mainHeightLabel.setText(translate('OpenLP.ThemeWizard', 'Height:'))
|
||||
self.mainHeightLabel.setText(
|
||||
translate('OpenLP.ThemeWizard', 'Height:'))
|
||||
self.footerPositionGroupBox.setTitle(
|
||||
translate('OpenLP.ThemeWizard', 'Footer Area'))
|
||||
self.footerXLabel.setText(translate('OpenLP.ThemeWizard', 'X position:'))
|
||||
self.footerXLabel.setText(
|
||||
translate('OpenLP.ThemeWizard', 'X position:'))
|
||||
self.footerXSpinBox.setSuffix(translate('OpenLP.ThemeWizard', 'px'))
|
||||
self.footerYLabel.setText(translate('OpenLP.ThemeWizard', 'Y position:'))
|
||||
self.footerYLabel.setText(
|
||||
translate('OpenLP.ThemeWizard', 'Y position:'))
|
||||
self.footerYSpinBox.setSuffix(translate('OpenLP.ThemeWizard', 'px'))
|
||||
self.footerWidthLabel.setText(translate('OpenLP.ThemeWizard', 'Width:'))
|
||||
self.footerWidthSpinBox.setSuffix(translate('OpenLP.ThemeWizard', 'px'))
|
||||
self.footerWidthLabel.setText(
|
||||
translate('OpenLP.ThemeWizard', 'Width:'))
|
||||
self.footerWidthSpinBox.setSuffix(
|
||||
translate('OpenLP.ThemeWizard', 'px'))
|
||||
self.footerHeightLabel.setText(
|
||||
translate('OpenLP.ThemeWizard', 'Height:'))
|
||||
self.footerHeightSpinBox.setSuffix(translate('OpenLP.ThemeWizard', 'px'))
|
||||
self.footerHeightSpinBox.setSuffix(
|
||||
translate('OpenLP.ThemeWizard', 'px'))
|
||||
self.footerDefaultPositionCheckBox.setText(
|
||||
translate('OpenLP.ThemeWizard', 'Use default location'))
|
||||
self.previewPage.setTitle(
|
||||
|
@ -171,11 +171,10 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog):
|
||||
# We found '<>' in the alert text, but the ParameterEdit field is
|
||||
# empty.
|
||||
if text.find(u'<>') != -1 and not self.ParameterEdit.text() and \
|
||||
QtGui.QMessageBox.question(self, translate(
|
||||
'AlertPlugin.AlertForm', 'No Parameter found'),
|
||||
QtGui.QMessageBox.question(self,
|
||||
translate('AlertPlugin.AlertForm', 'No Parameter found'),
|
||||
translate('AlertPlugin.AlertForm', 'You have not entered a '
|
||||
'parameter to be replaced.\nDo you want to continue '
|
||||
'anyway?'),
|
||||
'parameter to be replaced.\nDo you want to continue anyway?'),
|
||||
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.No |
|
||||
QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.No:
|
||||
self.ParameterEdit.setFocus()
|
||||
@ -183,8 +182,8 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog):
|
||||
# The ParameterEdit field is not empty, but we have not found '<>'
|
||||
# in the alert text.
|
||||
elif text.find(u'<>') == -1 and self.ParameterEdit.text() and \
|
||||
QtGui.QMessageBox.question(self, translate(
|
||||
'AlertPlugin.AlertForm', 'No Placeholder found'),
|
||||
QtGui.QMessageBox.question(self,
|
||||
translate('AlertPlugin.AlertForm', 'No Placeholder found'),
|
||||
translate('AlertPlugin.AlertForm', 'The alert text does not'
|
||||
' contain \'<>\'.\nDo want to continue anyway?'),
|
||||
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.No |
|
||||
|
@ -43,10 +43,12 @@ class WebDownload(object):
|
||||
Unknown = -1
|
||||
Crosswalk = 0
|
||||
BibleGateway = 1
|
||||
Bibleserver = 2
|
||||
|
||||
Names = {
|
||||
0: u'Crosswalk',
|
||||
1: u'BibleGateway'
|
||||
1: u'BibleGateway',
|
||||
2: u'Bibleserver'
|
||||
}
|
||||
|
||||
@classmethod
|
||||
@ -232,8 +234,7 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard):
|
||||
The index of the combo box.
|
||||
"""
|
||||
self.bibleComboBox.clear()
|
||||
bibles = [unicode(translate('BiblesPlugin.ImportWizardForm', bible)) for
|
||||
bible in self.web_bible_list[index].keys()]
|
||||
bibles = self.web_bible_list[index].keys()
|
||||
bibles.sort()
|
||||
for bible in bibles:
|
||||
self.bibleComboBox.addItem(bible)
|
||||
@ -252,14 +253,16 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard):
|
||||
"""
|
||||
self.getFileName(
|
||||
translate('BiblesPlugin.ImportWizardForm', 'Open Books CSV File'),
|
||||
self.booksLocationEdit)
|
||||
self.booksLocationEdit, u'%s (*.csv)'
|
||||
% translate('BiblesPlugin.ImportWizardForm', 'CSV File'))
|
||||
|
||||
def onCsvVersesFileButtonClicked(self):
|
||||
"""
|
||||
Show the file open dialog for the verses CSV file.
|
||||
"""
|
||||
self.getFileName(translate('BiblesPlugin.ImportWizardForm',
|
||||
'Open Verses CSV File'), self.csvVerseLocationEdit)
|
||||
'Open Verses CSV File'), self.csvVerseLocationEdit, u'%s (*.csv)'
|
||||
% translate('BiblesPlugin.ImportWizardForm', 'CSV File'))
|
||||
|
||||
def onOpenSongBrowseButtonClicked(self):
|
||||
"""
|
||||
@ -275,7 +278,9 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard):
|
||||
"""
|
||||
self.getFileName(
|
||||
translate('BiblesPlugin.ImportWizardForm',
|
||||
'Open openlp.org 1.x Bible'), self.openlp1LocationEdit)
|
||||
'Open openlp.org 1.x Bible'), self.openlp1LocationEdit,
|
||||
u'%s (*.bible)' % translate('BiblesPlugin.ImportWizardForm',
|
||||
'openlp.org 1.x bible'))
|
||||
|
||||
def onCurrentIdChanged(self, pageId):
|
||||
if pageId == 3:
|
||||
@ -338,31 +343,27 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard):
|
||||
"""
|
||||
Load the list of Crosswalk and BibleGateway bibles.
|
||||
"""
|
||||
# Load and store Crosswalk Bibles.
|
||||
# Load Crosswalk Bibles.
|
||||
filepath = AppLocation.get_directory(AppLocation.PluginsDir)
|
||||
filepath = os.path.join(filepath, u'bibles', u'resources')
|
||||
books_file = None
|
||||
try:
|
||||
self.web_bible_list[WebDownload.Crosswalk] = {}
|
||||
books_file = open(
|
||||
os.path.join(filepath, u'crosswalkbooks.csv'), 'r')
|
||||
os.path.join(filepath, u'crosswalkbooks.csv'), 'rb')
|
||||
dialect = csv.Sniffer().sniff(books_file.read(1024))
|
||||
books_file.seek(0)
|
||||
books_reader = csv.reader(books_file, dialect)
|
||||
for line in books_reader:
|
||||
ver = line[0]
|
||||
name = line[1]
|
||||
if not isinstance(ver, unicode):
|
||||
ver = unicode(ver, u'utf8')
|
||||
if not isinstance(name, unicode):
|
||||
name = unicode(name, u'utf8')
|
||||
ver = unicode(line[0], u'utf-8')
|
||||
name = unicode(line[1], u'utf-8')
|
||||
self.web_bible_list[WebDownload.Crosswalk][ver] = name.strip()
|
||||
except IOError:
|
||||
log.exception(u'Crosswalk resources missing')
|
||||
finally:
|
||||
if books_file:
|
||||
books_file.close()
|
||||
# Load and store BibleGateway Bibles.
|
||||
# Load BibleGateway Bibles.
|
||||
books_file = None
|
||||
try:
|
||||
self.web_bible_list[WebDownload.BibleGateway] = {}
|
||||
@ -384,10 +385,50 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard):
|
||||
finally:
|
||||
if books_file:
|
||||
books_file.close()
|
||||
# Load and Bibleserver Bibles.
|
||||
filepath = AppLocation.get_directory(AppLocation.PluginsDir)
|
||||
filepath = os.path.join(filepath, u'bibles', u'resources')
|
||||
books_file = None
|
||||
try:
|
||||
self.web_bible_list[WebDownload.Bibleserver] = {}
|
||||
books_file = open(
|
||||
os.path.join(filepath, u'bibleserver.csv'), 'rb')
|
||||
dialect = csv.Sniffer().sniff(books_file.read(1024))
|
||||
books_file.seek(0)
|
||||
books_reader = csv.reader(books_file, dialect)
|
||||
for line in books_reader:
|
||||
ver = unicode(line[0], u'utf-8')
|
||||
name = unicode(line[1], u'utf-8')
|
||||
self.web_bible_list[WebDownload.Bibleserver][ver] = name.strip()
|
||||
except IOError, UnicodeError:
|
||||
log.exception(u'Bibleserver resources missing')
|
||||
finally:
|
||||
if books_file:
|
||||
books_file.close()
|
||||
|
||||
def getFileName(self, title, editbox):
|
||||
def getFileName(self, title, editbox, filters=u''):
|
||||
"""
|
||||
Opens a QFileDialog and saves the filename to the given editbox.
|
||||
|
||||
``title``
|
||||
The title of the dialog (unicode).
|
||||
|
||||
``editbox``
|
||||
A editbox (QLineEdit).
|
||||
|
||||
``filters``
|
||||
The file extension filters. It should contain the file description as
|
||||
well as the file extension. For example::
|
||||
|
||||
u'openlp.org 1.x bible (*.bible)'
|
||||
"""
|
||||
if filters:
|
||||
filters += u';;'
|
||||
filters += u'%s (*)' % translate('BiblesPlugin.ImportWizardForm',
|
||||
'All Files')
|
||||
filename = QtGui.QFileDialog.getOpenFileName(self, title,
|
||||
SettingsManager.get_last_dir(self.bibleplugin.settingsSection, 1))
|
||||
os.path.dirname(SettingsManager.get_last_dir(
|
||||
self.bibleplugin.settingsSection, 1)), filters)
|
||||
if filename:
|
||||
editbox.setText(filename)
|
||||
SettingsManager.set_last_dir(
|
||||
@ -457,6 +498,9 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard):
|
||||
elif download_location == WebDownload.BibleGateway:
|
||||
bible = \
|
||||
self.web_bible_list[WebDownload.BibleGateway][bible_version]
|
||||
elif download_location == WebDownload.Bibleserver:
|
||||
bible = \
|
||||
self.web_bible_list[WebDownload.Bibleserver][bible_version]
|
||||
importer = self.manager.import_bible(
|
||||
BibleFormat.WebDownload,
|
||||
name=license_version,
|
||||
|
@ -208,6 +208,7 @@ class Ui_BibleImportWizard(object):
|
||||
self.locationComboBox.setObjectName(u'LocationComboBox')
|
||||
self.locationComboBox.addItem(u'')
|
||||
self.locationComboBox.addItem(u'')
|
||||
self.locationComboBox.addItem(u'')
|
||||
self.downloadOptionsLayout.setWidget(0, QtGui.QFormLayout.FieldRole,
|
||||
self.locationComboBox)
|
||||
self.bibleLabel = QtGui.QLabel(self.downloadOptionsTab)
|
||||
@ -388,6 +389,8 @@ class Ui_BibleImportWizard(object):
|
||||
translate('BiblesPlugin.ImportWizardForm', 'Crosswalk'))
|
||||
self.locationComboBox.setItemText(1,
|
||||
translate('BiblesPlugin.ImportWizardForm', 'BibleGateway'))
|
||||
self.locationComboBox.setItemText(2,
|
||||
translate('BiblesPlugin.ImportWizardForm', 'Bibleserver'))
|
||||
self.bibleLabel.setText(
|
||||
translate('BiblesPlugin.ImportWizardForm', 'Bible:'))
|
||||
self.webDownloadTabWidget.setTabText(
|
||||
|
@ -32,134 +32,164 @@ import re
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
BIBLE_REFERENCE = re.compile(
|
||||
r'^([\w ]+?) *([0-9]+)' # Initial book and chapter
|
||||
r'(?: *[:|v|V] *([0-9]+))?' # Verse for first chapter
|
||||
r'(?: *- *([0-9]+|end$))?' # Range for verses or chapters
|
||||
r'(?:(?:,([0-9]+))?' # Second chapter
|
||||
r' *[,|:|v|V] *([0-9]+|end$)' # More range for verses or chapters
|
||||
r'(?: *- *([0-9]+|end$))?)?$', # End of second verse range
|
||||
re.UNICODE)
|
||||
def get_reference_match(match_type):
|
||||
local_separator = unicode(u':;;\s*[:vV]\s*;;-;;\s*-\s*;;,;;\s*,\s*;;end'
|
||||
).split(u';;') # English
|
||||
# local_separator = unicode(u',;;\s*,\s*;;-;;\s*-\s*;;.;;\.;;[Ee]nde'
|
||||
# ).split(u';;') # German
|
||||
separators = {
|
||||
u'sep_v_display': local_separator[0], u'sep_v': local_separator[1],
|
||||
u'sep_r_display': local_separator[2], u'sep_r': local_separator[3],
|
||||
u'sep_l_display': local_separator[4], u'sep_l': local_separator[5],
|
||||
u'sep_e': local_separator[6]}
|
||||
|
||||
def check_end(match_group):
|
||||
"""
|
||||
Check if a regular expression match group contains the text u'end' or
|
||||
should be converted to an int.
|
||||
|
||||
``match_group``
|
||||
The match group to check.
|
||||
"""
|
||||
if match_group == u'end':
|
||||
return -1
|
||||
# verse range match: (<chapter>:)?<verse>(-((<chapter>:)?<verse>|end)?)?
|
||||
range_string = str(r'(?:(?P<from_chapter>[0-9]+)%(sep_v)s)?(?P<from_verse>'
|
||||
r'[0-9]+)(?P<range_to>%(sep_r)s(?:(?:(?P<to_chapter>[0-9]+)%(sep_v)s)?'
|
||||
r'(?P<to_verse>[0-9]+)|%(sep_e)s)?)?') % separators
|
||||
if match_type == u'range':
|
||||
return re.compile(r'^\s*' + range_string + r'\s*$', re.UNICODE)
|
||||
elif match_type == u'range_separator':
|
||||
return re.compile(separators[u'sep_l'])
|
||||
elif match_type == u'full':
|
||||
# full reference match: <book>(<range>(,|(?=$)))+
|
||||
return re.compile(str(r'^\s*(?!\s)(?P<book>[\d]*[^\d]+)(?<!\s)\s*'
|
||||
r'(?P<ranges>(?:' + range_string + r'(?:%(sep_l)s|(?=\s*$)))+)\s*$')
|
||||
% separators, re.UNICODE)
|
||||
else:
|
||||
return int(match_group)
|
||||
return separators[match_type]
|
||||
|
||||
def parse_reference(reference):
|
||||
"""
|
||||
This is the über-awesome function that takes a person's typed in string
|
||||
and converts it to a reference list, a list of references to be queried
|
||||
from the Bible database files.
|
||||
This is the next generation über-awesome function that takes a person's
|
||||
typed in string and converts it to a reference list, a list of references to
|
||||
be queried from the Bible database files.
|
||||
|
||||
The ``BIBLE_REFERENCE`` constant regular expression produces the following
|
||||
match groups:
|
||||
This is a user manual like description, how the references are working.
|
||||
|
||||
0. (match string)
|
||||
This is a special group consisting of the whole string that matched.
|
||||
1. ``[\w ]+``
|
||||
The book the reference is from.
|
||||
2. ``[0-9]+``
|
||||
The first (or only) chapter in the reference.
|
||||
3. ``None`` or ``[0-9]+``
|
||||
``None``, or the only verse, or the first verse in a verse range or,
|
||||
the start verse in a chapter range.
|
||||
4. ``None`` or ``[0-9]+`` or ``end``
|
||||
``None``, or the end verse of the first verse range, or the end chapter
|
||||
of a chapter range.
|
||||
5. ``None`` or ``[0-9]+``
|
||||
``None``, or the second chapter in multiple (non-ranged) chapters.
|
||||
6. ``None`` or ``[0-9]+`` or ``end``
|
||||
``None``, the start of the second verse range. or the end of a chapter
|
||||
range.
|
||||
7. ``None`` or ``[0-9]+`` or ``end``
|
||||
``None``, or the end of the second verse range.
|
||||
- Each reference starts with the book name. A chapter name is manditory.
|
||||
``John 3`` refers to Gospel of John chapter 3
|
||||
- A reference range can be given after a range separator.
|
||||
``John 3-5`` refers to John chapters 3 to 5
|
||||
- Single verses can be addressed after a verse separator
|
||||
``John 3:16`` refers to John chapter 3 verse 16
|
||||
``John 3:16-4:3`` refers to John chapter 3 verse 16 to chapter 4 verse 3
|
||||
- After a verse reference all further single values are treat as verse in
|
||||
the last selected chapter.
|
||||
``John 3:16-18`` refers to John chapter 3 verses 16 to 18
|
||||
- After a list separator it is possible to refer to additional verses. They
|
||||
are build analog to the first ones. This way it is possible to define each
|
||||
number of verse references. It is not possible to refer to verses in
|
||||
additional books.
|
||||
``John 3:16,18`` refers to John chapter 3 verses 16 and 18
|
||||
``John 3:16-18,20`` refers to John chapter 3 verses 16 to 18 and 20
|
||||
``John 3:16-18,4:1`` refers to John chapter 3 verses 16 to 18 and
|
||||
chapter 3 verse 1
|
||||
- If there is a range separator without further verse declaration the last
|
||||
refered chapter is addressed until the end.
|
||||
|
||||
``range_string`` is a regular expression which matches for verse range
|
||||
declarations:
|
||||
|
||||
1. ``(?:(?P<from_chapter>[0-9]+)%(sep_v)s)?'
|
||||
It starts with a optional chapter reference ``from_chapter`` followed by
|
||||
a verse separator.
|
||||
2. ``(?P<from_verse>[0-9]+)``
|
||||
The verse reference ``from_verse`` is manditory
|
||||
3. ``(?P<range_to>%(sep_r)s(?:`` ... ``|%(sep_e)s)?)?``
|
||||
A ``range_to`` declaration is optional. It starts with a range separator
|
||||
and contains optional a chapter and verse declaration or a end
|
||||
separator.
|
||||
4. ``(?:(?P<to_chapter>[0-9]+)%(sep_v)s)?``
|
||||
The ``to_chapter`` reference with separator is equivalent to group 1.
|
||||
5. ``(?P<to_verse>[0-9]+)``
|
||||
The ``to_verse`` reference is equivalent to group 2.
|
||||
|
||||
The full reference is matched against get_reference_match(u'full'). This
|
||||
regular expression looks like this:
|
||||
|
||||
1. ``^\s*(?!\s)(?P<book>[\d]*[^\d]+)(?<!\s)\s*``
|
||||
The ``book`` group starts with the first non-whitespace character. There
|
||||
are optional leading digits followed by non-digits. The group ends
|
||||
before the whitspace in front of the next digit.
|
||||
2. ``(?P<ranges>(?:`` + range_string + ``(?:%(sep_l)s|(?=\s*$)))+)\s*$``
|
||||
The second group contains all ``ranges``. This can be multiple
|
||||
declarations of a range_string separated by a list separator.
|
||||
|
||||
The reference list is a list of tuples, with each tuple structured like
|
||||
this::
|
||||
|
||||
(book, chapter, start_verse, end_verse)
|
||||
(book, chapter, from_verse, to_verse)
|
||||
|
||||
``reference``
|
||||
The bible reference to parse.
|
||||
|
||||
Returns None or a reference list.
|
||||
"""
|
||||
reference = reference.strip()
|
||||
log.debug('parse_reference("%s")', reference)
|
||||
unified_ref_list = []
|
||||
match = BIBLE_REFERENCE.match(reference)
|
||||
match = get_reference_match(u'full').match(reference)
|
||||
if match:
|
||||
log.debug(u'Matched reference %s' % reference)
|
||||
book = match.group(1)
|
||||
chapter = int(match.group(2))
|
||||
if match.group(7):
|
||||
# Two verse ranges
|
||||
vr1_start = int(match.group(3))
|
||||
vr1_end = int(match.group(4))
|
||||
unified_ref_list.append((book, chapter, vr1_start, vr1_end))
|
||||
vr2_start = int(match.group(6))
|
||||
vr2_end = check_end(match.group(7))
|
||||
if match.group(5):
|
||||
# One verse range per chapter
|
||||
chapter2 = int(match.group(5))
|
||||
unified_ref_list.append((book, chapter2, vr2_start, vr2_end))
|
||||
book = match.group(u'book')
|
||||
ranges = match.group(u'ranges')
|
||||
range_list = get_reference_match(u'range_separator').split(ranges)
|
||||
ref_list = []
|
||||
chapter = None
|
||||
for this_range in range_list:
|
||||
range_match = get_reference_match(u'range').match(this_range)
|
||||
from_chapter = range_match.group(u'from_chapter')
|
||||
from_verse = range_match.group(u'from_verse')
|
||||
has_range = range_match.group(u'range_to')
|
||||
to_chapter = range_match.group(u'to_chapter')
|
||||
to_verse = range_match.group(u'to_verse')
|
||||
if from_chapter:
|
||||
from_chapter = int(from_chapter)
|
||||
if from_verse:
|
||||
from_verse = int(from_verse)
|
||||
if to_chapter:
|
||||
to_chapter = int(to_chapter)
|
||||
if to_verse:
|
||||
to_verse = int(to_verse)
|
||||
# Fill chapter fields with reasonable values.
|
||||
if from_chapter:
|
||||
chapter = from_chapter
|
||||
elif chapter:
|
||||
from_chapter = chapter
|
||||
else:
|
||||
unified_ref_list.append((book, chapter, vr2_start, vr2_end))
|
||||
elif match.group(6):
|
||||
# Chapter range with verses
|
||||
if match.group(3):
|
||||
vr1_start = int(match.group(3))
|
||||
from_chapter = from_verse
|
||||
from_verse = None
|
||||
if to_chapter:
|
||||
if to_chapter < from_chapter:
|
||||
continue
|
||||
else:
|
||||
vr1_start = 1
|
||||
if match.group(2) == match.group(4):
|
||||
vr1_end = int(match.group(6))
|
||||
unified_ref_list.append((book, chapter, vr1_start, vr1_end))
|
||||
chapter = to_chapter
|
||||
elif to_verse:
|
||||
if chapter:
|
||||
to_chapter = chapter
|
||||
else:
|
||||
vr1_end = -1
|
||||
unified_ref_list.append((book, chapter, vr1_start, vr1_end))
|
||||
vr2_end = check_end(match.group(6))
|
||||
if int(match.group(4)) > chapter:
|
||||
for i in range(chapter + 1, int(match.group(4)) + 1):
|
||||
if i == int(match.group(4)):
|
||||
unified_ref_list.append((book, i, 1, vr2_end))
|
||||
to_chapter = to_verse
|
||||
to_verse = None
|
||||
# Append references to the list
|
||||
if has_range:
|
||||
if not from_verse:
|
||||
from_verse = 1
|
||||
if not to_verse:
|
||||
to_verse = -1
|
||||
if to_chapter > from_chapter:
|
||||
ref_list.append((book, from_chapter, from_verse, -1))
|
||||
for i in range(from_chapter + 1, to_chapter - 1):
|
||||
ref_list.append((book, i, 1, -1))
|
||||
ref_list.append((book, to_chapter, 1, to_verse))
|
||||
elif to_verse >= from_verse or to_verse == -1:
|
||||
ref_list.append((book, from_chapter, from_verse, to_verse))
|
||||
elif from_verse:
|
||||
ref_list.append((book, from_chapter, from_verse, from_verse))
|
||||
else:
|
||||
unified_ref_list.append((book, i, 1, -1))
|
||||
elif match.group(4):
|
||||
# Chapter range or chapter and verse range
|
||||
if match.group(3):
|
||||
vr1_start = int(match.group(3))
|
||||
vr1_end = check_end(match.group(4))
|
||||
if vr1_end == -1 or vr1_end > vr1_start:
|
||||
unified_ref_list.append((book, chapter, vr1_start, vr1_end))
|
||||
else:
|
||||
log.debug(u'Ambiguous reference: %s' % reference)
|
||||
return None
|
||||
elif match.group(4) != u'end':
|
||||
for i in range(chapter, int(match.group(4)) + 1):
|
||||
unified_ref_list.append((book, i, 1, -1))
|
||||
else:
|
||||
log.debug(u'Unsupported reference: %s' % reference)
|
||||
return None
|
||||
elif match.group(3):
|
||||
# Single chapter and verse
|
||||
verse = int(match.group(3))
|
||||
unified_ref_list.append((book, chapter, verse, verse))
|
||||
else:
|
||||
# Single chapter
|
||||
unified_ref_list.append((book, chapter, -1, -1))
|
||||
ref_list.append((book, from_chapter, 1, -1))
|
||||
return ref_list
|
||||
else:
|
||||
log.debug(u'Invalid reference: %s' % reference)
|
||||
return None
|
||||
return unified_ref_list
|
||||
|
||||
|
||||
class SearchResults(object):
|
||||
|
@ -240,6 +240,67 @@ class BGExtract(object):
|
||||
return SearchResults(bookname, chapter, verse_list)
|
||||
|
||||
|
||||
class BSExtract(object):
|
||||
"""
|
||||
Extract verses from Bibleserver.com
|
||||
"""
|
||||
def __init__(self, proxyurl=None):
|
||||
log.debug(u'init %s', proxyurl)
|
||||
self.proxyurl = proxyurl
|
||||
|
||||
def get_bible_chapter(self, version, bookname, chapter):
|
||||
"""
|
||||
Access and decode bibles via Bibleserver mobile website
|
||||
|
||||
``version``
|
||||
The version of the bible like NIV for New International Version
|
||||
|
||||
``bookname``
|
||||
Text name of bible book e.g. Genesis, 1. John, 1John or Offenbarung
|
||||
|
||||
``chapter``
|
||||
Chapter number
|
||||
"""
|
||||
log.debug(u'get_bible_chapter %s,%s,%s', version, bookname, chapter)
|
||||
chapter_url = u'http://m.bibleserver.com/text/%s/%s%s' % \
|
||||
(version, bookname, chapter)
|
||||
|
||||
log.debug(u'URL: %s', chapter_url)
|
||||
page = None
|
||||
try:
|
||||
page = urllib2.urlopen(chapter_url)
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
except urllib2.URLError:
|
||||
log.exception(u'The web bible page could not be downloaded.')
|
||||
finally:
|
||||
if not page:
|
||||
return None
|
||||
soup = None
|
||||
try:
|
||||
soup = BeautifulSoup(page)
|
||||
except HTMLParseError:
|
||||
log.exception(u'BeautifulSoup could not parse the bible page.')
|
||||
finally:
|
||||
if not soup:
|
||||
return None
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
content = None
|
||||
try:
|
||||
content = soup.find(u'div', u'content').find(u'div').findAll(u'div')
|
||||
except:
|
||||
log.exception(u'No verses found.')
|
||||
finally:
|
||||
if not content:
|
||||
return None
|
||||
verse_number = re.compile(r'v(\d{2})(\d{3})(\d{3}) verse')
|
||||
verses = {}
|
||||
for verse in content:
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
versenumber = int(verse_number.sub(r'\3', verse[u'class']))
|
||||
verses[versenumber] = verse.contents[1].rstrip(u'\n')
|
||||
return SearchResults(bookname, chapter, verses)
|
||||
|
||||
|
||||
class CWExtract(object):
|
||||
"""
|
||||
Extract verses from CrossWalk/BibleStudyTools
|
||||
@ -350,7 +411,7 @@ class HTTPBible(BibleDB):
|
||||
Run the import. This method overrides the parent class method. Returns
|
||||
``True`` on success, ``False`` on failure.
|
||||
"""
|
||||
self.wizard.ImportProgressBar.setMaximum(2)
|
||||
self.wizard.importProgressBar.setMaximum(2)
|
||||
self.wizard.incrementProgressBar('Registering bible...')
|
||||
self.create_meta(u'download source', self.download_source)
|
||||
self.create_meta(u'download name', self.download_name)
|
||||
@ -426,8 +487,10 @@ class HTTPBible(BibleDB):
|
||||
log.debug(u'source = %s', self.download_source)
|
||||
if self.download_source.lower() == u'crosswalk':
|
||||
ev = CWExtract(self.proxy_server)
|
||||
else:
|
||||
elif self.download_source.lower() == u'biblegateway':
|
||||
ev = BGExtract(self.proxy_server)
|
||||
elif self.download_source.lower() == u'bibleserver':
|
||||
ev = BSExtract(self.proxy_server)
|
||||
return ev.get_bible_chapter(self.download_name, book, chapter)
|
||||
|
||||
def get_books(self):
|
||||
|
@ -112,6 +112,7 @@ class BibleFormat(object):
|
||||
def get_availability(format):
|
||||
return BibleFormat._format_availability.get(format, True)
|
||||
|
||||
|
||||
class BibleManager(object):
|
||||
"""
|
||||
The Bible manager which holds and manages all the Bibles.
|
||||
@ -311,7 +312,7 @@ class BibleManager(object):
|
||||
'Scripture Reference Error'),
|
||||
translate('BiblesPlugin.BibleManager', 'You did not enter a '
|
||||
'search keyword.\nYou can separate different keywords by a '
|
||||
'space to search for all of your keywords and you can seperate '
|
||||
'space to search for all of your keywords and you can separate '
|
||||
'them by a comma to search for one of them.'))
|
||||
return None
|
||||
|
||||
@ -356,3 +357,4 @@ class BibleManager(object):
|
||||
BibleFormat.set_availability(BibleFormat.OpenLP1, has_openlp1)
|
||||
|
||||
__all__ = [u'BibleFormat']
|
||||
|
||||
|
@ -32,6 +32,7 @@ from PyQt4 import QtCore, QtGui
|
||||
from openlp.core.lib import MediaManagerItem, Receiver, BaseListWithDnD, \
|
||||
ItemCapabilities, translate
|
||||
from openlp.plugins.bibles.forms import BibleImportForm
|
||||
from openlp.plugins.bibles.lib import get_reference_match
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -72,7 +73,7 @@ class BibleMediaItem(MediaManagerItem):
|
||||
self.hasNewIcon = False
|
||||
self.hasEditIcon = False
|
||||
self.hasDeleteIcon = False
|
||||
self.addToServiceItem = True
|
||||
self.addToServiceItem = False
|
||||
|
||||
def addEndHeaderBar(self):
|
||||
self.SearchTabWidget = QtGui.QTabWidget(self)
|
||||
@ -553,12 +554,15 @@ class BibleMediaItem(MediaManagerItem):
|
||||
bible = unicode(self.AdvancedVersionComboBox.currentText())
|
||||
second_bible = unicode(self.AdvancedSecondBibleComboBox.currentText())
|
||||
book = unicode(self.AdvancedBookComboBox.currentText())
|
||||
chapter_from = int(self.AdvancedFromChapter.currentText())
|
||||
chapter_to = int(self.AdvancedToChapter.currentText())
|
||||
verse_from = int(self.AdvancedFromVerse.currentText())
|
||||
verse_to = int(self.AdvancedToVerse.currentText())
|
||||
versetext = u'%s %s:%s-%s:%s' % (book, chapter_from, verse_from,
|
||||
chapter_to, verse_to)
|
||||
chapter_from = self.AdvancedFromChapter.currentText()
|
||||
chapter_to = self.AdvancedToChapter.currentText()
|
||||
verse_from = self.AdvancedFromVerse.currentText()
|
||||
verse_to = self.AdvancedToVerse.currentText()
|
||||
verse_separator = get_reference_match(u'sep_v_display')
|
||||
range_separator = get_reference_match(u'sep_r_display')
|
||||
verse_range = chapter_from + verse_separator + verse_from + \
|
||||
range_separator + chapter_to + verse_separator + verse_to
|
||||
versetext = u'%s %s' % (book, verse_range)
|
||||
self.search_results = self.parent.manager.get_verses(bible, versetext)
|
||||
if second_bible:
|
||||
self.second_search_results = self.parent.manager.get_verses(
|
||||
@ -709,7 +713,7 @@ class BibleMediaItem(MediaManagerItem):
|
||||
obj = reference[QtCore.QString(key)]
|
||||
if isinstance(obj, QtCore.QVariant):
|
||||
obj = obj.toPyObject()
|
||||
return unicode(obj)
|
||||
return unicode(obj).strip()
|
||||
|
||||
def generateSlideData(self, service_item, item=None, xmlVersion=False):
|
||||
"""
|
||||
@ -739,7 +743,8 @@ class BibleMediaItem(MediaManagerItem):
|
||||
second_bible = self._decodeQtObject(bitem, 'second_bible')
|
||||
second_version = self._decodeQtObject(bitem, 'second_version')
|
||||
second_copyright = self._decodeQtObject(bitem, 'second_copyright')
|
||||
second_permissions = self._decodeQtObject(bitem, 'second_permissions')
|
||||
second_permissions = \
|
||||
self._decodeQtObject(bitem, 'second_permissions')
|
||||
second_text = self._decodeQtObject(bitem, 'second_text')
|
||||
verse_text = self.formatVerse(old_chapter, chapter, verse)
|
||||
footer = u'%s (%s %s %s)' % (book, version, copyright, permissions)
|
||||
@ -750,21 +755,21 @@ class BibleMediaItem(MediaManagerItem):
|
||||
second_copyright, second_permissions)
|
||||
if footer not in raw_footer:
|
||||
raw_footer.append(footer)
|
||||
bible_text = u'%s %s\n\n%s %s' % (verse_text, text, verse_text,
|
||||
second_text)
|
||||
bible_text = u'%s\u00a0%s\n\n%s\u00a0%s' % (verse_text, text,
|
||||
verse_text, second_text)
|
||||
raw_slides.append(bible_text)
|
||||
bible_text = u''
|
||||
# If we are 'Verse Per Slide' then create a new slide.
|
||||
elif self.parent.settings_tab.layout_style == 0:
|
||||
bible_text = u'%s %s' % (verse_text, text)
|
||||
bible_text = u'%s\u00a0%s' % (verse_text, text)
|
||||
raw_slides.append(bible_text)
|
||||
bible_text = u''
|
||||
# If we are 'Verse Per Line' then force a new line.
|
||||
elif self.parent.settings_tab.layout_style == 1:
|
||||
bible_text = u'%s %s %s\n' % (bible_text, verse_text, text)
|
||||
bible_text = u'%s %s\u00a0%s\n' % (bible_text, verse_text, text)
|
||||
# We have to be 'Continuous'.
|
||||
else:
|
||||
bible_text = u'%s %s %s\n' % (bible_text, verse_text, text)
|
||||
bible_text = u'%s %s\u00a0%s\n' % (bible_text, verse_text, text)
|
||||
if first_item:
|
||||
start_item = item
|
||||
first_item = False
|
||||
@ -816,36 +821,31 @@ class BibleMediaItem(MediaManagerItem):
|
||||
``old_item``
|
||||
The last item of a range.
|
||||
"""
|
||||
verse_separator = get_reference_match(u'sep_v_display')
|
||||
range_separator = get_reference_match(u'sep_r_display')
|
||||
old_bitem = self.listView.item(old_item.row())
|
||||
old_chapter = int(self._decodeQtObject(old_bitem, 'chapter'))
|
||||
old_verse = int(self._decodeQtObject(old_bitem, 'verse'))
|
||||
old_chapter = self._decodeQtObject(old_bitem, 'chapter')
|
||||
old_verse = self._decodeQtObject(old_bitem, 'verse')
|
||||
start_bitem = self.listView.item(start_item.row())
|
||||
start_book = self._decodeQtObject(start_bitem, 'book')
|
||||
start_chapter = int(self._decodeQtObject(start_bitem, 'chapter'))
|
||||
start_verse = int(self._decodeQtObject(start_bitem, 'verse'))
|
||||
start_chapter = self._decodeQtObject(start_bitem, 'chapter')
|
||||
start_verse = self._decodeQtObject(start_bitem, 'verse')
|
||||
start_bible = self._decodeQtObject(start_bitem, 'bible')
|
||||
start_second_bible = self._decodeQtObject(start_bitem, 'second_bible')
|
||||
if start_second_bible:
|
||||
if start_verse == old_verse and start_chapter == old_chapter:
|
||||
title = u'%s %s:%s (%s, %s)' % (start_book, start_chapter,
|
||||
start_verse, start_bible, start_second_bible)
|
||||
elif start_chapter == old_chapter:
|
||||
title = u'%s %s:%s-%s (%s, %s)' % (start_book, start_chapter,
|
||||
start_verse, old_verse, start_bible, start_second_bible)
|
||||
bibles = u'%s, %s' % (start_bible, start_second_bible)
|
||||
else:
|
||||
title = u'%s %s:%s-%s:%s (%s, %s)' % (start_book, start_chapter,
|
||||
start_verse, old_chapter, old_verse, start_bible,
|
||||
start_second_bible)
|
||||
bibles = start_bible
|
||||
if start_chapter == old_chapter:
|
||||
if start_verse == old_verse:
|
||||
verse_range = start_chapter + verse_separator + start_verse
|
||||
else:
|
||||
if start_verse == old_verse and start_chapter == old_chapter:
|
||||
title = u'%s %s:%s (%s)' % (start_book, start_chapter,
|
||||
start_verse, start_bible)
|
||||
elif start_chapter == old_chapter:
|
||||
title = u'%s %s:%s-%s (%s)' % (start_book, start_chapter,
|
||||
start_verse, old_verse, start_bible)
|
||||
verse_range = start_chapter + verse_separator + start_verse + \
|
||||
range_separator + old_verse
|
||||
else:
|
||||
title = u'%s %s:%s-%s:%s (%s)' % (start_book, start_chapter,
|
||||
start_verse, old_chapter, old_verse, start_bible)
|
||||
verse_range = start_chapter + verse_separator + start_verse + \
|
||||
range_separator + old_chapter + verse_separator + old_verse
|
||||
title = u'%s %s (%s)' % (start_book, verse_range, bibles)
|
||||
return title
|
||||
|
||||
def checkTitle(self, item, old_item):
|
||||
@ -907,9 +907,10 @@ class BibleMediaItem(MediaManagerItem):
|
||||
``verse``
|
||||
The verse number (int).
|
||||
"""
|
||||
verse_separator = get_reference_match(u'sep_v_display')
|
||||
if not self.parent.settings_tab.show_new_chapters or \
|
||||
old_chapter != chapter:
|
||||
verse_text = u'%s:%s' % (chapter, verse)
|
||||
verse_text = unicode(chapter) + verse_separator + unicode(verse)
|
||||
else:
|
||||
verse_text = u'%s' % verse
|
||||
if self.parent.settings_tab.display_style == 1:
|
||||
|
0
openlp/plugins/bibles/lib/openlp1.py
Executable file → Normal file
0
openlp/plugins/bibles/lib/openlp1.py
Executable file → Normal file
@ -134,9 +134,9 @@ class OSISBible(BibleDB):
|
||||
testament)
|
||||
if last_chapter == 0:
|
||||
if book == u'Gen':
|
||||
self.wizard.ImportProgressBar.setMaximum(1188)
|
||||
self.wizard.importProgressBar.setMaximum(1188)
|
||||
else:
|
||||
self.wizard.ImportProgressBar.setMaximum(260)
|
||||
self.wizard.importProgressBar.setMaximum(260)
|
||||
if last_chapter != chapter:
|
||||
if last_chapter != 0:
|
||||
self.session.commit()
|
||||
|
@ -1,80 +1,81 @@
|
||||
Amuzgo de Guerrero,AMU
|
||||
Arabic Life Application Bible,ALAB
|
||||
Bulgarian Bible,BULG
|
||||
1940 Bulgarian Bible,BG1940
|
||||
Chinanteco de Comaltepec,CCO
|
||||
Cakchiquel Occidental,CKW
|
||||
Haitian Creole Version,HCV
|
||||
Slovo na cestu,SNC
|
||||
Dette er Biblen på dansk,DN1933
|
||||
Hoffnung für Alle,HOF
|
||||
Luther Bibel 1545,LUTH1545
|
||||
New International Version,NIV
|
||||
New American Standard Bible,NASB
|
||||
The Message,MSG
|
||||
Amplified Bible,AMP
|
||||
New Living Translation,NLT
|
||||
King James Version,KJV
|
||||
English Standard Version,ESV
|
||||
Contemporary English Version,CEV
|
||||
New King James Version,NKJV
|
||||
New Century Version,NCV
|
||||
21st Century King James Version,KJ21
|
||||
American Standard Version,ASV
|
||||
Young's Literal Translation,YLT
|
||||
Darby Translation,DARBY
|
||||
Holman Christian Standard Bible,HCSB
|
||||
New International Reader's Version,NIRV
|
||||
Wycliffe New Testament,WYC
|
||||
Worldwide English (New Testament),WE
|
||||
New International Version - UK,NIVUK
|
||||
Today's New International Version,TNIV
|
||||
Reina-Valera 1960,RVR1960
|
||||
Nueva Versión Internacional,NVI
|
||||
Reina-Valera 1995,RVR1995
|
||||
Castilian,CST
|
||||
Reina-Valera Antigua,RVA
|
||||
Biblia en Lenguaje Sencillo,BLS
|
||||
La Biblia de las Américas,LBLA
|
||||
Louis Segond,LSG
|
||||
La Bible du Semeur,BDS
|
||||
1881 Westcott-Hort New Testament,WHNU
|
||||
1550 Stephanus New Testament,TR1550
|
||||
1894 Scrivener New Testament,TR1894
|
||||
The Westminster Leningrad Codex,WLC
|
||||
Hiligaynon Bible,HLGN
|
||||
Croatian Bible,CRO
|
||||
Hungarian Károli,KAR
|
||||
Icelandic Bible,ICELAND
|
||||
La Nuova Diodati,LND
|
||||
La Parola è Vita,LM
|
||||
Jacalteco, Oriental,JAC
|
||||
Kekchi,KEK
|
||||
Korean Bible,KOREAN
|
||||
Maori Bible,MAORI
|
||||
Macedonian New Testament,MNT
|
||||
Mam, Central,MVC
|
||||
Mam de Todos Santos Chuchumatán,MVJ
|
||||
Reimer 2001,REIMER
|
||||
Náhuatl de Guerrero,NGU
|
||||
Het Boek,HTB
|
||||
Det Norsk Bibelselskap 1930,DNB1930
|
||||
Levande Bibeln,LB
|
||||
O Livro,OL
|
||||
João Ferreira de Almeida Atualizada,AA
|
||||
Quiché, Centro Occidental,QUT
|
||||
Romanian,RMNN
|
||||
Romanian,TLCR
|
||||
Russian Synodal Version,RUSV
|
||||
Slovo Zhizny,SZ
|
||||
التفسير التطبيقى للكتاب المقدس,ALAB
|
||||
Shqip,ALB
|
||||
Amplified Bible,AMP
|
||||
Amuzgo de Guerrero,AMU
|
||||
American Standard Version,ASV
|
||||
La Bible du Semeur,BDS
|
||||
Български 1940,BG1940
|
||||
Български,BULG
|
||||
Chinanteco de Comaltepec,CCO
|
||||
Contemporary English Version,CEV
|
||||
Cakchiquel Occidental,CKW
|
||||
Hrvatski,CRO
|
||||
Castilian,CST
|
||||
聖經和合本 (简体中文),CUVS
|
||||
聖經和合本 (繁体中文),CUV
|
||||
Darby Translation,DARBY
|
||||
Dette er Biblen på dansk,DN1933
|
||||
Det Norsk Bibelselskap 1930,DNB1930
|
||||
English Standard Version,ESV
|
||||
GOD’S WORD Translation,GW
|
||||
Holman Christian Standard Bible,HCSB
|
||||
Kreyòl ayisyen bib,HCV
|
||||
Hiligaynon Bible,HLGN
|
||||
Hoffnung für Alle,HOF
|
||||
Het Boek,HTB
|
||||
Icelandic Bible,ICELAND
|
||||
Jacalteco – Oriental,JAC
|
||||
Károlyi-biblia,KAR
|
||||
Kekchi,KEK
|
||||
21st Century King James Version,KJ21
|
||||
King James Version,KJV
|
||||
La Biblia de las Américas,LBLA
|
||||
Levande Bibeln,LB
|
||||
La Parola è Vita,LM
|
||||
La Nuova Diodati,LND
|
||||
Louis Segond,LSG
|
||||
Luther Bibel 1545,LUTH1545
|
||||
Māori Bible,MAORI
|
||||
Македонски Новиот Завет,MNT
|
||||
The Message,MSG
|
||||
Mam de Comitancillo Central,MVC
|
||||
Mam de Todos Santos Cuchumatán,MVJ
|
||||
New American Standard Bible,NASB
|
||||
New Century Version,NCV
|
||||
Náhuatl de Guerrero,NGU
|
||||
New International Reader's Version,NIRV
|
||||
New International Version 1984,NIV1984
|
||||
New International Version 2010,NIV
|
||||
New International Version - UK,NIVUK
|
||||
New King James Version,NKJV
|
||||
New Living Translation,NLT
|
||||
Nádej pre kazdého,NPK
|
||||
Albanian Bible,ALB
|
||||
Levande Bibeln,SVL
|
||||
Svenska 1917,SV1917
|
||||
Swahili New Testament,SNT
|
||||
Nueva Versión Internacional,NVI
|
||||
O Livro,OL
|
||||
Quiché – Centro Occidental,QUT
|
||||
Reimer 2001,REIMER
|
||||
Română Cornilescu,RMNN
|
||||
Новый перевод на русский язык,RUSV
|
||||
Reina-Valera Antigua,RVA
|
||||
Reina-Valera 1960,RVR1960
|
||||
Reina-Valera 1995,RVR1995
|
||||
Slovo na cestu,SNC
|
||||
Ang Salita ng Diyos,SND
|
||||
Ukrainian Bible,UKR
|
||||
Swahili New Testament,SNT
|
||||
Svenska 1917,SV1917
|
||||
Levande Bibeln,SVL
|
||||
Создать страницу,SZ
|
||||
Traducción en lenguaje actual,TLA
|
||||
New Romanian Translation,TLCR
|
||||
Today’s New International Version 2005,TNIV
|
||||
Textus Receptus Stephanus 1550,TR1550
|
||||
Textus Receptus Scrivener 1894,TR1894
|
||||
Українська Біблія. Переклад Івана Огієнка,UKR
|
||||
Uspanteco,USP
|
||||
1934 Vietnamese Bible,VIET
|
||||
Chinese Union Version (Simplified),CUVS
|
||||
Chinese Union Version (Traditional),CUV
|
||||
Kinh Thánh tiếng Việt 1934,VIET
|
||||
Worldwide English (New Testament),WE
|
||||
Codex Vaticanus Westcott-Hort 1881,WHNU
|
||||
Westminster Leningrad Codex,WLC
|
||||
Wycliffe New Testament,WYC
|
||||
Young's Literal Translation,YLT
|
||||
|
Can't render this file because it has a wrong number of fields in line 51.
|
39
openlp/plugins/bibles/resources/bibleserver.csv
Normal file
39
openlp/plugins/bibles/resources/bibleserver.csv
Normal file
@ -0,0 +1,39 @@
|
||||
عربي, ARA
|
||||
Bible – překlad 21. století, B21
|
||||
Bible du Semeur, BDS
|
||||
Българската Библия, BLG
|
||||
Český ekumenický překlad, CEP
|
||||
Hrvatski, CRO
|
||||
Священное Писание, CRS
|
||||
Version La Biblia al Dia, CST
|
||||
中文和合本(简体), CUVS
|
||||
Bibelen på hverdagsdansk, DK
|
||||
Revidierte Elberfelder, ELB
|
||||
Einheitsübersetzung, EU
|
||||
Gute Nachricht Bibel, GNB
|
||||
Hoffnung für alle, HFA
|
||||
Hungarian, HUN
|
||||
Het Boek, HTB
|
||||
La Parola è Vita, ITA
|
||||
IBS-fordítás (Új Károli), KAR
|
||||
King James Version, KJV
|
||||
Luther 1984, LUT
|
||||
Septuaginta, LXX
|
||||
Neue Genfer Übersetzung, NGÜ
|
||||
New International Readers Version, NIRV
|
||||
New International Version, NIV
|
||||
Neues Leben, NL
|
||||
En Levende Bok (NOR), NOR
|
||||
Nádej pre kazdého, NPK
|
||||
Noua traducere în limba românã, NTR
|
||||
Nueva Versión Internacional, NVI
|
||||
הברית הישנה, OT
|
||||
Słowo Życia, POL
|
||||
O Livro, PRT
|
||||
Новый перевод на русский язык, RUS
|
||||
Slovo na cestu, SNC
|
||||
Schlachter 2000, SLT
|
||||
En Levande Bok (SWE), SVL
|
||||
Today's New International Version, TNIV
|
||||
Türkçe, TR
|
||||
Biblia Vulgata, VUL
|
|
@ -109,7 +109,7 @@ class CustomPlugin(Plugin):
|
||||
}
|
||||
## Name for MediaDockManager, SettingsManager ##
|
||||
self.textStrings[StringContent.VisibleName] = {
|
||||
u'title': translate('CustomsPlugin', 'Customs')
|
||||
u'title': translate('CustomsPlugin', 'Custom')
|
||||
}
|
||||
# Middle Header Bar
|
||||
## Import Button ##
|
||||
|
@ -224,9 +224,6 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
|
||||
``edit_all``
|
||||
Indicates if all slides or only one slide has been edited.
|
||||
"""
|
||||
if len(slides) == 1:
|
||||
self.slideListView.currentItem().setText(slides[0])
|
||||
else:
|
||||
if edit_all:
|
||||
self.slideListView.clear()
|
||||
for slide in slides:
|
||||
|
@ -31,7 +31,7 @@ from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import MediaManagerItem, BaseListWithDnD, build_icon, \
|
||||
context_menu_action, ItemCapabilities, SettingsManager, translate, \
|
||||
check_item_selected
|
||||
check_item_selected, Receiver
|
||||
from openlp.core.utils import AppLocation, get_images_filter
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@ -139,6 +139,8 @@ class ImageMediaItem(MediaManagerItem):
|
||||
self.settingsSection, self.getFileList())
|
||||
|
||||
def loadList(self, list):
|
||||
self.listView.setCursor(QtCore.Qt.BusyCursor)
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
for file in list:
|
||||
filename = os.path.split(unicode(file))[1]
|
||||
thumb = os.path.join(self.servicePath, filename)
|
||||
@ -153,6 +155,8 @@ class ImageMediaItem(MediaManagerItem):
|
||||
item_name.setIcon(icon)
|
||||
item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(file))
|
||||
self.listView.addItem(item_name)
|
||||
self.listView.setCursor(QtCore.Qt.ArrowCursor)
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
|
||||
def generateSlideData(self, service_item, item=None, xmlVersion=False):
|
||||
items = self.listView.selectedIndexes()
|
||||
|
@ -146,8 +146,7 @@ class Ui_EditSongDialog(object):
|
||||
self.AuthorsSelectionComboItem.sizePolicy().hasHeightForWidth())
|
||||
self.AuthorsSelectionComboItem.setSizePolicy(sizePolicy)
|
||||
self.AuthorsSelectionComboItem.setEditable(True)
|
||||
self.AuthorsSelectionComboItem.setInsertPolicy(
|
||||
QtGui.QComboBox.InsertAlphabetically)
|
||||
self.AuthorsSelectionComboItem.setInsertPolicy(QtGui.QComboBox.NoInsert)
|
||||
self.AuthorsSelectionComboItem.setSizeAdjustPolicy(
|
||||
QtGui.QComboBox.AdjustToMinimumContentsLength)
|
||||
self.AuthorsSelectionComboItem.setMinimumContentsLength(8)
|
||||
@ -224,6 +223,7 @@ class Ui_EditSongDialog(object):
|
||||
sizePolicy.setHeightForWidth(
|
||||
self.SongTopicCombo.sizePolicy().hasHeightForWidth())
|
||||
self.SongTopicCombo.setEditable(True)
|
||||
self.SongTopicCombo.setInsertPolicy(QtGui.QComboBox.NoInsert)
|
||||
self.SongTopicCombo.setSizePolicy(sizePolicy)
|
||||
self.SongTopicCombo.setObjectName(u'SongTopicCombo')
|
||||
self.TopicAddLayout.addWidget(self.SongTopicCombo)
|
||||
@ -271,6 +271,7 @@ class Ui_EditSongDialog(object):
|
||||
sizePolicy.setHeightForWidth(
|
||||
self.SongbookCombo.sizePolicy().hasHeightForWidth())
|
||||
self.SongbookCombo.setEditable(True)
|
||||
self.SongbookCombo.setInsertPolicy(QtGui.QComboBox.NoInsert)
|
||||
self.SongbookCombo.setSizePolicy(sizePolicy)
|
||||
self.SongbookCombo.setObjectName(u'SongbookCombo')
|
||||
self.SongbookLayout.addRow(self.SongbookNameLabel, self.SongbookCombo)
|
||||
@ -315,6 +316,7 @@ class Ui_EditSongDialog(object):
|
||||
self.ThemeLayout.setObjectName(u'ThemeLayout')
|
||||
self.ThemeSelectionComboItem = QtGui.QComboBox(self.ThemeGroupBox)
|
||||
self.ThemeSelectionComboItem.setEditable(True)
|
||||
self.ThemeSelectionComboItem.setInsertPolicy(QtGui.QComboBox.NoInsert)
|
||||
self.ThemeSelectionComboItem.setObjectName(u'ThemeSelectionComboItem')
|
||||
self.ThemeLayout.addWidget(self.ThemeSelectionComboItem)
|
||||
self.ThemeAddButton = QtGui.QPushButton(self.ThemeGroupBox)
|
||||
|
@ -108,6 +108,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
||||
self.TopicsListView.setSortingEnabled(False)
|
||||
self.TopicsListView.setAlternatingRowColors(True)
|
||||
self.findVerseSplit = re.compile(u'---\[\]---\n', re.UNICODE)
|
||||
self.whitespace = re.compile(r'\W+', re.UNICODE)
|
||||
|
||||
def initialise(self):
|
||||
self.VerseEditButton.setEnabled(False)
|
||||
@ -546,13 +547,10 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
||||
if self.AuthorsListView.count() == 0:
|
||||
self.SongTabWidget.setCurrentIndex(1)
|
||||
self.AuthorsListView.setFocus()
|
||||
answer = QtGui.QMessageBox.warning(self,
|
||||
QtGui.QMessageBox.critical(self,
|
||||
translate('SongsPlugin.EditSongForm', 'Warning'),
|
||||
translate('SongsPlugin.EditSongForm',
|
||||
'You have not added any authors for this song. Do you '
|
||||
'want to add an author now?'),
|
||||
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
|
||||
if answer == QtGui.QMessageBox.Yes:
|
||||
'You need to have an author for this song.'))
|
||||
return False
|
||||
if self.song.verse_order:
|
||||
order = []
|
||||
@ -738,7 +736,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
||||
verseId = unicode(item.data(QtCore.Qt.UserRole).toString())
|
||||
bits = verseId.split(u':')
|
||||
sxml.add_verse_to_lyrics(bits[0], bits[1], unicode(item.text()))
|
||||
text = text + re.sub(r'\W+', u' ',
|
||||
text = text + self.whitespace.sub(u' ',
|
||||
unicode(self.VerseListWidget.item(i, 0).text())) + u' '
|
||||
if (bits[1] > u'1') and (bits[0][0] not in multiple):
|
||||
multiple.append(bits[0][0])
|
||||
|
@ -29,7 +29,7 @@ import logging
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.plugins.songs.lib import VerseType
|
||||
from openlp.plugins.songs.lib import VerseType, translate
|
||||
|
||||
from editversedialog import Ui_EditVerseDialog
|
||||
|
||||
@ -131,6 +131,7 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog):
|
||||
|
||||
def setVerse(self, text, single=False,
|
||||
tag=u'%s:1' % VerseType.to_string(VerseType.Verse)):
|
||||
self.hasSingleVerse = single
|
||||
if single:
|
||||
verse_type, verse_number = tag.split(u':')
|
||||
verse_type_index = VerseType.from_string(verse_type)
|
||||
@ -159,3 +160,16 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog):
|
||||
text = u'---[%s:1]---\n%s' % (VerseType.to_string(VerseType.Verse),
|
||||
text)
|
||||
return text
|
||||
|
||||
def accept(self):
|
||||
if self.hasSingleVerse:
|
||||
value = unicode(self.getVerse()[0])
|
||||
else:
|
||||
value = self.getVerse()[0].split(u'\n')[1]
|
||||
if len(value) == 0:
|
||||
QtGui.QMessageBox.critical(self,
|
||||
translate('SongsPlugin.EditSongForm', 'Error'),
|
||||
translate('SongsPlugin.EditSongForm',
|
||||
'You need to type some text in to the verse.'))
|
||||
return False
|
||||
QtGui.QDialog.accept(self)
|
||||
|
@ -254,24 +254,57 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard):
|
||||
# Progress page
|
||||
return True
|
||||
|
||||
def getFileName(self, title, editbox,
|
||||
filters = '%s (*)' % translate('SongsPlugin.ImportWizardForm',
|
||||
'All Files')):
|
||||
def getFileName(self, title, editbox, filters=u''):
|
||||
"""
|
||||
Opens a QFileDialog and writes the filename to the given editbox.
|
||||
|
||||
``title``
|
||||
The title of the dialog (unicode).
|
||||
|
||||
``editbox``
|
||||
A editbox (QLineEdit).
|
||||
|
||||
``filters``
|
||||
The file extension filters. It should contain the file descriptions
|
||||
as well as the file extensions. For example::
|
||||
|
||||
u'OpenLP 2.0 Databases (*.sqlite)'
|
||||
"""
|
||||
if filters:
|
||||
filters += u';;'
|
||||
filters += u'%s (*)' % translate('SongsPlugin.ImportWizardForm',
|
||||
'All Files')
|
||||
filename = QtGui.QFileDialog.getOpenFileName(self, title,
|
||||
SettingsManager.get_last_dir(self.plugin.settingsSection, 1),
|
||||
filters)
|
||||
os.path.dirname(SettingsManager.get_last_dir(
|
||||
self.plugin.settingsSection, 1)), filters)
|
||||
if filename:
|
||||
editbox.setText(filename)
|
||||
SettingsManager.set_last_dir(
|
||||
self.plugin.settingsSection,
|
||||
SettingsManager.set_last_dir(self.plugin.settingsSection,
|
||||
os.path.split(unicode(filename))[0], 1)
|
||||
|
||||
def getFiles(self, title, listbox,
|
||||
filters = u'%s (*)' % translate('SongsPlugin.ImportWizardForm',
|
||||
'All Files')):
|
||||
def getFiles(self, title, listbox, filters=u''):
|
||||
"""
|
||||
Opens a QFileDialog and writes the filenames to the given listbox.
|
||||
|
||||
``title``
|
||||
The title of the dialog (unicode).
|
||||
|
||||
``listbox``
|
||||
A listbox (QListWidget).
|
||||
|
||||
``filters``
|
||||
The file extension filters. It should contain the file descriptions
|
||||
as well as the file extensions. For example::
|
||||
|
||||
u'SongBeamer files (*.sng)'
|
||||
"""
|
||||
if filters:
|
||||
filters += u';;'
|
||||
filters += u'%s (*)' % translate('SongsPlugin.ImportWizardForm',
|
||||
'All Files')
|
||||
filenames = QtGui.QFileDialog.getOpenFileNames(self, title,
|
||||
SettingsManager.get_last_dir(self.plugin.settingsSection, 1),
|
||||
filters)
|
||||
os.path.dirname(SettingsManager.get_last_dir(
|
||||
self.plugin.settingsSection, 1)), filters)
|
||||
if filenames:
|
||||
listbox.addItems(filenames)
|
||||
SettingsManager.set_last_dir(
|
||||
@ -293,24 +326,18 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard):
|
||||
self.getFileName(
|
||||
translate('SongsPlugin.ImportWizardForm',
|
||||
'Select OpenLP 2.0 Database File'),
|
||||
self.openLP2FilenameEdit,
|
||||
u'%s (*.sqlite);;%s (*)'
|
||||
self.openLP2FilenameEdit, u'%s (*.sqlite)'
|
||||
% (translate('SongsPlugin.ImportWizardForm',
|
||||
'OpenLP 2.0 Databases'),
|
||||
translate('SongsPlugin.ImportWizardForm',
|
||||
'All Files'))
|
||||
'OpenLP 2.0 Databases'))
|
||||
)
|
||||
|
||||
def onOpenLP1BrowseButtonClicked(self):
|
||||
self.getFileName(
|
||||
translate('SongsPlugin.ImportWizardForm',
|
||||
'Select openlp.org 1.x Database File'),
|
||||
self.openLP1FilenameEdit,
|
||||
u'%s (*.olp);;%s (*)'
|
||||
% (translate('SongsPlugin.ImportWizardForm',
|
||||
'openlp.org v1.x Databases'),
|
||||
translate('SongsPlugin.ImportWizardForm',
|
||||
'All Files'))
|
||||
self.openLP1FilenameEdit, u'%s (*.olp)'
|
||||
% translate('SongsPlugin.ImportWizardForm',
|
||||
'openlp.org v1.x Databases')
|
||||
)
|
||||
|
||||
#def onOpenLyricsAddButtonClicked(self):
|
||||
@ -337,12 +364,9 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard):
|
||||
self.getFiles(
|
||||
translate('SongsPlugin.ImportWizardForm',
|
||||
'Select Words of Worship Files'),
|
||||
self.wordsOfWorshipFileListWidget,
|
||||
u'%s (*.wsg *.wow-song);;%s (*)'
|
||||
% (translate('SongsPlugin.ImportWizardForm',
|
||||
'Words Of Worship Song Files'),
|
||||
translate('SongsPlugin.ImportWizardForm',
|
||||
'All Files'))
|
||||
self.wordsOfWorshipFileListWidget, u'%s (*.wsg *.wow-song)'
|
||||
% translate('SongsPlugin.ImportWizardForm',
|
||||
'Words Of Worship Song Files')
|
||||
)
|
||||
|
||||
def onWordsOfWorshipRemoveButtonClicked(self):
|
||||
@ -362,12 +386,9 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard):
|
||||
self.getFiles(
|
||||
translate('SongsPlugin.ImportWizardForm',
|
||||
'Select Songs of Fellowship Files'),
|
||||
self.songsOfFellowshipFileListWidget,
|
||||
u'%s (*.rtf);;%s (*)'
|
||||
% (translate('SongsPlugin.ImportWizardForm',
|
||||
'Songs Of Felloship Song Files'),
|
||||
translate('SongsPlugin.ImportWizardForm',
|
||||
'All Files'))
|
||||
self.songsOfFellowshipFileListWidget, u'%s (*.rtf)'
|
||||
% translate('SongsPlugin.ImportWizardForm',
|
||||
'Songs Of Felloship Song Files')
|
||||
)
|
||||
|
||||
def onSongsOfFellowshipRemoveButtonClicked(self):
|
||||
@ -394,7 +415,8 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard):
|
||||
self.getFiles(
|
||||
translate('SongsPlugin.ImportWizardForm',
|
||||
'Select SongBeamer Files'),
|
||||
self.songBeamerFileListWidget
|
||||
self.songBeamerFileListWidget, u'%s (*.sng)' %
|
||||
translate('SongsPlugin.ImportWizardForm', 'SongBeamer files')
|
||||
)
|
||||
|
||||
def onSongBeamerRemoveButtonClicked(self):
|
||||
|
@ -71,7 +71,8 @@ class VerseType(object):
|
||||
The string to return a VerseType for
|
||||
"""
|
||||
verse_type = verse_type.lower()
|
||||
if verse_type == unicode(VerseType.to_string(VerseType.Verse)).lower()[0]:
|
||||
if verse_type == \
|
||||
unicode(VerseType.to_string(VerseType.Verse)).lower()[0]:
|
||||
return translate('SongsPlugin.VerseType', 'Verse')
|
||||
elif verse_type == \
|
||||
unicode(VerseType.to_string(VerseType.Chorus)).lower()[0]:
|
||||
|
@ -44,6 +44,7 @@ class SongListView(BaseListWithDnD):
|
||||
self.PluginName = u'Songs'
|
||||
BaseListWithDnD.__init__(self, parent)
|
||||
|
||||
|
||||
class SongMediaItem(MediaManagerItem):
|
||||
"""
|
||||
This is the custom media manager item for Songs.
|
||||
@ -417,27 +418,37 @@ class SongMediaItem(MediaManagerItem):
|
||||
item.data_string[u'title'].split(u'@')[0].lower() ,
|
||||
Song.search_title.asc())
|
||||
author_list = item.data_string[u'authors'].split(u', ')
|
||||
# The service item always has an author (at least it has u'' as
|
||||
# author). However, songs saved in the database do not have to have
|
||||
# an author.
|
||||
if u'' in author_list:
|
||||
author_list.remove(u'')
|
||||
editId = 0
|
||||
uuid = item._uuid
|
||||
add_song = True
|
||||
if search_results:
|
||||
for song in search_results:
|
||||
count = 0
|
||||
same_authors = True
|
||||
# If the author counts are different, we do not have to do
|
||||
# any further checking. This is also important when a song
|
||||
# does not have any author (because we can not loop over an
|
||||
# empty list).
|
||||
if len(song.authors) == len(author_list):
|
||||
for author in song.authors:
|
||||
if author.display_name in author_list:
|
||||
count += 1
|
||||
# All Authors the same
|
||||
if count == len(author_list):
|
||||
if author.display_name not in author_list:
|
||||
same_authors = False
|
||||
else:
|
||||
same_authors = False
|
||||
# All authors are the same, so we can stop here and the song
|
||||
# does not have to be saved.
|
||||
if same_authors:
|
||||
add_song = False
|
||||
editId = song.id
|
||||
else:
|
||||
# Authors different
|
||||
if self.addSongFromService:
|
||||
editId = self.openLyrics. \
|
||||
xml_to_song(item.xml_version)
|
||||
else:
|
||||
# Title does not match
|
||||
break
|
||||
if add_song:
|
||||
if self.addSongFromService:
|
||||
editId = self.openLyrics.xml_to_song(item.xml_version)
|
||||
# Update service with correct song id
|
||||
# Update service with correct song id.
|
||||
if editId != 0:
|
||||
Receiver.send_message(u'service_item_update',
|
||||
u'%s:%s' %(editId, uuid))
|
||||
|
@ -247,7 +247,7 @@ class SongImport(QtCore.QObject):
|
||||
"""
|
||||
Extracts alphanumeric words for searchable fields
|
||||
"""
|
||||
return re.sub(r'\W+', u' ', text)
|
||||
return re.sub(r'\W+', u' ', text, re.UNICODE)
|
||||
|
||||
def finish(self):
|
||||
"""
|
||||
|
@ -297,6 +297,8 @@ class OpenLyricsParser(object):
|
||||
song_xml = objectify.fromstring(xml)
|
||||
properties = song_xml.properties
|
||||
song.copyright = unicode(properties.copyright.text)
|
||||
if song.copyright == u'None':
|
||||
song.copyright = u''
|
||||
song.verse_order = unicode(properties.verseOrder.text)
|
||||
if song.verse_order == u'None':
|
||||
song.verse_order = u''
|
||||
|
@ -31,7 +31,7 @@ from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import Plugin, StringContent, build_icon, translate
|
||||
from openlp.core.lib.db import Manager
|
||||
from openlp.plugins.songs.lib import SongMediaItem, SongsTab
|
||||
from openlp.plugins.songs.lib import SongMediaItem, SongsTab, SongXMLParser
|
||||
from openlp.plugins.songs.lib.db import init_schema, Song
|
||||
from openlp.plugins.songs.lib.importer import SongFormat
|
||||
|
||||
@ -150,9 +150,13 @@ class SongsPlugin(Plugin):
|
||||
song.title = u''
|
||||
if song.alternate_title is None:
|
||||
song.alternate_title = u''
|
||||
song.search_title = self.whitespace.sub(u' ', \
|
||||
song.title.lower()) + u' ' + \
|
||||
self.whitespace.sub(u' ', song.alternate_title.lower())
|
||||
song.search_title = self.whitespace.sub(u' ', song.title.lower() + \
|
||||
u' ' + song.alternate_title.lower())
|
||||
lyrics = u''
|
||||
verses = SongXMLParser(song.lyrics).get_verses()
|
||||
for verse in verses:
|
||||
lyrics = lyrics + self.whitespace.sub(u' ', verse[1]) + u' '
|
||||
song.search_lyrics = lyrics.lower()
|
||||
progressDialog.setValue(counter)
|
||||
self.manager.save_objects(songs)
|
||||
counter += 1
|
||||
|
3047
resources/i18n/af.ts
3047
resources/i18n/af.ts
File diff suppressed because it is too large
Load Diff
3192
resources/i18n/de.ts
3192
resources/i18n/de.ts
File diff suppressed because it is too large
Load Diff
2973
resources/i18n/en.ts
2973
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
2977
resources/i18n/es.ts
2977
resources/i18n/es.ts
File diff suppressed because it is too large
Load Diff
3046
resources/i18n/et.ts
3046
resources/i18n/et.ts
File diff suppressed because it is too large
Load Diff
3226
resources/i18n/hu.ts
3226
resources/i18n/hu.ts
File diff suppressed because it is too large
Load Diff
2977
resources/i18n/ja.ts
2977
resources/i18n/ja.ts
File diff suppressed because it is too large
Load Diff
3154
resources/i18n/ko.ts
3154
resources/i18n/ko.ts
File diff suppressed because it is too large
Load Diff
3013
resources/i18n/nb.ts
3013
resources/i18n/nb.ts
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
3308
resources/i18n/sv.ts
3308
resources/i18n/sv.ts
File diff suppressed because it is too large
Load Diff
0
scripts/openlp-remoteclient.py
Executable file → Normal file
0
scripts/openlp-remoteclient.py
Executable file → Normal file
Loading…
Reference in New Issue
Block a user