This commit is contained in:
Andreas Preikschat 2010-12-23 06:52:09 +01:00
commit 76241edc9f
45 changed files with 25924 additions and 15175 deletions

View File

@ -113,6 +113,14 @@ class ImageManager(QtCore.QObject):
time.sleep(0.1) time.sleep(0.1)
return self._cache[name].image_bytes 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): def add_image(self, name, path):
""" """
Add image to cache if it is not already there Add image to cache if it is not already there
@ -125,6 +133,8 @@ class ImageManager(QtCore.QObject):
image.image = resize_image(path, image.image = resize_image(path,
self.width, self.height) self.width, self.height)
self._cache[name] = image self._cache[name] = image
else:
log.debug(u'Image in cache %s:%s' % (name, path))
self._cache_dirty = True self._cache_dirty = True
# only one thread please # only one thread please
if not self._thread_running: if not self._thread_running:

View File

@ -123,7 +123,7 @@ if sys.platform[:3] == u'win':
# Platform support for MacOS # Platform support for MacOS
elif sys.platform == u'darwin': elif sys.platform == u'darwin':
_controllers[u'open']= Controller(u'open') _controllers[u'open'] = Controller(u'open')
_open = _controllers[u'open'].open _open = _controllers[u'open'].open

View File

@ -213,6 +213,8 @@ class RenderManager(object):
# make big page for theme edit dialog to get line count # make big page for theme edit dialog to get line count
if self.force_page: if self.force_page:
verse = verse + verse + verse verse = verse + verse + verse
else:
self.image_manager.del_image(self.theme_data.theme_name)
footer = [] footer = []
footer.append(u'Arky Arky (Unknown)' ) footer.append(u'Arky Arky (Unknown)' )
footer.append(u'Public Domain') footer.append(u'Public Domain')

View File

@ -166,6 +166,17 @@ class Ui_AboutDialog(object):
' PyQt4: http://www.riverbankcomputing.co.uk/software/pyqt/' ' PyQt4: http://www.riverbankcomputing.co.uk/software/pyqt/'
'intro\n' 'intro\n'
' Oxygen Icons: http://oxygen-icons.org/\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.setTabText(
self.aboutNotebook.indexOf(self.creditsTab), self.aboutNotebook.indexOf(self.creditsTab),

View File

@ -23,7 +23,7 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59 # # with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
import logging
import re import re
import os import os
import platform import platform
@ -59,6 +59,8 @@ from openlp.core.lib.mailto import mailto
from exceptiondialog import Ui_ExceptionDialog from exceptiondialog import Ui_ExceptionDialog
log = logging.getLogger(__name__)
class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog): class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
""" """
The exception dialog The exception dialog
@ -103,7 +105,8 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
filename = QtGui.QFileDialog.getSaveFileName(self, filename = QtGui.QFileDialog.getSaveFileName(self,
translate('OpenLP.ExceptionForm', 'Save Crash Report'), translate('OpenLP.ExceptionForm', 'Save Crash Report'),
SettingsManager.get_last_dir(self.settingsSection), SettingsManager.get_last_dir(self.settingsSection),
translate('OpenLP.ExceptionForm', 'Text files (*.txt *.log *.text)')) translate('OpenLP.ExceptionForm',
'Text files (*.txt *.log *.text)'))
if filename: if filename:
filename = unicode(QtCore.QDir.toNativeSeparators(filename)) filename = unicode(QtCore.QDir.toNativeSeparators(filename))
SettingsManager.set_last_dir(self.settingsSection, os.path.dirname( SettingsManager.set_last_dir(self.settingsSection, os.path.dirname(
@ -138,6 +141,7 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
if re.search(r'[/\\]openlp[/\\]', line): if re.search(r'[/\\]openlp[/\\]', line):
source = re.sub(r'.*[/\\]openlp[/\\](.*)".*', r'\1', line) source = re.sub(r'.*[/\\]openlp[/\\](.*)".*', r'\1', line)
if u':' in line: if u':' in line:
exception = line.split(u'\n')[-1].split(u':')[0] exception = line.split(u'\n')[-1].split(u':')[0]
subject = u'Bug report: %s in %s' % (exception, source) 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)

View File

@ -64,8 +64,7 @@ class ServiceItemEditForm(QtGui.QDialog, Ui_ServiceItemEditDialog):
self.item._raw_frames = [] self.item._raw_frames = []
if self.item.is_image(): if self.item.is_image():
for item in self.itemList: for item in self.itemList:
self.item.add_from_image(item[u'path'], item[u'title'], self.item.add_from_image(item[u'path'], item[u'title'])
item[u'image'])
self.item.render() self.item.render()
return self.item return self.item

View File

@ -332,11 +332,12 @@ class SlideController(QtGui.QWidget):
QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onSlideSelected) QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onSlideSelected)
if not self.isLive: if not self.isLive:
QtCore.QObject.connect(self.PreviewListWidget, QtCore.QObject.connect(self.PreviewListWidget,
QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), self.onGoLiveClick) QtCore.SIGNAL(u'doubleClicked(QModelIndex)'),
self.onGoLiveClick)
if isLive: if isLive:
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'slidecontroller_live_spin_delay'), QtCore.SIGNAL(u'slidecontroller_live_spin_delay'),
self.receiveSpinDelay) self.receiveSpinDelay)
if isLive: if isLive:
self.Toolbar.makeWidgetsInvisible(self.loopList) self.Toolbar.makeWidgetsInvisible(self.loopList)
self.Toolbar.actions[u'Stop Loop'].setVisible(False) self.Toolbar.actions[u'Stop Loop'].setVisible(False)
@ -466,7 +467,7 @@ class SlideController(QtGui.QWidget):
self.Toolbar.actions[u'Stop Loop'].setVisible(False) self.Toolbar.actions[u'Stop Loop'].setVisible(False)
if item.is_text(): if item.is_text():
if QtCore.QSettings().value( 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: QtCore.QVariant(True)).toBool() and len(self.slideList) > 0:
self.Toolbar.makeWidgetsVisible([u'Song Menu']) self.Toolbar.makeWidgetsVisible([u'Song Menu'])
if item.is_capable(ItemCapabilities.AllowsLoop) and \ if item.is_capable(ItemCapabilities.AllowsLoop) and \
@ -560,7 +561,7 @@ class SlideController(QtGui.QWidget):
[serviceItem, self.isLive, blanked, slideno]) [serviceItem, self.isLive, blanked, slideno])
self.slideList = {} self.slideList = {}
width = self.parent.ControlSplitter.sizes()[self.split] 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.PreviewListWidget.setCursor(QtCore.Qt.PointingHandCursor)
self.serviceItem = serviceItem self.serviceItem = serviceItem
self.PreviewListWidget.clear() self.PreviewListWidget.clear()

View File

@ -289,6 +289,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
""" """
Run the wizard. Run the wizard.
""" """
log.debug(u'Editing theme %s' % self.theme.theme_name)
self.updateThemeAllowed = False self.updateThemeAllowed = False
self.setDefaults() self.setDefaults()
self.updateThemeAllowed = True self.updateThemeAllowed = True
@ -444,7 +445,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
def setPreviewTabValues(self): def setPreviewTabValues(self):
self.setField(u'name', QtCore.QVariant(self.theme.theme_name)) 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) self.themeNameEdit.setEnabled(False)
else: else:
self.themeNameEdit.setEnabled(True) self.themeNameEdit.setEnabled(True)

View File

@ -555,7 +555,8 @@ class Ui_ThemeWizard(object):
u'footerDefaultPositionCheckBox') u'footerDefaultPositionCheckBox')
self.footerPositionLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.footerPositionLayout.setWidget(0, QtGui.QFormLayout.FieldRole,
self.footerDefaultPositionCheckBox) self.footerDefaultPositionCheckBox)
self.areaPositionLayout.addWidget(self.footerPositionGroupBox, 1, 1, 1, 1) self.areaPositionLayout.addWidget(
self.footerPositionGroupBox, 1, 1, 1, 1)
ThemeWizard.addPage(self.areaPositionPage) ThemeWizard.addPage(self.areaPositionPage)
self.previewPage = QtGui.QWizardPage() self.previewPage = QtGui.QWizardPage()
self.previewPage.setObjectName(u'previewPage') self.previewPage.setObjectName(u'previewPage')
@ -720,8 +721,8 @@ class Ui_ThemeWizard(object):
self.areaPositionPage.setTitle( self.areaPositionPage.setTitle(
translate('OpenLP.ThemeWizard', 'Output Area Locations')) translate('OpenLP.ThemeWizard', 'Output Area Locations'))
self.areaPositionPage.setSubTitle( self.areaPositionPage.setSubTitle(
translate('OpenLP.ThemeWizard', 'Allows you to change and move the ' translate('OpenLP.ThemeWizard', 'Allows you to change and move the'
'main and footer areas.')) ' main and footer areas.'))
self.mainPositionGroupBox.setTitle( self.mainPositionGroupBox.setTitle(
translate('OpenLP.ThemeWizard', '&Main Area')) translate('OpenLP.ThemeWizard', '&Main Area'))
self.mainDefaultPositionCheckBox.setText( self.mainDefaultPositionCheckBox.setText(
@ -733,18 +734,24 @@ class Ui_ThemeWizard(object):
self.mainWidthSpinBox.setSuffix(translate('OpenLP.ThemeWizard', 'px')) self.mainWidthSpinBox.setSuffix(translate('OpenLP.ThemeWizard', 'px'))
self.mainWidthLabel.setText(translate('OpenLP.ThemeWizard', 'Width:')) self.mainWidthLabel.setText(translate('OpenLP.ThemeWizard', 'Width:'))
self.mainHeightSpinBox.setSuffix(translate('OpenLP.ThemeWizard', 'px')) self.mainHeightSpinBox.setSuffix(translate('OpenLP.ThemeWizard', 'px'))
self.mainHeightLabel.setText(translate('OpenLP.ThemeWizard', 'Height:')) self.mainHeightLabel.setText(
translate('OpenLP.ThemeWizard', 'Height:'))
self.footerPositionGroupBox.setTitle( self.footerPositionGroupBox.setTitle(
translate('OpenLP.ThemeWizard', 'Footer Area')) 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.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.footerYSpinBox.setSuffix(translate('OpenLP.ThemeWizard', 'px'))
self.footerWidthLabel.setText(translate('OpenLP.ThemeWizard', 'Width:')) self.footerWidthLabel.setText(
self.footerWidthSpinBox.setSuffix(translate('OpenLP.ThemeWizard', 'px')) translate('OpenLP.ThemeWizard', 'Width:'))
self.footerWidthSpinBox.setSuffix(
translate('OpenLP.ThemeWizard', 'px'))
self.footerHeightLabel.setText( self.footerHeightLabel.setText(
translate('OpenLP.ThemeWizard', 'Height:')) translate('OpenLP.ThemeWizard', 'Height:'))
self.footerHeightSpinBox.setSuffix(translate('OpenLP.ThemeWizard', 'px')) self.footerHeightSpinBox.setSuffix(
translate('OpenLP.ThemeWizard', 'px'))
self.footerDefaultPositionCheckBox.setText( self.footerDefaultPositionCheckBox.setText(
translate('OpenLP.ThemeWizard', 'Use default location')) translate('OpenLP.ThemeWizard', 'Use default location'))
self.previewPage.setTitle( self.previewPage.setTitle(

View File

@ -171,24 +171,23 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog):
# We found '<>' in the alert text, but the ParameterEdit field is # We found '<>' in the alert text, but the ParameterEdit field is
# empty. # empty.
if text.find(u'<>') != -1 and not self.ParameterEdit.text() and \ if text.find(u'<>') != -1 and not self.ParameterEdit.text() and \
QtGui.QMessageBox.question(self, translate( QtGui.QMessageBox.question(self,
'AlertPlugin.AlertForm', 'No Parameter found'), translate('AlertPlugin.AlertForm', 'No Parameter found'),
translate('AlertPlugin.AlertForm', 'You have not entered a ' translate('AlertPlugin.AlertForm', 'You have not entered a '
'parameter to be replaced.\nDo you want to continue ' 'parameter to be replaced.\nDo you want to continue anyway?'),
'anyway?'), QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.No |
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.No | QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.No:
QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.No:
self.ParameterEdit.setFocus() self.ParameterEdit.setFocus()
return False return False
# The ParameterEdit field is not empty, but we have not found '<>' # The ParameterEdit field is not empty, but we have not found '<>'
# in the alert text. # in the alert text.
elif text.find(u'<>') == -1 and self.ParameterEdit.text() and \ elif text.find(u'<>') == -1 and self.ParameterEdit.text() and \
QtGui.QMessageBox.question(self, translate( QtGui.QMessageBox.question(self,
'AlertPlugin.AlertForm', 'No Placeholder found'), translate('AlertPlugin.AlertForm', 'No Placeholder found'),
translate('AlertPlugin.AlertForm', 'The alert text does not' translate('AlertPlugin.AlertForm', 'The alert text does not'
' contain \'<>\'.\nDo want to continue anyway?'), ' contain \'<>\'.\nDo want to continue anyway?'),
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.No | QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.No |
QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.No: QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.No:
self.ParameterEdit.setFocus() self.ParameterEdit.setFocus()
return False return False
text = text.replace(u'<>', unicode(self.ParameterEdit.text())) text = text.replace(u'<>', unicode(self.ParameterEdit.text()))

View File

@ -43,10 +43,12 @@ class WebDownload(object):
Unknown = -1 Unknown = -1
Crosswalk = 0 Crosswalk = 0
BibleGateway = 1 BibleGateway = 1
Bibleserver = 2
Names = { Names = {
0: u'Crosswalk', 0: u'Crosswalk',
1: u'BibleGateway' 1: u'BibleGateway',
2: u'Bibleserver'
} }
@classmethod @classmethod
@ -232,8 +234,7 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard):
The index of the combo box. The index of the combo box.
""" """
self.bibleComboBox.clear() self.bibleComboBox.clear()
bibles = [unicode(translate('BiblesPlugin.ImportWizardForm', bible)) for bibles = self.web_bible_list[index].keys()
bible in self.web_bible_list[index].keys()]
bibles.sort() bibles.sort()
for bible in bibles: for bible in bibles:
self.bibleComboBox.addItem(bible) self.bibleComboBox.addItem(bible)
@ -252,14 +253,16 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard):
""" """
self.getFileName( self.getFileName(
translate('BiblesPlugin.ImportWizardForm', 'Open Books CSV File'), translate('BiblesPlugin.ImportWizardForm', 'Open Books CSV File'),
self.booksLocationEdit) self.booksLocationEdit, u'%s (*.csv)'
% translate('BiblesPlugin.ImportWizardForm', 'CSV File'))
def onCsvVersesFileButtonClicked(self): def onCsvVersesFileButtonClicked(self):
""" """
Show the file open dialog for the verses CSV file. Show the file open dialog for the verses CSV file.
""" """
self.getFileName(translate('BiblesPlugin.ImportWizardForm', 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): def onOpenSongBrowseButtonClicked(self):
""" """
@ -275,7 +278,9 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard):
""" """
self.getFileName( self.getFileName(
translate('BiblesPlugin.ImportWizardForm', 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): def onCurrentIdChanged(self, pageId):
if pageId == 3: if pageId == 3:
@ -338,31 +343,27 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard):
""" """
Load the list of Crosswalk and BibleGateway bibles. Load the list of Crosswalk and BibleGateway bibles.
""" """
# Load and store Crosswalk Bibles. # Load Crosswalk Bibles.
filepath = AppLocation.get_directory(AppLocation.PluginsDir) filepath = AppLocation.get_directory(AppLocation.PluginsDir)
filepath = os.path.join(filepath, u'bibles', u'resources') filepath = os.path.join(filepath, u'bibles', u'resources')
books_file = None books_file = None
try: try:
self.web_bible_list[WebDownload.Crosswalk] = {} self.web_bible_list[WebDownload.Crosswalk] = {}
books_file = open( 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)) dialect = csv.Sniffer().sniff(books_file.read(1024))
books_file.seek(0) books_file.seek(0)
books_reader = csv.reader(books_file, dialect) books_reader = csv.reader(books_file, dialect)
for line in books_reader: for line in books_reader:
ver = line[0] ver = unicode(line[0], u'utf-8')
name = line[1] name = unicode(line[1], u'utf-8')
if not isinstance(ver, unicode):
ver = unicode(ver, u'utf8')
if not isinstance(name, unicode):
name = unicode(name, u'utf8')
self.web_bible_list[WebDownload.Crosswalk][ver] = name.strip() self.web_bible_list[WebDownload.Crosswalk][ver] = name.strip()
except IOError: except IOError:
log.exception(u'Crosswalk resources missing') log.exception(u'Crosswalk resources missing')
finally: finally:
if books_file: if books_file:
books_file.close() books_file.close()
# Load and store BibleGateway Bibles. # Load BibleGateway Bibles.
books_file = None books_file = None
try: try:
self.web_bible_list[WebDownload.BibleGateway] = {} self.web_bible_list[WebDownload.BibleGateway] = {}
@ -384,10 +385,50 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard):
finally: finally:
if books_file: if books_file:
books_file.close() 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, 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: if filename:
editbox.setText(filename) editbox.setText(filename)
SettingsManager.set_last_dir( SettingsManager.set_last_dir(
@ -457,6 +498,9 @@ class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard):
elif download_location == WebDownload.BibleGateway: elif download_location == WebDownload.BibleGateway:
bible = \ bible = \
self.web_bible_list[WebDownload.BibleGateway][bible_version] 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( importer = self.manager.import_bible(
BibleFormat.WebDownload, BibleFormat.WebDownload,
name=license_version, name=license_version,

View File

@ -208,6 +208,7 @@ class Ui_BibleImportWizard(object):
self.locationComboBox.setObjectName(u'LocationComboBox') self.locationComboBox.setObjectName(u'LocationComboBox')
self.locationComboBox.addItem(u'') self.locationComboBox.addItem(u'')
self.locationComboBox.addItem(u'') self.locationComboBox.addItem(u'')
self.locationComboBox.addItem(u'')
self.downloadOptionsLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.downloadOptionsLayout.setWidget(0, QtGui.QFormLayout.FieldRole,
self.locationComboBox) self.locationComboBox)
self.bibleLabel = QtGui.QLabel(self.downloadOptionsTab) self.bibleLabel = QtGui.QLabel(self.downloadOptionsTab)
@ -388,6 +389,8 @@ class Ui_BibleImportWizard(object):
translate('BiblesPlugin.ImportWizardForm', 'Crosswalk')) translate('BiblesPlugin.ImportWizardForm', 'Crosswalk'))
self.locationComboBox.setItemText(1, self.locationComboBox.setItemText(1,
translate('BiblesPlugin.ImportWizardForm', 'BibleGateway')) translate('BiblesPlugin.ImportWizardForm', 'BibleGateway'))
self.locationComboBox.setItemText(2,
translate('BiblesPlugin.ImportWizardForm', 'Bibleserver'))
self.bibleLabel.setText( self.bibleLabel.setText(
translate('BiblesPlugin.ImportWizardForm', 'Bible:')) translate('BiblesPlugin.ImportWizardForm', 'Bible:'))
self.webDownloadTabWidget.setTabText( self.webDownloadTabWidget.setTabText(

View File

@ -32,134 +32,164 @@ import re
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
BIBLE_REFERENCE = re.compile( def get_reference_match(match_type):
r'^([\w ]+?) *([0-9]+)' # Initial book and chapter local_separator = unicode(u':;;\s*[:vV]\s*;;-;;\s*-\s*;;,;;\s*,\s*;;end'
r'(?: *[:|v|V] *([0-9]+))?' # Verse for first chapter ).split(u';;') # English
r'(?: *- *([0-9]+|end$))?' # Range for verses or chapters # local_separator = unicode(u',;;\s*,\s*;;-;;\s*-\s*;;.;;\.;;[Ee]nde'
r'(?:(?:,([0-9]+))?' # Second chapter # ).split(u';;') # German
r' *[,|:|v|V] *([0-9]+|end$)' # More range for verses or chapters separators = {
r'(?: *- *([0-9]+|end$))?)?$', # End of second verse range u'sep_v_display': local_separator[0], u'sep_v': local_separator[1],
re.UNICODE) 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): # verse range match: (<chapter>:)?<verse>(-((<chapter>:)?<verse>|end)?)?
""" range_string = str(r'(?:(?P<from_chapter>[0-9]+)%(sep_v)s)?(?P<from_verse>'
Check if a regular expression match group contains the text u'end' or r'[0-9]+)(?P<range_to>%(sep_r)s(?:(?:(?P<to_chapter>[0-9]+)%(sep_v)s)?'
should be converted to an int. r'(?P<to_verse>[0-9]+)|%(sep_e)s)?)?') % separators
if match_type == u'range':
``match_group`` return re.compile(r'^\s*' + range_string + r'\s*$', re.UNICODE)
The match group to check. elif match_type == u'range_separator':
""" return re.compile(separators[u'sep_l'])
if match_group == u'end': elif match_type == u'full':
return -1 # 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: else:
return int(match_group) return separators[match_type]
def parse_reference(reference): def parse_reference(reference):
""" """
This is the über-awesome function that takes a person's typed in string This is the next generation über-awesome function that takes a person's
and converts it to a reference list, a list of references to be queried typed in string and converts it to a reference list, a list of references to
from the Bible database files. be queried from the Bible database files.
The ``BIBLE_REFERENCE`` constant regular expression produces the following This is a user manual like description, how the references are working.
match groups:
0. (match string) - Each reference starts with the book name. A chapter name is manditory.
This is a special group consisting of the whole string that matched. ``John 3`` refers to Gospel of John chapter 3
1. ``[\w ]+`` - A reference range can be given after a range separator.
The book the reference is from. ``John 3-5`` refers to John chapters 3 to 5
2. ``[0-9]+`` - Single verses can be addressed after a verse separator
The first (or only) chapter in the reference. ``John 3:16`` refers to John chapter 3 verse 16
3. ``None`` or ``[0-9]+`` ``John 3:16-4:3`` refers to John chapter 3 verse 16 to chapter 4 verse 3
``None``, or the only verse, or the first verse in a verse range or, - After a verse reference all further single values are treat as verse in
the start verse in a chapter range. the last selected chapter.
4. ``None`` or ``[0-9]+`` or ``end`` ``John 3:16-18`` refers to John chapter 3 verses 16 to 18
``None``, or the end verse of the first verse range, or the end chapter - After a list separator it is possible to refer to additional verses. They
of a chapter range. are build analog to the first ones. This way it is possible to define each
5. ``None`` or ``[0-9]+`` number of verse references. It is not possible to refer to verses in
``None``, or the second chapter in multiple (non-ranged) chapters. additional books.
6. ``None`` or ``[0-9]+`` or ``end`` ``John 3:16,18`` refers to John chapter 3 verses 16 and 18
``None``, the start of the second verse range. or the end of a chapter ``John 3:16-18,20`` refers to John chapter 3 verses 16 to 18 and 20
range. ``John 3:16-18,4:1`` refers to John chapter 3 verses 16 to 18 and
7. ``None`` or ``[0-9]+`` or ``end`` chapter 3 verse 1
``None``, or the end of the second verse range. - 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 The reference list is a list of tuples, with each tuple structured like
this:: this::
(book, chapter, start_verse, end_verse) (book, chapter, from_verse, to_verse)
``reference`` ``reference``
The bible reference to parse. The bible reference to parse.
Returns None or a reference list. Returns None or a reference list.
""" """
reference = reference.strip()
log.debug('parse_reference("%s")', reference) log.debug('parse_reference("%s")', reference)
unified_ref_list = [] match = get_reference_match(u'full').match(reference)
match = BIBLE_REFERENCE.match(reference)
if match: if match:
log.debug(u'Matched reference %s' % reference) log.debug(u'Matched reference %s' % reference)
book = match.group(1) book = match.group(u'book')
chapter = int(match.group(2)) ranges = match.group(u'ranges')
if match.group(7): range_list = get_reference_match(u'range_separator').split(ranges)
# Two verse ranges ref_list = []
vr1_start = int(match.group(3)) chapter = None
vr1_end = int(match.group(4)) for this_range in range_list:
unified_ref_list.append((book, chapter, vr1_start, vr1_end)) range_match = get_reference_match(u'range').match(this_range)
vr2_start = int(match.group(6)) from_chapter = range_match.group(u'from_chapter')
vr2_end = check_end(match.group(7)) from_verse = range_match.group(u'from_verse')
if match.group(5): has_range = range_match.group(u'range_to')
# One verse range per chapter to_chapter = range_match.group(u'to_chapter')
chapter2 = int(match.group(5)) to_verse = range_match.group(u'to_verse')
unified_ref_list.append((book, chapter2, vr2_start, vr2_end)) 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: else:
unified_ref_list.append((book, chapter, vr2_start, vr2_end)) from_chapter = from_verse
elif match.group(6): from_verse = None
# Chapter range with verses if to_chapter:
if match.group(3): if to_chapter < from_chapter:
vr1_start = int(match.group(3)) 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))
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))
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: else:
log.debug(u'Ambiguous reference: %s' % reference) chapter = to_chapter
return None elif to_verse:
elif match.group(4) != u'end': if chapter:
for i in range(chapter, int(match.group(4)) + 1): to_chapter = chapter
unified_ref_list.append((book, i, 1, -1)) else:
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: else:
log.debug(u'Unsupported reference: %s' % reference) ref_list.append((book, from_chapter, 1, -1))
return None return ref_list
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))
else: else:
log.debug(u'Invalid reference: %s' % reference) log.debug(u'Invalid reference: %s' % reference)
return None return None
return unified_ref_list
class SearchResults(object): class SearchResults(object):

View File

@ -240,6 +240,66 @@ class BGExtract(object):
return SearchResults(bookname, chapter, verse_list) 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')
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): class CWExtract(object):
""" """
Extract verses from CrossWalk/BibleStudyTools Extract verses from CrossWalk/BibleStudyTools
@ -350,7 +410,7 @@ class HTTPBible(BibleDB):
Run the import. This method overrides the parent class method. Returns Run the import. This method overrides the parent class method. Returns
``True`` on success, ``False`` on failure. ``True`` on success, ``False`` on failure.
""" """
self.wizard.ImportProgressBar.setMaximum(2) self.wizard.importProgressBar.setMaximum(2)
self.wizard.incrementProgressBar('Registering bible...') self.wizard.incrementProgressBar('Registering bible...')
self.create_meta(u'download source', self.download_source) self.create_meta(u'download source', self.download_source)
self.create_meta(u'download name', self.download_name) self.create_meta(u'download name', self.download_name)
@ -426,8 +486,10 @@ class HTTPBible(BibleDB):
log.debug(u'source = %s', self.download_source) log.debug(u'source = %s', self.download_source)
if self.download_source.lower() == u'crosswalk': if self.download_source.lower() == u'crosswalk':
ev = CWExtract(self.proxy_server) ev = CWExtract(self.proxy_server)
else: elif self.download_source.lower() == u'biblegateway':
ev = BGExtract(self.proxy_server) 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) return ev.get_bible_chapter(self.download_name, book, chapter)
def get_books(self): def get_books(self):

View File

@ -112,6 +112,7 @@ class BibleFormat(object):
def get_availability(format): def get_availability(format):
return BibleFormat._format_availability.get(format, True) return BibleFormat._format_availability.get(format, True)
class BibleManager(object): class BibleManager(object):
""" """
The Bible manager which holds and manages all the Bibles. The Bible manager which holds and manages all the Bibles.
@ -311,7 +312,7 @@ class BibleManager(object):
'Scripture Reference Error'), 'Scripture Reference Error'),
translate('BiblesPlugin.BibleManager', 'You did not enter a ' translate('BiblesPlugin.BibleManager', 'You did not enter a '
'search keyword.\nYou can separate different keywords by 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.')) 'them by a comma to search for one of them.'))
return None return None
@ -356,3 +357,4 @@ class BibleManager(object):
BibleFormat.set_availability(BibleFormat.OpenLP1, has_openlp1) BibleFormat.set_availability(BibleFormat.OpenLP1, has_openlp1)
__all__ = [u'BibleFormat'] __all__ = [u'BibleFormat']

View File

@ -32,6 +32,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import MediaManagerItem, Receiver, BaseListWithDnD, \ from openlp.core.lib import MediaManagerItem, Receiver, BaseListWithDnD, \
ItemCapabilities, translate ItemCapabilities, translate
from openlp.plugins.bibles.forms import BibleImportForm from openlp.plugins.bibles.forms import BibleImportForm
from openlp.plugins.bibles.lib import get_reference_match
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -72,7 +73,7 @@ class BibleMediaItem(MediaManagerItem):
self.hasNewIcon = False self.hasNewIcon = False
self.hasEditIcon = False self.hasEditIcon = False
self.hasDeleteIcon = False self.hasDeleteIcon = False
self.addToServiceItem = True self.addToServiceItem = False
def addEndHeaderBar(self): def addEndHeaderBar(self):
self.SearchTabWidget = QtGui.QTabWidget(self) self.SearchTabWidget = QtGui.QTabWidget(self)
@ -553,12 +554,15 @@ class BibleMediaItem(MediaManagerItem):
bible = unicode(self.AdvancedVersionComboBox.currentText()) bible = unicode(self.AdvancedVersionComboBox.currentText())
second_bible = unicode(self.AdvancedSecondBibleComboBox.currentText()) second_bible = unicode(self.AdvancedSecondBibleComboBox.currentText())
book = unicode(self.AdvancedBookComboBox.currentText()) book = unicode(self.AdvancedBookComboBox.currentText())
chapter_from = int(self.AdvancedFromChapter.currentText()) chapter_from = self.AdvancedFromChapter.currentText()
chapter_to = int(self.AdvancedToChapter.currentText()) chapter_to = self.AdvancedToChapter.currentText()
verse_from = int(self.AdvancedFromVerse.currentText()) verse_from = self.AdvancedFromVerse.currentText()
verse_to = int(self.AdvancedToVerse.currentText()) verse_to = self.AdvancedToVerse.currentText()
versetext = u'%s %s:%s-%s:%s' % (book, chapter_from, verse_from, verse_separator = get_reference_match(u'sep_v_display')
chapter_to, verse_to) 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) self.search_results = self.parent.manager.get_verses(bible, versetext)
if second_bible: if second_bible:
self.second_search_results = self.parent.manager.get_verses( self.second_search_results = self.parent.manager.get_verses(
@ -709,7 +713,7 @@ class BibleMediaItem(MediaManagerItem):
obj = reference[QtCore.QString(key)] obj = reference[QtCore.QString(key)]
if isinstance(obj, QtCore.QVariant): if isinstance(obj, QtCore.QVariant):
obj = obj.toPyObject() obj = obj.toPyObject()
return unicode(obj) return unicode(obj).strip()
def generateSlideData(self, service_item, item=None, xmlVersion=False): def generateSlideData(self, service_item, item=None, xmlVersion=False):
""" """
@ -739,7 +743,8 @@ class BibleMediaItem(MediaManagerItem):
second_bible = self._decodeQtObject(bitem, 'second_bible') second_bible = self._decodeQtObject(bitem, 'second_bible')
second_version = self._decodeQtObject(bitem, 'second_version') second_version = self._decodeQtObject(bitem, 'second_version')
second_copyright = self._decodeQtObject(bitem, 'second_copyright') 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') second_text = self._decodeQtObject(bitem, 'second_text')
verse_text = self.formatVerse(old_chapter, chapter, verse) verse_text = self.formatVerse(old_chapter, chapter, verse)
footer = u'%s (%s %s %s)' % (book, version, copyright, permissions) footer = u'%s (%s %s %s)' % (book, version, copyright, permissions)
@ -750,21 +755,21 @@ class BibleMediaItem(MediaManagerItem):
second_copyright, second_permissions) second_copyright, second_permissions)
if footer not in raw_footer: if footer not in raw_footer:
raw_footer.append(footer) raw_footer.append(footer)
bible_text = u'%s %s\n\n%s %s' % (verse_text, text, verse_text, bible_text = u'%s\u00a0%s\n\n%s\u00a0%s' % (verse_text, text,
second_text) verse_text, second_text)
raw_slides.append(bible_text) raw_slides.append(bible_text)
bible_text = u'' bible_text = u''
# If we are 'Verse Per Slide' then create a new slide. # If we are 'Verse Per Slide' then create a new slide.
elif self.parent.settings_tab.layout_style == 0: 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) raw_slides.append(bible_text)
bible_text = u'' bible_text = u''
# If we are 'Verse Per Line' then force a new line. # If we are 'Verse Per Line' then force a new line.
elif self.parent.settings_tab.layout_style == 1: 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'. # We have to be 'Continuous'.
else: 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: if first_item:
start_item = item start_item = item
first_item = False first_item = False
@ -816,36 +821,31 @@ class BibleMediaItem(MediaManagerItem):
``old_item`` ``old_item``
The last item of a range. 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_bitem = self.listView.item(old_item.row())
old_chapter = int(self._decodeQtObject(old_bitem, 'chapter')) old_chapter = self._decodeQtObject(old_bitem, 'chapter')
old_verse = int(self._decodeQtObject(old_bitem, 'verse')) old_verse = self._decodeQtObject(old_bitem, 'verse')
start_bitem = self.listView.item(start_item.row()) start_bitem = self.listView.item(start_item.row())
start_book = self._decodeQtObject(start_bitem, 'book') start_book = self._decodeQtObject(start_bitem, 'book')
start_chapter = int(self._decodeQtObject(start_bitem, 'chapter')) start_chapter = self._decodeQtObject(start_bitem, 'chapter')
start_verse = int(self._decodeQtObject(start_bitem, 'verse')) start_verse = self._decodeQtObject(start_bitem, 'verse')
start_bible = self._decodeQtObject(start_bitem, 'bible') start_bible = self._decodeQtObject(start_bitem, 'bible')
start_second_bible = self._decodeQtObject(start_bitem, 'second_bible') start_second_bible = self._decodeQtObject(start_bitem, 'second_bible')
if start_second_bible: if start_second_bible:
if start_verse == old_verse and start_chapter == old_chapter: bibles = u'%s, %s' % (start_bible, start_second_bible)
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)
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)
else: else:
if start_verse == old_verse and start_chapter == old_chapter: bibles = start_bible
title = u'%s %s:%s (%s)' % (start_book, start_chapter, if start_chapter == old_chapter:
start_verse, start_bible) if start_verse == old_verse:
elif start_chapter == old_chapter: verse_range = start_chapter + verse_separator + start_verse
title = u'%s %s:%s-%s (%s)' % (start_book, start_chapter,
start_verse, old_verse, start_bible)
else: else:
title = u'%s %s:%s-%s:%s (%s)' % (start_book, start_chapter, verse_range = start_chapter + verse_separator + start_verse + \
start_verse, old_chapter, old_verse, start_bible) range_separator + old_verse
else:
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 return title
def checkTitle(self, item, old_item): def checkTitle(self, item, old_item):
@ -907,9 +907,10 @@ class BibleMediaItem(MediaManagerItem):
``verse`` ``verse``
The verse number (int). The verse number (int).
""" """
verse_separator = get_reference_match(u'sep_v_display')
if not self.parent.settings_tab.show_new_chapters or \ if not self.parent.settings_tab.show_new_chapters or \
old_chapter != chapter: old_chapter != chapter:
verse_text = u'%s:%s' % (chapter, verse) verse_text = unicode(chapter) + verse_separator + unicode(verse)
else: else:
verse_text = u'%s' % verse verse_text = u'%s' % verse
if self.parent.settings_tab.display_style == 1: if self.parent.settings_tab.display_style == 1:

0
openlp/plugins/bibles/lib/openlp1.py Executable file → Normal file
View File

View File

@ -134,9 +134,9 @@ class OSISBible(BibleDB):
testament) testament)
if last_chapter == 0: if last_chapter == 0:
if book == u'Gen': if book == u'Gen':
self.wizard.ImportProgressBar.setMaximum(1188) self.wizard.importProgressBar.setMaximum(1188)
else: else:
self.wizard.ImportProgressBar.setMaximum(260) self.wizard.importProgressBar.setMaximum(260)
if last_chapter != chapter: if last_chapter != chapter:
if last_chapter != 0: if last_chapter != 0:
self.session.commit() self.session.commit()

View File

@ -1,80 +1,81 @@
João Ferreira de Almeida Atualizada,AA
التفسير التطبيقى للكتاب المقدس,ALAB
Shqip,ALB
Amplified Bible,AMP
Amuzgo de Guerrero,AMU Amuzgo de Guerrero,AMU
Arabic Life Application Bible,ALAB American Standard Version,ASV
Bulgarian Bible,BULG La Bible du Semeur,BDS
1940 Bulgarian Bible,BG1940 Български 1940,BG1940
Chinanteco de Comaltepec,CCO Български,BULG
Cakchiquel Occidental,CKW Chinanteco de Comaltepec,CCO
Haitian Creole Version,HCV Contemporary English Version,CEV
Slovo na cestu,SNC Cakchiquel Occidental,CKW
Dette er Biblen på dansk,DN1933 Hrvatski,CRO
Hoffnung für Alle,HOF Castilian,CST
Luther Bibel 1545,LUTH1545 聖經和合本 (简体中文),CUVS
New International Version,NIV 聖經和合本 (繁体中文),CUV
New American Standard Bible,NASB Darby Translation,DARBY
The Message,MSG Dette er Biblen på dansk,DN1933
Amplified Bible,AMP Det Norsk Bibelselskap 1930,DNB1930
New Living Translation,NLT English Standard Version,ESV
King James Version,KJV GODS WORD Translation,GW
English Standard Version,ESV Holman Christian Standard Bible,HCSB
Contemporary English Version,CEV Kreyòl ayisyen bib,HCV
New King James Version,NKJV Hiligaynon Bible,HLGN
New Century Version,NCV Hoffnung für Alle,HOF
21st Century King James Version,KJ21 Het Boek,HTB
American Standard Version,ASV Icelandic Bible,ICELAND
Young's Literal Translation,YLT Jacalteco Oriental,JAC
Darby Translation,DARBY Károlyi-biblia,KAR
Holman Christian Standard Bible,HCSB Kekchi,KEK
New International Reader's Version,NIRV 21st Century King James Version,KJ21
Wycliffe New Testament,WYC King James Version,KJV
Worldwide English (New Testament),WE La Biblia de las Américas,LBLA
New International Version - UK,NIVUK Levande Bibeln,LB
Today's New International Version,TNIV 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
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 1960,RVR1960
Nueva Versión Internacional,NVI Reina-Valera 1995,RVR1995
Reina-Valera 1995,RVR1995 Slovo na cestu,SNC
Castilian,CST Ang Salita ng Diyos,SND
Reina-Valera Antigua,RVA Swahili New Testament,SNT
Biblia en Lenguaje Sencillo,BLS Svenska 1917,SV1917
La Biblia de las Américas,LBLA Levande Bibeln,SVL
Louis Segond,LSG Создать страницу,SZ
La Bible du Semeur,BDS Traducción en lenguaje actual,TLA
1881 Westcott-Hort New Testament,WHNU New Romanian Translation,TLCR
1550 Stephanus New Testament,TR1550 Todays New International Version 2005,TNIV
1894 Scrivener New Testament,TR1894 Textus Receptus Stephanus 1550,TR1550
The Westminster Leningrad Codex,WLC Textus Receptus Scrivener 1894,TR1894
Hiligaynon Bible,HLGN Українська Біблія. Переклад Івана Огієнка,UKR
Croatian Bible,CRO Uspanteco,USP
Hungarian Károli,KAR Kinh Thánh tiếng Việt 1934,VIET
Icelandic Bible,ICELAND Worldwide English (New Testament),WE
La Nuova Diodati,LND Codex Vaticanus Westcott-Hort 1881,WHNU
La Parola è Vita,LM Westminster Leningrad Codex,WLC
Jacalteco, Oriental,JAC Wycliffe New Testament,WYC
Kekchi,KEK Young's Literal Translation,YLT
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
Nádej pre kazdého,NPK
Albanian Bible,ALB
Levande Bibeln,SVL
Svenska 1917,SV1917
Swahili New Testament,SNT
Ang Salita ng Diyos,SND
Ukrainian Bible,UKR
Uspanteco,USP
1934 Vietnamese Bible,VIET
Chinese Union Version (Simplified),CUVS
Chinese Union Version (Traditional),CUV

Can't render this file because it has a wrong number of fields in line 51.

View 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
1 عربي ARA
2 Bible – překlad 21. století B21
3 Bible du Semeur BDS
4 Българската Библия BLG
5 Český ekumenický překlad CEP
6 Hrvatski CRO
7 Священное Писание CRS
8 Version La Biblia al Dia CST
9 中文和合本(简体) CUVS
10 Bibelen på hverdagsdansk DK
11 Revidierte Elberfelder ELB
12 Einheitsübersetzung EU
13 Gute Nachricht Bibel GNB
14 Hoffnung für alle HFA
15 Hungarian HUN
16 Het Boek HTB
17 La Parola è Vita ITA
18 IBS-fordítás (Új Károli) KAR
19 King James Version KJV
20 Luther 1984 LUT
21 Septuaginta LXX
22 Neue Genfer Übersetzung NGÜ
23 New International Readers Version NIRV
24 New International Version NIV
25 Neues Leben NL
26 En Levende Bok (NOR) NOR
27 Nádej pre kazdého NPK
28 Noua traducere în limba românã NTR
29 Nueva Versión Internacional NVI
30 הברית הישנה OT
31 Słowo Życia POL
32 O Livro PRT
33 Новый перевод на русский язык RUS
34 Slovo na cestu SNC
35 Schlachter 2000 SLT
36 En Levande Bok (SWE) SVL
37 Today's New International Version TNIV
38 Türkçe TR
39 Biblia Vulgata VUL

View File

@ -24,4 +24,4 @@ New International Reader's Version,nrv
The Darby Translation,dby The Darby Translation,dby
The Webster Bible,wbt The Webster Bible,wbt
The Latin Vulgate,vul The Latin Vulgate,vul
Weymouth New Testament,wnt Weymouth New Testament,wnt

1 New American Standard nas
24 The Darby Translation dby
25 The Webster Bible wbt
26 The Latin Vulgate vul
27 Weymouth New Testament wnt

View File

@ -109,7 +109,7 @@ class CustomPlugin(Plugin):
} }
## Name for MediaDockManager, SettingsManager ## ## Name for MediaDockManager, SettingsManager ##
self.textStrings[StringContent.VisibleName] = { self.textStrings[StringContent.VisibleName] = {
u'title': translate('CustomsPlugin', 'Customs') u'title': translate('CustomsPlugin', 'Custom')
} }
# Middle Header Bar # Middle Header Bar
## Import Button ## ## Import Button ##

View File

@ -31,7 +31,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import MediaManagerItem, BaseListWithDnD, build_icon, \ from openlp.core.lib import MediaManagerItem, BaseListWithDnD, build_icon, \
context_menu_action, ItemCapabilities, SettingsManager, translate, \ context_menu_action, ItemCapabilities, SettingsManager, translate, \
check_item_selected check_item_selected, Receiver
from openlp.core.utils import AppLocation, get_images_filter from openlp.core.utils import AppLocation, get_images_filter
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -139,6 +139,8 @@ class ImageMediaItem(MediaManagerItem):
self.settingsSection, self.getFileList()) self.settingsSection, self.getFileList())
def loadList(self, list): def loadList(self, list):
self.listView.setCursor(QtCore.Qt.BusyCursor)
Receiver.send_message(u'openlp_process_events')
for file in list: for file in list:
filename = os.path.split(unicode(file))[1] filename = os.path.split(unicode(file))[1]
thumb = os.path.join(self.servicePath, filename) thumb = os.path.join(self.servicePath, filename)
@ -153,6 +155,8 @@ class ImageMediaItem(MediaManagerItem):
item_name.setIcon(icon) item_name.setIcon(icon)
item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(file)) item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(file))
self.listView.addItem(item_name) 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): def generateSlideData(self, service_item, item=None, xmlVersion=False):
items = self.listView.selectedIndexes() items = self.listView.selectedIndexes()

View File

@ -108,6 +108,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.TopicsListView.setSortingEnabled(False) self.TopicsListView.setSortingEnabled(False)
self.TopicsListView.setAlternatingRowColors(True) self.TopicsListView.setAlternatingRowColors(True)
self.findVerseSplit = re.compile(u'---\[\]---\n', re.UNICODE) self.findVerseSplit = re.compile(u'---\[\]---\n', re.UNICODE)
self.whitespace = re.compile(r'\W+', re.UNICODE)
def initialise(self): def initialise(self):
self.VerseEditButton.setEnabled(False) self.VerseEditButton.setEnabled(False)
@ -546,14 +547,11 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
if self.AuthorsListView.count() == 0: if self.AuthorsListView.count() == 0:
self.SongTabWidget.setCurrentIndex(1) self.SongTabWidget.setCurrentIndex(1)
self.AuthorsListView.setFocus() self.AuthorsListView.setFocus()
answer = QtGui.QMessageBox.warning(self, QtGui.QMessageBox.critical(self,
translate('SongsPlugin.EditSongForm', 'Warning'), translate('SongsPlugin.EditSongForm', 'Warning'),
translate('SongsPlugin.EditSongForm', translate('SongsPlugin.EditSongForm',
'You have not added any authors for this song. Do you ' 'You need to have an author for this song.'))
'want to add an author now?'), return False
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
if answer == QtGui.QMessageBox.Yes:
return False
if self.song.verse_order: if self.song.verse_order:
order = [] order = []
order_names = self.song.verse_order.split() order_names = self.song.verse_order.split()
@ -738,7 +736,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
verseId = unicode(item.data(QtCore.Qt.UserRole).toString()) verseId = unicode(item.data(QtCore.Qt.UserRole).toString())
bits = verseId.split(u':') bits = verseId.split(u':')
sxml.add_verse_to_lyrics(bits[0], bits[1], unicode(item.text())) 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' ' unicode(self.VerseListWidget.item(i, 0).text())) + u' '
if (bits[1] > u'1') and (bits[0][0] not in multiple): if (bits[1] > u'1') and (bits[0][0] not in multiple):
multiple.append(bits[0][0]) multiple.append(bits[0][0])

View File

@ -29,7 +29,7 @@ import logging
from PyQt4 import QtCore, QtGui 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 from editversedialog import Ui_EditVerseDialog
@ -131,6 +131,7 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog):
def setVerse(self, text, single=False, def setVerse(self, text, single=False,
tag=u'%s:1' % VerseType.to_string(VerseType.Verse)): tag=u'%s:1' % VerseType.to_string(VerseType.Verse)):
self.hasSingleVerse = single
if single: if single:
verse_type, verse_number = tag.split(u':') verse_type, verse_number = tag.split(u':')
verse_type_index = VerseType.from_string(verse_type) 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 = u'---[%s:1]---\n%s' % (VerseType.to_string(VerseType.Verse),
text) text)
return 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)

View File

@ -152,101 +152,101 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard):
if self.openLP2FilenameEdit.text().isEmpty(): if self.openLP2FilenameEdit.text().isEmpty():
QtGui.QMessageBox.critical(self, QtGui.QMessageBox.critical(self,
translate('SongsPlugin.ImportWizardForm', translate('SongsPlugin.ImportWizardForm',
'No OpenLP 2.0 Song Database Selected'), 'No OpenLP 2.0 Song Database Selected'),
translate('SongsPlugin.ImportWizardForm', translate('SongsPlugin.ImportWizardForm',
'You need to select an OpenLP 2.0 song database ' 'You need to select an OpenLP 2.0 song database '
'file to import from.')) 'file to import from.'))
self.openLP2BrowseButton.setFocus() self.openLP2BrowseButton.setFocus()
return False return False
elif source_format == SongFormat.OpenLP1: elif source_format == SongFormat.OpenLP1:
if self.openLP1FilenameEdit.text().isEmpty(): if self.openLP1FilenameEdit.text().isEmpty():
QtGui.QMessageBox.critical(self, QtGui.QMessageBox.critical(self,
translate('SongsPlugin.ImportWizardForm', translate('SongsPlugin.ImportWizardForm',
'No openlp.org 1.x Song Database Selected'), 'No openlp.org 1.x Song Database Selected'),
translate('SongsPlugin.ImportWizardForm', translate('SongsPlugin.ImportWizardForm',
'You need to select an openlp.org 1.x song ' 'You need to select an openlp.org 1.x song '
'database file to import from.')) 'database file to import from.'))
self.openLP1BrowseButton.setFocus() self.openLP1BrowseButton.setFocus()
return False return False
elif source_format == SongFormat.OpenLyrics: elif source_format == SongFormat.OpenLyrics:
#if self.openLyricsFileListWidget.count() == 0: # if self.openLyricsFileListWidget.count() == 0:
# QtGui.QMessageBox.critical(self, # QtGui.QMessageBox.critical(self,
# translate('SongsPlugin.ImportWizardForm', # translate('SongsPlugin.ImportWizardForm',
# 'No OpenLyrics Files Selected'), # 'No OpenLyrics Files Selected'),
# translate('SongsPlugin.ImportWizardForm', # translate('SongsPlugin.ImportWizardForm',
# 'You need to add at least one OpenLyrics ' # 'You need to add at least one OpenLyrics '
# 'song file to import from.')) # 'song file to import from.'))
# self.openLyricsAddButton.setFocus() # self.openLyricsAddButton.setFocus()
# return False # return False
return False return False
elif source_format == SongFormat.OpenSong: elif source_format == SongFormat.OpenSong:
if self.openSongFileListWidget.count() == 0: if self.openSongFileListWidget.count() == 0:
QtGui.QMessageBox.critical(self, QtGui.QMessageBox.critical(self,
translate('SongsPlugin.ImportWizardForm', translate('SongsPlugin.ImportWizardForm',
'No OpenSong Files Selected'), 'No OpenSong Files Selected'),
translate('SongsPlugin.ImportWizardForm', translate('SongsPlugin.ImportWizardForm',
'You need to add at least one OpenSong ' 'You need to add at least one OpenSong '
'song file to import from.')) 'song file to import from.'))
self.openSongAddButton.setFocus() self.openSongAddButton.setFocus()
return False return False
elif source_format == SongFormat.WordsOfWorship: elif source_format == SongFormat.WordsOfWorship:
if self.wordsOfWorshipFileListWidget.count() == 0: if self.wordsOfWorshipFileListWidget.count() == 0:
QtGui.QMessageBox.critical(self, QtGui.QMessageBox.critical(self,
translate('SongsPlugin.ImportWizardForm', translate('SongsPlugin.ImportWizardForm',
'No Words of Worship Files Selected'), 'No Words of Worship Files Selected'),
translate('SongsPlugin.ImportWizardForm', translate('SongsPlugin.ImportWizardForm',
'You need to add at least one Words of Worship ' 'You need to add at least one Words of Worship '
'file to import from.')) 'file to import from.'))
self.wordsOfWorshipAddButton.setFocus() self.wordsOfWorshipAddButton.setFocus()
return False return False
elif source_format == SongFormat.CCLI: elif source_format == SongFormat.CCLI:
if self.ccliFileListWidget.count() == 0: if self.ccliFileListWidget.count() == 0:
QtGui.QMessageBox.critical(self, QtGui.QMessageBox.critical(self,
translate('SongsPlugin.ImportWizardForm', translate('SongsPlugin.ImportWizardForm',
'No CCLI Files Selected'), 'No CCLI Files Selected'),
translate('SongsPlugin.ImportWizardForm', translate('SongsPlugin.ImportWizardForm',
'You need to add at least one CCLI file ' 'You need to add at least one CCLI file '
'to import from.')) 'to import from.'))
self.ccliAddButton.setFocus() self.ccliAddButton.setFocus()
return False return False
elif source_format == SongFormat.SongsOfFellowship: elif source_format == SongFormat.SongsOfFellowship:
if self.songsOfFellowshipFileListWidget.count() == 0: if self.songsOfFellowshipFileListWidget.count() == 0:
QtGui.QMessageBox.critical(self, QtGui.QMessageBox.critical(self,
translate('SongsPlugin.ImportWizardForm', translate('SongsPlugin.ImportWizardForm',
'No Songs of Fellowship File Selected'), 'No Songs of Fellowship File Selected'),
translate('SongsPlugin.ImportWizardForm', translate('SongsPlugin.ImportWizardForm',
'You need to add at least one Songs of Fellowship ' 'You need to add at least one Songs of Fellowship '
'file to import from.')) 'file to import from.'))
self.songsOfFellowshipAddButton.setFocus() self.songsOfFellowshipAddButton.setFocus()
return False return False
elif source_format == SongFormat.Generic: elif source_format == SongFormat.Generic:
if self.genericFileListWidget.count() == 0: if self.genericFileListWidget.count() == 0:
QtGui.QMessageBox.critical(self, QtGui.QMessageBox.critical(self,
translate('SongsPlugin.ImportWizardForm', translate('SongsPlugin.ImportWizardForm',
'No Document/Presentation Selected'), 'No Document/Presentation Selected'),
translate('SongsPlugin.ImportWizardForm', translate('SongsPlugin.ImportWizardForm',
'You need to add at least one document or ' 'You need to add at least one document or '
'presentation file to import from.')) 'presentation file to import from.'))
self.genericAddButton.setFocus() self.genericAddButton.setFocus()
return False return False
elif source_format == SongFormat.EasyWorship: elif source_format == SongFormat.EasyWorship:
if self.ewFilenameEdit.text().isEmpty(): if self.ewFilenameEdit.text().isEmpty():
QtGui.QMessageBox.critical(self, QtGui.QMessageBox.critical(self,
translate('SongsPlugin.ImportWizardForm', translate('SongsPlugin.ImportWizardForm',
'No EasyWorship Song Database Selected'), 'No EasyWorship Song Database Selected'),
translate('SongsPlugin.ImportWizardForm', translate('SongsPlugin.ImportWizardForm',
'You need to select an EasyWorship song database ' 'You need to select an EasyWorship song database '
'file to import from.')) 'file to import from.'))
self.ewBrowseButton.setFocus() self.ewBrowseButton.setFocus()
return False return False
elif source_format == SongFormat.SongBeamer: elif source_format == SongFormat.SongBeamer:
if self.songBeamerFileListWidget.count() == 0: if self.songBeamerFileListWidget.count() == 0:
QtGui.QMessageBox.critical(self, QtGui.QMessageBox.critical(self,
translate('SongsPlugin.ImportWizardForm', translate('SongsPlugin.ImportWizardForm',
'No SongBeamer File Selected'), 'No SongBeamer File Selected'),
translate('SongsPlugin.ImportWizardForm', translate('SongsPlugin.ImportWizardForm',
'You need to add at least one SongBeamer ' 'You need to add at least one SongBeamer '
'file to import from.')) 'file to import from.'))
self.songBeamerAddButton.setFocus() self.songBeamerAddButton.setFocus()
return False return False
return True return True
@ -254,24 +254,57 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard):
# Progress page # Progress page
return True return True
def getFileName(self, title, editbox, def getFileName(self, title, editbox, filters=u''):
filters = '%s (*)' % translate('SongsPlugin.ImportWizardForm', """
'All Files')): 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, filename = QtGui.QFileDialog.getOpenFileName(self, title,
SettingsManager.get_last_dir(self.plugin.settingsSection, 1), os.path.dirname(SettingsManager.get_last_dir(
filters) self.plugin.settingsSection, 1)), filters)
if filename: if filename:
editbox.setText(filename) editbox.setText(filename)
SettingsManager.set_last_dir( SettingsManager.set_last_dir(self.plugin.settingsSection,
self.plugin.settingsSection,
os.path.split(unicode(filename))[0], 1) os.path.split(unicode(filename))[0], 1)
def getFiles(self, title, listbox, def getFiles(self, title, listbox, filters=u''):
filters = u'%s (*)' % translate('SongsPlugin.ImportWizardForm', """
'All Files')): 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, filenames = QtGui.QFileDialog.getOpenFileNames(self, title,
SettingsManager.get_last_dir(self.plugin.settingsSection, 1), os.path.dirname(SettingsManager.get_last_dir(
filters) self.plugin.settingsSection, 1)), filters)
if filenames: if filenames:
listbox.addItems(filenames) listbox.addItems(filenames)
SettingsManager.set_last_dir( SettingsManager.set_last_dir(
@ -293,24 +326,18 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard):
self.getFileName( self.getFileName(
translate('SongsPlugin.ImportWizardForm', translate('SongsPlugin.ImportWizardForm',
'Select OpenLP 2.0 Database File'), 'Select OpenLP 2.0 Database File'),
self.openLP2FilenameEdit, self.openLP2FilenameEdit, u'%s (*.sqlite)'
u'%s (*.sqlite);;%s (*)'
% (translate('SongsPlugin.ImportWizardForm', % (translate('SongsPlugin.ImportWizardForm',
'OpenLP 2.0 Databases'), 'OpenLP 2.0 Databases'))
translate('SongsPlugin.ImportWizardForm',
'All Files'))
) )
def onOpenLP1BrowseButtonClicked(self): def onOpenLP1BrowseButtonClicked(self):
self.getFileName( self.getFileName(
translate('SongsPlugin.ImportWizardForm', translate('SongsPlugin.ImportWizardForm',
'Select openlp.org 1.x Database File'), 'Select openlp.org 1.x Database File'),
self.openLP1FilenameEdit, self.openLP1FilenameEdit, u'%s (*.olp)'
u'%s (*.olp);;%s (*)' % translate('SongsPlugin.ImportWizardForm',
% (translate('SongsPlugin.ImportWizardForm', 'openlp.org v1.x Databases')
'openlp.org v1.x Databases'),
translate('SongsPlugin.ImportWizardForm',
'All Files'))
) )
#def onOpenLyricsAddButtonClicked(self): #def onOpenLyricsAddButtonClicked(self):
@ -337,12 +364,9 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard):
self.getFiles( self.getFiles(
translate('SongsPlugin.ImportWizardForm', translate('SongsPlugin.ImportWizardForm',
'Select Words of Worship Files'), 'Select Words of Worship Files'),
self.wordsOfWorshipFileListWidget, self.wordsOfWorshipFileListWidget, u'%s (*.wsg *.wow-song)'
u'%s (*.wsg *.wow-song);;%s (*)' % translate('SongsPlugin.ImportWizardForm',
% (translate('SongsPlugin.ImportWizardForm', 'Words Of Worship Song Files')
'Words Of Worship Song Files'),
translate('SongsPlugin.ImportWizardForm',
'All Files'))
) )
def onWordsOfWorshipRemoveButtonClicked(self): def onWordsOfWorshipRemoveButtonClicked(self):
@ -362,12 +386,9 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard):
self.getFiles( self.getFiles(
translate('SongsPlugin.ImportWizardForm', translate('SongsPlugin.ImportWizardForm',
'Select Songs of Fellowship Files'), 'Select Songs of Fellowship Files'),
self.songsOfFellowshipFileListWidget, self.songsOfFellowshipFileListWidget, u'%s (*.rtf)'
u'%s (*.rtf);;%s (*)' % translate('SongsPlugin.ImportWizardForm',
% (translate('SongsPlugin.ImportWizardForm', 'Songs Of Felloship Song Files')
'Songs Of Felloship Song Files'),
translate('SongsPlugin.ImportWizardForm',
'All Files'))
) )
def onSongsOfFellowshipRemoveButtonClicked(self): def onSongsOfFellowshipRemoveButtonClicked(self):
@ -394,7 +415,8 @@ class SongImportForm(QtGui.QWizard, Ui_SongImportWizard):
self.getFiles( self.getFiles(
translate('SongsPlugin.ImportWizardForm', translate('SongsPlugin.ImportWizardForm',
'Select SongBeamer Files'), 'Select SongBeamer Files'),
self.songBeamerFileListWidget self.songBeamerFileListWidget, u'%s (*.sng)' %
translate('SongsPlugin.ImportWizardForm', 'SongBeamer files')
) )
def onSongBeamerRemoveButtonClicked(self): def onSongBeamerRemoveButtonClicked(self):

View File

@ -71,7 +71,8 @@ class VerseType(object):
The string to return a VerseType for The string to return a VerseType for
""" """
verse_type = verse_type.lower() 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') return translate('SongsPlugin.VerseType', 'Verse')
elif verse_type == \ elif verse_type == \
unicode(VerseType.to_string(VerseType.Chorus)).lower()[0]: unicode(VerseType.to_string(VerseType.Chorus)).lower()[0]:

View File

@ -197,7 +197,7 @@ class CCLIFileImport(SongImport):
verse_text = verse_lines[1] verse_text = verse_lines[1]
elif verse_lines[0].startswith(u'('): elif verse_lines[0].startswith(u'('):
verse_type = u'O' verse_type = u'O'
verse_text = verse_lines[1] verse_text = verse_lines[1]
if len(verse_text) > 0: if len(verse_text) > 0:
self.add_verse(verse_text, verse_type) self.add_verse(verse_text, verse_type)
check_first_verse_line = False check_first_verse_line = False
@ -303,13 +303,13 @@ class CCLIFileImport(SongImport):
verse_type = u'P' verse_type = u'P'
elif line.startswith(u'(BRIDGE'): elif line.startswith(u'(BRIDGE'):
verse_type = u'B' verse_type = u'B'
# Handle all other misc types # Handle all other misc types
elif line.startswith(u'('): elif line.startswith(u'('):
verse_type = u'O' verse_type = u'O'
else: else:
verse_text = verse_text + line verse_text = verse_text + line
check_first_verse_line = False check_first_verse_line = False
else: else:
# We have verse content or the start of the # We have verse content or the start of the
# last part. Add l so as to keep the CRLF # last part. Add l so as to keep the CRLF
verse_text = verse_text + line verse_text = verse_text + line

View File

@ -369,7 +369,7 @@ class SofImport(OooImport):
if song_number == 50: if song_number == 50:
return 8 return 8
if song_number == 70: if song_number == 70:
return 4 return 4
if song_number == 75: if song_number == 75:
return 8 return 8
if song_number == 79: if song_number == 79:
@ -529,7 +529,7 @@ class SofImport(OooImport):
if song_number == 955: if song_number == 955:
return 9 return 9
if song_number == 968: if song_number == 968:
return 8 return 8
if song_number == 972: if song_number == 972:
return 7 return 7
if song_number == 974: if song_number == 974:

View File

@ -247,7 +247,7 @@ class SongImport(QtCore.QObject):
""" """
Extracts alphanumeric words for searchable fields 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): def finish(self):
""" """

View File

@ -56,11 +56,11 @@ def test():
assert o.title == u'Martins Test' assert o.title == u'Martins Test'
assert o.alternate_title == u'' assert o.alternate_title == u''
assert o.song_number == u'1' assert o.song_number == u'1'
assert [u'C1', u'Chorus 1'] in o.verses assert [u'C1', u'Chorus 1'] in o.verses
assert [u'C2', u'Chorus 2'] in o.verses assert [u'C2', u'Chorus 2'] in o.verses
assert not [u'C3', u'Chorus 3'] in o.verses assert not [u'C3', u'Chorus 3'] in o.verses
assert [u'B1', u'Bridge 1\nBridge 1 line 2'] in o.verses assert [u'B1', u'Bridge 1\nBridge 1 line 2'] in o.verses
assert [u'V1', u'v1 Line 1\nV1 Line 2'] in o.verses assert [u'V1', u'v1 Line 1\nV1 Line 2'] in o.verses
assert [u'V2', u'v2 Line 1\nV2 Line 2'] in o.verses assert [u'V2', u'v2 Line 1\nV2 Line 2'] in o.verses
assert [u'V3A', u'V3 Line 1\nV3 Line 2'] in o.verses assert [u'V3A', u'V3 Line 1\nV3 Line 2'] in o.verses
assert [u'RAP1', u'Rap 1 Line 1\nRap 1 Line 2'] in o.verses assert [u'RAP1', u'Rap 1 Line 1\nRap 1 Line 2'] in o.verses
@ -80,11 +80,11 @@ def test():
assert o.title == u'Martins Test' assert o.title == u'Martins Test'
assert o.alternate_title == u'' assert o.alternate_title == u''
assert o.song_number == u'1' assert o.song_number == u'1'
assert [u'B1', u'Bridge 1\nBridge 1 line 2'] in o.verses assert [u'B1', u'Bridge 1\nBridge 1 line 2'] in o.verses
assert [u'C1', u'Chorus 1'] in o.verses assert [u'C1', u'Chorus 1'] in o.verses
assert [u'C2', u'Chorus 2'] in o.verses assert [u'C2', u'Chorus 2'] in o.verses
assert not [u'C3', u'Chorus 3'] in o.verses assert not [u'C3', u'Chorus 3'] in o.verses
assert [u'V1', u'v1 Line 1\nV1 Line 2'] in o.verses assert [u'V1', u'v1 Line 1\nV1 Line 2'] in o.verses
assert [u'V2', u'v2 Line 1\nV2 Line 2'] in o.verses assert [u'V2', u'v2 Line 1\nV2 Line 2'] in o.verses
print o.verse_order_list print o.verse_order_list
assert o.verse_order_list == [u'V1', u'C1', u'V2', u'C2', u'V3', u'B1', u'V1'] assert o.verse_order_list == [u'V1', u'C1', u'V2', u'C2', u'V3', u'B1', u'V1']
@ -99,11 +99,11 @@ def test():
assert o.alternate_title == u'' assert o.alternate_title == u''
assert o.song_number == u'2' assert o.song_number == u'2'
print o.verses print o.verses
assert [u'B1', u'Bridge 1\nBridge 1 line 2'] in o.verses assert [u'B1', u'Bridge 1\nBridge 1 line 2'] in o.verses
assert [u'C1', u'Chorus 1'] in o.verses assert [u'C1', u'Chorus 1'] in o.verses
assert [u'C2', u'Chorus 2'] in o.verses assert [u'C2', u'Chorus 2'] in o.verses
assert not [u'C3', u'Chorus 3'] in o.verses assert not [u'C3', u'Chorus 3'] in o.verses
assert [u'V1', u'v1 Line 1\nV1 Line 2'] in o.verses assert [u'V1', u'v1 Line 1\nV1 Line 2'] in o.verses
assert [u'V2', u'v2 Line 1\nV2 Line 2'] in o.verses assert [u'V2', u'v2 Line 1\nV2 Line 2'] in o.verses
print o.verse_order_list print o.verse_order_list
assert o.verse_order_list == [u'V1', u'V2', u'B1', u'C1', u'C2'] assert o.verse_order_list == [u'V1', u'V2', u'B1', u'C1', u'C2']
@ -120,7 +120,7 @@ def test():
assert o.verse_order_list == [u'V1'] assert o.verse_order_list == [u'V1']
assert o.topics == [u'Worship: Declaration'] assert o.topics == [u'Worship: Declaration']
print o.verses[0] print o.verses[0]
assert [u'V1', u'Line 1\nLine 2'] in o.verses assert [u'V1', u'Line 1\nLine 2'] in o.verses
print "Tests passed" print "Tests passed"

View File

@ -31,7 +31,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import Plugin, StringContent, build_icon, translate from openlp.core.lib import Plugin, StringContent, build_icon, translate
from openlp.core.lib.db import Manager from openlp.core.lib.db import Manager
from openlp.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.db import init_schema, Song
from openlp.plugins.songs.lib.importer import SongFormat from openlp.plugins.songs.lib.importer import SongFormat
@ -150,9 +150,13 @@ class SongsPlugin(Plugin):
song.title = u'' song.title = u''
if song.alternate_title is None: if song.alternate_title is None:
song.alternate_title = u'' song.alternate_title = u''
song.search_title = self.whitespace.sub(u' ', \ song.search_title = self.whitespace.sub(u' ', song.title.lower() + \
song.title.lower()) + u' ' + \ u' ' + song.alternate_title.lower())
self.whitespace.sub(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) progressDialog.setValue(counter)
self.manager.save_objects(songs) self.manager.save_objects(songs)
counter += 1 counter += 1

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

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

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

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

File diff suppressed because it is too large Load Diff