Some major work on the Bibles plugin:

- Reworked import system to make it pluggable.
 - Created a Bible Import Wizard.
 - Converted Crosswalk to use BeautifulSoup.
 - Merged HTTP and DB Bible list.
 - Made all Bibles descend from BibleDB.
 - Lots of other changes and fixes.

bzr-revno: 700
This commit is contained in:
Raoul Snyman 2010-02-06 16:23:18 +02:00
commit bebe01e80e
23 changed files with 1243 additions and 1271 deletions

View File

@ -148,7 +148,7 @@ def main():
usage = u'Usage: %prog [options] [qt-options]'
parser = OptionParser(usage=usage)
parser.add_option("-l", "--log-level", dest="loglevel",
default="info", metavar="LEVEL",
default="warning", metavar="LEVEL",
help="Set logging to LEVEL level. Valid values are "
"\"debug\", \"info\", \"warning\".")
parser.add_option("-p", "--portable", dest="portable",

View File

@ -32,6 +32,7 @@ class BaseListWithDnD(QtGui.QListWidget):
def __init__(self, parent=None):
QtGui.QListWidget.__init__(self, parent)
self.parent = parent
# this must be set by the class which is inheriting
assert(self.PluginName)
@ -47,4 +48,5 @@ class BaseListWithDnD(QtGui.QListWidget):
mimeData = QtCore.QMimeData()
drag.setMimeData(mimeData)
mimeData.setText(self.PluginName)
dropAction = drag.start(QtCore.Qt.CopyAction)
dropAction = drag.start(QtCore.Qt.CopyAction)

View File

@ -165,3 +165,4 @@ class Receiver():
Get the global ``eventreceiver`` instance.
"""
return Receiver.eventreceiver

View File

@ -253,7 +253,7 @@ class MediaManagerItem(QtGui.QWidget):
def addListViewToToolBar(self):
#Add the List widget
self.ListView = self.ListViewWithDnD_class()
self.ListView = self.ListViewWithDnD_class(self)
self.ListView.uniformItemSizes = True
self.ListView.setGeometry(QtCore.QRect(10, 100, 256, 591))
self.ListView.setSpacing(1)
@ -400,4 +400,4 @@ class MediaManagerItem(QtGui.QWidget):
if self.generateSlideData(service_item):
return service_item
else:
return None
return None

View File

@ -40,12 +40,12 @@ class BiblePlugin(Plugin):
self.weight = -9
self.icon = build_icon(u':/media/media_bible.png')
#Register the bible Manager
self.biblemanager = None
self.manager = None
def initialise(self):
log.info(u'bibles Initialising')
if self.biblemanager is None:
self.biblemanager = BibleManager(self.config)
if self.manager is None:
self.manager = BibleManager(self, self.config)
Plugin.initialise(self)
self.insert_toolbox_item()
self.ImportBibleItem.setVisible(True)
@ -90,4 +90,5 @@ class BiblePlugin(Plugin):
about_text = self.trUtf8('<strong>Bible Plugin</strong><br />This '
'plugin allows bible verses from different sources to be '
'displayed on the screen during the service.')
return about_text
return about_text

View File

@ -91,15 +91,6 @@ class Ui_BibleImportWizard(object):
self.OsisLayout.setMargin(0)
self.OsisLayout.setSpacing(8)
self.OsisLayout.setObjectName(u'OsisLayout')
self.OsisBibleNameLabel = QtGui.QLabel(self.OsisPage)
self.OsisBibleNameLabel.setIndent(0)
self.OsisBibleNameLabel.setObjectName(u'OsisBibleNameLabel')
self.OsisLayout.setWidget(0, QtGui.QFormLayout.LabelRole,
self.OsisBibleNameLabel)
self.OsisBibleNameEdit = QtGui.QLineEdit(self.OsisPage)
self.OsisBibleNameEdit.setObjectName(u'OsisBibleNameEdit')
self.OsisLayout.setWidget(0, QtGui.QFormLayout.FieldRole,
self.OsisBibleNameEdit)
self.OsisLocationLabel = QtGui.QLabel(self.OsisPage)
self.OsisLocationLabel.setObjectName(u'OsisLocationLabel')
self.OsisLayout.setWidget(1, QtGui.QFormLayout.LabelRole,
@ -302,13 +293,11 @@ class Ui_BibleImportWizard(object):
self.ImportProgressLabel.setObjectName(u'ImportProgressLabel')
self.ImportLayout.addWidget(self.ImportProgressLabel)
self.ImportProgressBar = QtGui.QProgressBar(self.ImportPage)
self.ImportProgressBar.setProperty(u'value', 0)
self.ImportProgressBar.setInvertedAppearance(False)
self.ImportProgressBar.setValue(0)
self.ImportProgressBar.setObjectName(u'ImportProgressBar')
self.ImportLayout.addWidget(self.ImportProgressBar)
BibleImportWizard.addPage(self.ImportPage)
self.retranslateUi(BibleImportWizard)
self.FormatWidget.setCurrentIndex(0)
self.WebDownloadTabWidget.setCurrentIndex(0)
@ -334,7 +323,6 @@ class Ui_BibleImportWizard(object):
self.FormatComboBox.setItemText(1, self.trUtf8('CSV'))
self.FormatComboBox.setItemText(2, self.trUtf8('OpenSong'))
self.FormatComboBox.setItemText(3, self.trUtf8('Web Download'))
self.OsisBibleNameLabel.setText(self.trUtf8('Bible Name:'))
self.OsisLocationLabel.setText(self.trUtf8('File Location:'))
self.BooksLocationLabel.setText(self.trUtf8('Books Location:'))
self.VerseLocationLabel.setText(self.trUtf8('Verse Location:'))
@ -362,4 +350,4 @@ class Ui_BibleImportWizard(object):
self.ImportPage.setSubTitle(
self.trUtf8('Please wait while your Bible is imported.'))
self.ImportProgressLabel.setText(self.trUtf8('Ready.'))
#self.ImportProgressBar.setFormat(u'%p')
self.ImportProgressBar.setFormat(u'%p%')

View File

@ -27,6 +27,7 @@ import logging
import os
import os.path
from time import sleep
import csv
from PyQt4 import QtCore, QtGui
@ -59,7 +60,7 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
log = logging.getLogger(u'BibleImportForm')
log.info(u'BibleImportForm loaded')
def __init__(self, parent, config, biblemanager, bibleplugin):
def __init__(self, parent, config, manager, bibleplugin):
'''
Constructor
'''
@ -68,10 +69,10 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
self.registerFields()
self.finishButton = self.button(QtGui.QWizard.FinishButton)
self.cancelButton = self.button(QtGui.QWizard.CancelButton)
self.biblemanager = biblemanager
self.manager = manager
self.config = config
self.bibleplugin = bibleplugin
self.biblemanager.set_process_dialog(self)
self.manager.set_process_dialog(self)
self.web_bible_list = {}
self.loadWebBibles()
QtCore.QObject.connect(self.LocationComboBox,
@ -96,9 +97,9 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
QtCore.SIGNAL(u'currentIdChanged(int)'),
self.onCurrentIdChanged)
def show(self):
def exec_(self):
self.setDefaults()
return QtGui.QWizard.show()
return QtGui.QWizard.exec_(self)
def validateCurrentPage(self):
if self.currentId() == 0:
@ -107,14 +108,6 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
elif self.currentId() == 1:
# Select page
if self.field(u'source_format').toInt()[0] == BibleFormat.OSIS:
if self.field(u'osis_biblename').toString() == u'':
QtGui.QMessageBox.critical(self,
self.trUtf8('Invalid Bible Name'),
self.trUtf8('You need to specify a name for your '
'Bible!'),
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok))
self.OsisBibleNameEdit.setFocus()
return False
if self.field(u'osis_location').toString() == u'':
QtGui.QMessageBox.critical(self,
self.trUtf8('Invalid Bible Location'),
@ -169,6 +162,15 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok))
self.CopyrightEdit.setFocus()
return False
elif self.manager.exists(
self.field(u'license_version').toString()):
QtGui.QMessageBox.critical(self,
self.trUtf8('Bible Exists'),
self.trUtf8('This Bible already exists! Please import '
'a different Bible or first delete the existing one.'),
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok))
self.VersionNameEdit.setFocus()
return False
return True
if self.currentId() == 3:
# Progress page
@ -209,8 +211,6 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
def registerFields(self):
self.SelectPage.registerField(
u'source_format', self.FormatComboBox)
self.SelectPage.registerField(
u'osis_biblename', self.OsisBibleNameEdit)
self.SelectPage.registerField(
u'osis_location', self.OSISLocationEdit)
self.SelectPage.registerField(
@ -238,23 +238,22 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
def setDefaults(self):
self.setField(u'source_format', 0)
self.setField(u'osis_biblename', u'')
self.setField(u'osis_location', u'')
self.setField(u'csv_booksfile', u'')
self.setField(u'csv_versefile', u'')
self.setField(u'opensong_file', u'')
self.setField(u'web_location', 0)
self.setField(u'osis_location', '')
self.setField(u'csv_booksfile', '')
self.setField(u'csv_versefile', '')
self.setField(u'opensong_file', '')
self.setField(u'web_location', DownloadLocation.Crosswalk)
self.setField(u'web_biblename', self.BibleComboBox)
self.setField(u'proxy_server',
self.config.get_config(u'proxy address', u''))
self.config.get_config(u'proxy address', ''))
self.setField(u'proxy_username',
self.config.get_config(u'proxy username',u''))
self.config.get_config(u'proxy username',''))
self.setField(u'proxy_password',
self.config.get_config(u'proxy password',u''))
self.config.get_config(u'proxy password',''))
self.setField(u'license_version', self.VersionNameEdit)
self.setField(u'license_copyright', self.CopyrightEdit)
self.setField(u'license_permission', self.PermissionEdit)
self.onLocationComboBoxChanged(0)
self.onLocationComboBoxChanged(DownloadLocation.Crosswalk)
def loadWebBibles(self):
"""
@ -267,29 +266,33 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
fbibles = None
try:
self.web_bible_list[DownloadLocation.Crosswalk] = {}
fbibles = open(os.path.join(filepath, u'crosswalkbooks.csv'), 'r')
for line in fbibles:
parts = line.split(u',')
self.web_bible_list[DownloadLocation.Crosswalk][parts[0]] = \
parts[1].rstrip()
books_file = open(os.path.join(filepath, u'crosswalkbooks.csv'), 'r')
dialect = csv.Sniffer().sniff(books_file.read(1024))
books_file.seek(0)
books_reader = csv.reader(books_file, dialect)
for line in books_reader:
self.web_bible_list[DownloadLocation.Crosswalk][line[0]] = \
unicode(line[1], u'utf-8').strip()
except:
log.exception(u'Crosswalk resources missing')
finally:
if fbibles:
fbibles.close()
if books_file:
books_file.close()
#Load and store BibleGateway Bibles
try:
self.web_bible_list[DownloadLocation.BibleGateway] = {}
fbibles = open(os.path.join(filepath, u'biblegateway.csv'), 'r')
for line in fbibles:
parts = line.split(u',')
self.web_bible_list[DownloadLocation.BibleGateway][parts[0]] = \
parts[1].rstrip()
books_file = open(os.path.join(filepath, u'biblegateway.csv'), 'r')
dialect = csv.Sniffer().sniff(books_file.read(1024))
books_file.seek(0)
books_reader = csv.reader(books_file, dialect)
for line in books_reader:
self.web_bible_list[DownloadLocation.BibleGateway][line[0]] = \
unicode(line[1], u'utf-8').strip()
except:
log.exception(u'Biblegateway resources missing')
finally:
if fbibles:
fbibles.close()
if books_file:
books_file.close()
def getFileName(self, title, editbox):
filename = QtGui.QFileDialog.getOpenFileName(self, title,
@ -317,22 +320,22 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
success = False
if bible_type == BibleFormat.OSIS:
# Import an OSIS bible
success = self.biblemanager.register_osis_file_bible(
unicode(self.field(u'license_version').toString()),
unicode(self.field(u'osis_location').toString())
success = self.manager.import_bible(BibleFormat.OSIS,
name=unicode(self.field(u'license_version').toString()),
filename=unicode(self.field(u'osis_location').toString())
)
elif bible_type == BibleFormat.CSV:
# Import a CSV bible
success = self.biblemanager.register_csv_file_bible(
unicode(self.field(u'license_version').toString()),
self.field(u'csv_booksfile').toString(),
self.field(u'csv_versefile').toString()
success = self.manager.import_bible(BibleFormat.CSV,
name=unicode(self.field(u'license_version').toString()),
booksfile=self.field(u'csv_booksfile').toString(),
versefile=self.field(u'csv_versefile').toString()
)
elif bible_type == BibleFormat.OpenSong:
# Import an OpenSong bible
success = self.biblemanager.register_opensong_bible(
unicode(self.field(u'license_version').toString()),
self.field(u'opensong_file').toString()
success = self.manager.import_bible(BibleFormat.OpenSong,
name=unicode(self.field(u'license_version').toString()),
filename=self.field(u'opensong_file').toString()
)
elif bible_type == BibleFormat.WebDownload:
# Import a bible from the web
@ -344,21 +347,22 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
elif download_location == DownloadLocation.BibleGateway:
bible = self.web_bible_list[DownloadLocation.BibleGateway][
unicode(self.BibleComboBox.currentText())]
success = self.biblemanager.register_http_bible(
unicode(self.field(u'license_version').toString()),
unicode(DownloadLocation.get_name(download_location)),
unicode(bible),
unicode(self.field(u'proxy_server').toString()),
unicode(self.field(u'proxy_username').toString()),
unicode(self.field(u'proxy_password').toString())
success = self.manager.import_bible(BibleFormat.WebDownload,
name=unicode(self.field(u'license_version').toString()),
download_source=unicode(DownloadLocation.get_name(download_location)),
download_name=unicode(bible),
proxy_server=unicode(self.field(u'proxy_server').toString()),
proxy_username=unicode(self.field(u'proxy_username').toString()),
proxy_password=unicode(self.field(u'proxy_password').toString())
)
if success:
self.biblemanager.save_meta_data(
self.manager.save_meta_data(
unicode(self.field(u'license_version').toString()),
unicode(self.field(u'license_version').toString()),
unicode(self.field(u'license_copyright').toString()),
unicode(self.field(u'license_permission').toString())
)
self.manager.reload_bibles()
self.ImportProgressLabel.setText(self.trUtf8('Finished import.'))
else:
self.ImportProgressLabel.setText(
@ -368,4 +372,4 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
self.ImportProgressBar.setValue(self.ImportProgressBar.maximum())
self.finishButton.setVisible(True)
self.cancelButton.setVisible(False)
Receiver.send_message(u'process_events')
Receiver.send_message(u'process_events')

View File

@ -1,190 +0,0 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2010 Raoul Snyman #
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
# Carsten Tinggaard #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
import os
import logging
from common import BibleCommon
from openlp.plugins.bibles.lib.models import *
class BibleDBImpl(BibleCommon):
global log
log = logging.getLogger(u'BibleDBImpl')
log.info(u'BibleDBimpl loaded')
def __init__(self, biblepath, biblename, config):
# Connect to database
self.config = config
self.biblefile = os.path.join(biblepath, biblename + u'.sqlite')
log.debug(u'Load bible %s on path %s', biblename, self.biblefile)
db_type = self.config.get_config(u'db type', u'sqlite')
db_url = u''
if db_type == u'sqlite':
db_url = u'sqlite:///' + self.biblefile
else:
db_url = u'%s://%s:%s@%s/%s' % \
(db_type, self.config.get_config(u'db username'),
self.config.get_config(u'db password'),
self.config.get_config(u'db hostname'),
self.config.get_config(u'db database'))
self.metadata, self.session = init_models(db_url)
self.metadata.create_all(checkfirst=True)
def create_tables(self):
log.debug(u'createTables')
self.save_meta(u'dbversion', u'2')
self._load_testament(u'Old Testament')
self._load_testament(u'New Testament')
self._load_testament(u'Apocrypha')
def add_verse(self, bookid, chap, vse, text):
verse = Verse()
verse.book_id = bookid
verse.chapter = chap
verse.verse = vse
verse.text = text
self.session.add(verse)
return verse
def save_verses(self):
log.debug('Saving verses...')
self.session.commit()
def create_chapter(self, bookid, chap, textlist):
log.debug(u'create_chapter %s,%s', bookid, chap)
#text list has book and chapter as first to elements of the array
for verse_number, verse_text in textlist.iteritems():
verse = Verse()
verse.book_id = bookid
verse.chapter = chap
verse.verse = verse_number
verse.text = verse_text
self.session.add(verse)
self.session.commit()
def create_book(self, bookname, bookabbrev, testament=1):
log.debug(u'create_book %s,%s', bookname, bookabbrev)
book = Book()
book.testament_id = testament
book.name = bookname
book.abbreviation = bookabbrev
self.session.add(book)
self.session.commit()
return book
def save_meta(self, key, value):
log.debug(u'save_meta %s/%s', key, value)
bmeta = BibleMeta()
bmeta.key = key
bmeta.value = value
self.session.add(bmeta)
self.session.commit()
def get_meta(self, metakey):
log.debug(u'get meta %s', metakey)
return self.session.query(BibleMeta).filter_by(key=metakey).first()
def delete_meta(self, metakey):
biblemeta = self.get_meta(metakey)
try:
self.session.delete(biblemeta)
self.session.commit()
return True
except:
return False
def _load_testament(self, testament):
log.debug(u'load_testaments %s', testament)
test = ONTestament()
test.name = testament
self.session.add(test)
self.session.commit()
def get_bible_books(self):
log.debug(u'get_bible_books')
return self.session.query(Book).order_by(Book.id).all()
def get_max_bible_book_verses(self, bookname, chapter):
log.debug(u'get_max_bible_book_verses %s, %s', bookname, chapter)
verse = self.session.query(Verse).join(Book).filter(
Book.name == bookname).filter(
Verse.chapter == chapter).order_by(Verse.verse.desc()).first()
if verse == None:
return 0
else:
return verse.verse
def get_max_bible_book_chapter(self, bookname):
log.debug(u'get_max_bible_book_chapter %s', bookname)
verse = self.session.query(Verse).join(Book).filter(
Book.name == bookname).order_by(Verse.chapter.desc()).first()
if verse == None:
return 0
else:
return verse.chapter
def get_bible_book(self, bookname):
log.debug(u'get_bible_book %s', bookname)
book = self.session.query(Book).filter(
Book.name.like(bookname + u'%')).first()
if book is None:
book = self.session.query(Book).filter(
Book.abbreviation.like(bookname + u'%')).first()
return book
def get_bible_chapter(self, id, chapter):
log.debug(u'get_bible_chapter %s, %s', id, chapter)
return self.session.query(Verse).filter_by(chapter=chapter).filter_by(
book_id=id).first()
def get_bible_text(self, bookname, chapter, sverse, everse):
log.debug(u'get_bible_text %s, %s, %s, %s', bookname, chapter, sverse,
everse)
#Look up book name or abbreviation
book = self.get_bible_book(bookname)
if book:
bookname = book.name
log.debug(u'bookname corrected to %s' % bookname)
verses = self.session.query(Verse).join(Book).filter(
Book.name == bookname).filter(Verse.chapter == chapter).filter(
Verse.verse>=sverse).filter(Verse.verse<=everse).order_by(
Verse.verse).all()
return verses
def get_verses_from_text(self, versetext):
log.debug(u'get_verses_from_text %s',versetext)
versetext = u'%%%s%%' % versetext
verses = self.session.query(Verse).filter(
Verse.text.like(versetext)).all()
return verses
def dump_bible(self):
log.debug( u'.........Dumping Bible Database')
log.debug( '...............................Books ')
books = self.session.query(Book).all()
log.debug(books)
log.debug( u'...............................Verses ')
verses = self.session.query(Verse).all()
log.debug(verses)

View File

@ -1,228 +0,0 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2010 Raoul Snyman #
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
# Carsten Tinggaard #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
import logging
from common import BibleCommon, SearchResults
class BGExtract(BibleCommon):
global log
log = logging.getLogger(u'BibleHTTPMgr(BG_extract)')
log.info(u'BG_extract loaded')
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 the BibleGateway website
``Version``
The version of the bible like 31 for New International version
``bookname``
Name of the Book
``chapter``
Chapter number
"""
log.debug(u'get_bible_chapter %s,%s,%s',
version, bookname, chapter)
urlstring = \
u'http://www.biblegateway.com/passage/?search=%s+%d&version=%s' % \
(bookname, chapter, version)
log.debug(u'BibleGateway urm = %s' % urlstring)
xml_string = self._get_web_text(urlstring, self.proxyurl)
verseSearch = u'<sup class=\"versenum'
verseFootnote = u'<sup class=\'footnote'
verse = 1
i = xml_string.find(u'result-text-style-normal') + 26
xml_string = xml_string[i:len(xml_string)]
versePos = xml_string.find(verseSearch)
bible = {}
while versePos > -1:
# clear out string
verseText = u''
versePos = xml_string.find(u'</sup>', versePos) + 6
i = xml_string.find(verseSearch, versePos + 1)
# Not sure if this is needed now
if i == -1:
i = xml_string.find(u'</div', versePos + 1)
j = xml_string.find(u'<strong', versePos + 1)
if j > 0 and j < i:
i = j
verseText = xml_string[versePos + 7 : i ]
# store the verse
bible[verse] = self._clean_text(verseText)
versePos = -1
else:
verseText = xml_string[versePos: i]
start_tag = verseText.find(verseFootnote)
while start_tag > -1:
end_tag = verseText.find(u'</sup>')
verseText = verseText[:start_tag] + verseText[end_tag + 6:len(verseText)]
start_tag = verseText.find(verseFootnote)
# Chop off verse and start again
xml_string = xml_string[i:]
#look for the next verse
versePos = xml_string.find(verseSearch)
# store the verse
bible[verse] = self._clean_text(verseText)
verse += 1
return SearchResults(bookname, chapter, bible)
class CWExtract(BibleCommon):
global log
log = logging.getLogger(u'BibleHTTPMgr(CWExtract)')
log.info(u'CWExtract loaded')
def __init__(self, proxyurl=None):
log.debug(u'init %s', proxyurl)
self.proxyurl = proxyurl
def get_bible_chapter(self, version, bookname, chapter) :
log.debug(u'getBibleChapter %s,%s,%s',
version,bookname, chapter)
"""
Access and decode bibles via the Crosswalk website
``version``
The version of the bible like niv for New International Version
``bookname``
Text name of in english e.g. 'gen' for Genesis
``chapter``
Chapter number
"""
log.debug(u'get_bible_chapter %s,%s,%s',
version, bookname, chapter)
bookname = bookname.replace(u' ', u'')
urlstring = u'http://bible.crosswalk.com/OnlineStudyBible/bible.cgi?word=%s+%d&version=%s'\
% (bookname, chapter, version)
xml_string = self._get_web_text(urlstring, self.proxyurl)
## Strip Book Title from Heading to return it to system
##
i = xml_string.find(u'<title>')
j = xml_string.find(u'-', i)
book_title = xml_string[i + 7:j]
book_title = book_title.rstrip()
log.debug(u'Book Title %s', book_title)
i = book_title.rfind(u' ')
book_chapter = book_title[i+1:len(book_title)].rstrip()
book_title = book_title[:i].rstrip()
log.debug(u'Book Title %s', book_title)
log.debug(u'Book Chapter %s', book_chapter)
# Strip Verse Data from Page and build an array
i = xml_string.find(u'NavCurrentChapter')
xml_string = xml_string[i:len(xml_string)]
i = xml_string.find(u'<TABLE')
xml_string = xml_string[i:len(xml_string)]
i = xml_string.find(u'<B>')
#remove the <B> at the front
xml_string = xml_string[i + 3 :len(xml_string)]
# Remove the heading for the book
i = xml_string.find(u'<B>')
#remove the <B> at the front
xml_string = xml_string[i + 3 :len(xml_string)]
versePos = xml_string.find(u'<BLOCKQUOTE>')
bible = {}
while versePos > 0:
verseText = u''
versePos = xml_string.find(u'<B><I>', versePos) + 6
i = xml_string.find(u'</I></B>', versePos)
# Got the Chapter
verse = xml_string[versePos:i]
# move the starting position to begining of the text
versePos = i + 8
# find the start of the next verse
i = xml_string.find(u'<B><I>', versePos)
if i == -1:
i = xml_string.find(u'</BLOCKQUOTE>',versePos)
verseText = xml_string[versePos: i]
versePos = 0
else:
verseText = xml_string[versePos: i]
versePos = i
bible[verse] = self._clean_text(verseText)
return SearchResults(book_title, book_chapter, bible)
class BibleHTTPImpl():
global log
log = logging.getLogger(u'BibleHTTPMgr')
log.info(u'BibleHTTP manager loaded')
def __init__(self):
"""
Finds all the bibles defined for the system
Creates an Interface Object for each bible containing connection
information
Throws Exception if no Bibles are found.
Init confirms the bible exists and stores the database path.
"""
self.biblesource = u''
self.proxyurl = None
self.bibleid = None
def set_proxy(self, proxyurl):
"""
Set the Proxy Url
"""
log.debug(u'set_proxy %s', proxyurl)
self.proxyurl = proxyurl
def set_bibleid(self, bibleid):
"""
Set the bible id.
The shore identifier of the the bible.
"""
log.debug(u'set_bibleid %s', bibleid)
self.bibleid = bibleid
def set_bible_source(self, biblesource):
"""
Set the source of where the bible text is coming from
"""
log.debug(u'set_bible_source %s', biblesource)
self.biblesource = biblesource
def get_bible_chapter(self, version, bookname, chapter):
"""
Receive the request and call the relevant handler methods
"""
log.debug(u'get_bible_chapter %s,%s,%s',
version, bookname, chapter)
log.debug(u'biblesource = %s', self.biblesource)
try:
if self.biblesource.lower() == u'crosswalk':
ev = CWExtract(self.proxyurl)
else:
ev = BGExtract(self.proxyurl)
return ev.get_bible_chapter(self.bibleid, bookname, chapter)
except:
log.exception("Failed to get bible chapter")

View File

@ -26,8 +26,98 @@
import urllib2
import chardet
import logging
import re
import sqlite3
class SearchResults:
only_verses = re.compile(r'([\w .]+)[ ]+([0-9]+)[ ]*[:|v|V][ ]*([0-9]+)'
r'(?:[ ]*-[ ]*([0-9]+|end))?(?:[ ]*,[ ]*([0-9]+)(?:[ ]*-[ ]*([0-9]+|end))?)?',
re.UNICODE)
chapter_range = re.compile(r'([\w .]+)[ ]+([0-9]+)[ ]*[:|v|V][ ]*'
r'([0-9]+)[ ]*-[ ]*([0-9]+)[ ]*[:|v|V][ ]*([0-9]+)',
re.UNICODE)
log = logging.getLogger(__name__)
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.
The reference list is a list of tuples, with each tuple structured like
this::
(book, chapter, start_verse, end_verse)
"""
reference = reference.strip()
log.debug('parse_reference("%s")', reference)
reference_list = []
# We start with the most "complicated" match first, so that they are found
# first, and we don't have any "false positives".
match = chapter_range.match(reference)
if match:
log.debug('Found a chapter range.')
book = match.group(1)
from_verse = match.group(3)
to_verse = match.group(5)
if int(match.group(2)) == int(match.group(4)):
reference_list.append(
(match.group(1), int(match.group(2)), from_verse, to_verse)
)
else:
if int(match.group(2)) > int(match.group(4)):
from_chapter = int(match.group(4))
to_chapter = int(match.group(2))
else:
from_chapter = int(match.group(2))
to_chapter = int(match.group(4))
for chapter in xrange(from_chapter, to_chapter + 1):
if chapter == from_chapter:
reference_list.append(
(match.group(1), chapter, from_verse, -1)
)
elif chapter == to_chapter:
reference_list.append(
(match.group(1), chapter, 1, to_verse)
)
else:
reference_list.append(
(match.group(1), chapter, 1, -1)
)
else:
match = only_verses.match(reference)
if match:
log.debug('Found a verse range.')
book = match.group(1)
chapter = match.group(2)
verse = match.group(3)
if match.group(4) is None:
reference_list.append((book, chapter, verse, verse))
elif match.group(5) is None:
end_verse = match.group(4)
if end_verse == u'end':
end_verse = -1
reference_list.append((book, chapter, verse, end_verse))
elif match.group(6) is None:
reference_list.extend([
(book, chapter, verse, match.group(4)),
(book, chapter, match.group(5), match.group(5))
])
else:
end_verse = match.group(6)
if end_verse == u'end':
end_verse = -1
reference_list.extend([
(book, chapter, verse, match.group(4)),
(book, chapter, match.group(5), end_verse)
])
else:
log.debug('Didn\'t find anything.')
log.debug(reference_list)
return reference_list
class SearchResults(object):
"""
Encapsulate a set of search results. This is Bible-type independant.
"""
@ -81,12 +171,6 @@ class BibleCommon(object):
log = logging.getLogger(u'BibleCommon')
log.info(u'BibleCommon')
def __init__(self):
"""
An empty constructor... not sure why I'm here.
"""
pass
def _get_web_text(self, urlstring, proxyurl):
"""
Get the HTML from the web page.
@ -165,4 +249,4 @@ class BibleCommon(object):
text = text[:start_tag] + text[end_tag + 1:]
start_tag = text.find(u'<')
text = text.replace(u'>', u'')
return text.rstrip().lstrip()
return text.rstrip().lstrip()

View File

@ -25,96 +25,97 @@
import logging
import chardet
import csv
from openlp.plugins.bibles.lib.common import BibleCommon
from openlp.core.lib import Receiver
from db import BibleDB
class BibleCSVImpl(BibleCommon):
global log
log = logging.getLogger(u'BibleCSVImpl')
log.info(u'BibleCVSImpl loaded')
def __init__(self, bibledb):
log = logging.getLogger(__name__)
class CSVBible(BibleDB):
"""
This class provides a specialisation for importing of CSV Bibles.
"""
def __init__(self, parent, **kwargs):
"""
Loads a Bible from a pair of CVS files passed in
This class assumes the files contain all the information and
a clean bible is being loaded.
"""
self.bibledb = bibledb
self.loadbible = True
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'openlpstopimport'), self.stop_import)
BibleDB.__init__(self, parent, **kwargs)
log.info(self.__class__.__name__)
if u'booksfile' not in kwargs:
raise KeyError(u'You have to supply a file to import books from.')
self.booksfile = kwargs[u'booksfile']
if u'versesfile' not in kwargs:
raise KeyError(u'You have to supply a file to import verses from.')
self.versesfile = kwargs[u'versesfile']
#QtCore.QObject.connect(Receiver.get_receiver(),
# QtCore.SIGNAL(u'openlpstopimport'), self.stop_import)
def stop_import(self):
self.loadbible = False
"""
Stops the import of the Bible.
"""
log.debug('Stopping import!')
self.stop_import = True
def load_data(self, booksfile, versesfile, dialogobject):
def do_import(self):
#Populate the Tables
success = True
fbooks = None
books_file = None
try:
fbooks = open(booksfile, 'r')
count = 0
for line in fbooks:
books_file = open(self.booksfile, 'r')
dialect = csv.Sniffer().sniff(books_file.read(1024))
books_file.seek(0)
books_reader = csv.reader(books_file, dialect)
for line in books_reader:
# cancel pressed
if not self.loadbible:
if self.stop_import:
break
details = chardet.detect(line)
line = unicode(line, details['encoding'])
p = line.split(u',')
p1 = p[1].replace(u'"', u'')
p2 = p[2].replace(u'"', u'')
p3 = p[3].replace(u'"', u'')
self.bibledb.create_book(p2, p3, int(p1))
count += 1
#Flush the screen events
if count % 3 == 0:
Receiver.send_message(u'process_events')
count = 0
details = chardet.detect(line[1])
self.create_book(unicode(line[1], details['encoding']),
line[2], int(line[0]))
Receiver.send_message(u'process_events')
except:
log.exception(u'Loading books from file failed')
success = False
finally:
if fbooks:
fbooks.close()
if books_file:
books_file.close()
if not success:
return False
fverse = None
verse_file = None
try:
fverse = open(versesfile, 'r')
count = 0
book_ptr = None
for line in fverse:
if not self.loadbible: # cancel pressed
verse_file = open(versesfile, 'r')
dialect = csv.Sniffer().sniff(verse_file.read(1024))
verse_file.seek(0)
verse_reader = csv.reader(verse_file, dialect)
for line in verse_reader:
if self.stop_import: # cancel pressed
break
details = chardet.detect(line)
line = unicode(line, details['encoding'])
# split into 3 units and leave the rest as a single field
p = line.split(u',', 3)
p0 = p[0].replace(u'"', u'')
p3 = p[3].replace(u'"', u'')
if book_ptr is not p0:
book = self.bibledb.get_bible_book(p0)
details = chardet.detect(line[3])
if book_ptr != line[0]:
book = self.get_book(line[0])
book_ptr = book.name
# increament the progress bar
dialogobject.incrementProgressBar(u'Importing %s %s' % \
book.name)
self.bibledb.add_verse(book.id, p[1], p[2], p3)
count += 1
#Every x verses repaint the screen
if count % 3 == 0:
Receiver.send_message(u'process_events')
count = 0
self.bibledb.save_verses()
self.wizard.incrementProgressBar(
u'Importing %s %s' % (book.name, line[1]))
self.commit()
self.create_verse(book.id, line[1], line[2],
unicode(line[3], details['encoding']))
Receiver.send_message(u'process_events')
self.commit()
except:
log.exception(u'Loading verses from file failed')
success = False
finally:
if fverse:
fverse.close()
if not self.loadbible:
dialogobject.incrementProgressBar(u'Import canceled!')
dialogobject.ImportProgressBar.setValue(
dialogobject.ImportProgressBar.maximum())
if verse_file:
verse_file.close()
if self.stop_import:
self.wizard.incrementProgressBar(u'Import canceled!')
return False
else:
return success
return success

View File

@ -0,0 +1,286 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2010 Raoul Snyman #
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
# Carsten Tinggaard #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
import os
import logging
import chardet
from sqlalchemy import or_
from PyQt4 import QtCore
from openlp.plugins.bibles.lib.models import *
log = logging.getLogger(__name__)
class BibleDB(QtCore.QObject):
"""
This class represents a database-bound Bible. It is used as a base class
for all the custom importers, so that the can implement their own import
methods, but benefit from the database methods in here via inheritance,
rather than depending on yet another object.
"""
def __init__(self, parent, **kwargs):
"""
The constructor loads up the database and creates and initialises the
tables if the database doesn't exist.
**Required keyword arguments:**
``path``
The path to the bible database file.
``name``
The name of the database. This is also used as the file name for
SQLite databases.
``config``
The configuration object, passed in from the plugin.
"""
log.info(u'BibleDBimpl loaded')
QtCore.QObject.__init__(self)
if u'path' not in kwargs:
raise KeyError(u'Missing keyword argument "path".')
if u'name' not in kwargs:
raise KeyError(u'Missing keyword argument "name".')
if u'config' not in kwargs:
raise KeyError(u'Missing keyword argument "config".')
self.stop_import = False
self.name = kwargs[u'name']
self.config = kwargs[u'config']
self.db_file = os.path.join(kwargs[u'path'],
u'%s.sqlite' % kwargs[u'name'])
log.debug(u'Load bible %s on path %s', kwargs[u'name'], self.db_file)
db_type = self.config.get_config(u'db type', u'sqlite')
db_url = u''
if db_type == u'sqlite':
db_url = u'sqlite:///' + self.db_file
else:
db_url = u'%s://%s:%s@%s/%s' % \
(db_type, self.config.get_config(u'db username'),
self.config.get_config(u'db password'),
self.config.get_config(u'db hostname'),
self.config.get_config(u'db database'))
self.metadata, self.session = init_models(db_url)
self.metadata.create_all(checkfirst=True)
def register(self, wizard):
"""
This method basically just initialialises the database. It is called
from the Bible Manager when a Bible is imported. Descendant classes
may want to override this method to supply their own custom
initialisation as well.
"""
self.wizard = wizard
self.create_tables()
return self.name
def commit(self):
log.debug('Committing...')
self.session.commit()
def create_tables(self):
log.debug(u'createTables')
self.create_meta(u'dbversion', u'2')
self.create_testament(u'Old Testament')
self.create_testament(u'New Testament')
self.create_testament(u'Apocrypha')
def create_testament(self, testament):
log.debug(u'BibleDB.create_testament("%s")', testament)
self.session.add(Testament.populate(name=testament))
self.commit()
def create_book(self, name, abbrev, testament=1):
log.debug(u'create_book %s,%s', name, abbrev)
book = Book.populate(name=name, abbreviation=abbrev,
testament_id=testament)
self.session.add(book)
self.commit()
return book
def create_chapter(self, book_id, chapter, textlist):
log.debug(u'create_chapter %s,%s', book_id, chapter)
#text list has book and chapter as first two elements of the array
for verse_number, verse_text in textlist.iteritems():
verse = Verse.populate(
book_id = book_id,
chapter = chapter,
verse = verse_number,
text = verse_text
)
self.session.add(verse)
self.commit()
def create_verse(self, book_id, chapter, verse, text):
if not isinstance(text, unicode):
details = chardet.detect(text)
text = unicode(text, details[u'encoding'])
verse = Verse.populate(
book_id=book_id,
chapter=chapter,
verse=verse,
text=text
)
self.session.add(verse)
return verse
def create_meta(self, key, value):
log.debug(u'save_meta %s/%s', key, value)
self.session.add(BibleMeta.populate(key=key, value=value))
self.commit()
def get_books(self):
log.debug(u'BibleDB.get_books()')
return self.session.query(Book).order_by(Book.id).all()
def get_book(self, book):
log.debug(u'BibleDb.get_book("%s")', book)
db_book = self.session.query(Book)\
.filter(Book.name.like(book + u'%'))\
.first()
if db_book is None:
db_book = self.session.query(Book)\
.filter(Book.abbreviation.like(book + u'%'))\
.first()
return db_book
def get_chapter(self, id, chapter):
log.debug(u'BibleDB.get_chapter("%s", %s)', id, chapter)
return self.session.query(Verse)\
.filter_by(chapter=chapter)\
.filter_by(book_id=id)\
.first()
def get_verses(self, reference_list):
"""
This is probably the most used function. It retrieves the list of
verses based on the user's query.
``reference_list``
This is the list of references the media manager item wants. It is
a list of tuples, with the following format::
(book, chapter, start_verse, end_verse)
Therefore, when you are looking for multiple items, simply break
them up into references like this, bundle them into a list. This
function then runs through the list, and returns an amalgamated
list of ``Verse`` objects. For example::
[(u'Genesis', 1, 1, 1), (u'Genesis', 2, 2, 3)]
"""
log.debug(u'BibleDB.get_verses: %s', reference_list)
verse_list = []
for book, chapter, start_verse, end_verse in reference_list:
db_book = self.get_book(book)
if end_verse == -1:
end_verse = self.get_verse_count(book, chapter)
if db_book:
book = db_book.name
log.debug(u'Book name corrected to "%s"', book)
verses = self.session.query(Verse)\
.filter_by(book_id=db_book.id)\
.filter_by(chapter=chapter)\
.filter(Verse.verse >= start_verse)\
.filter(Verse.verse <= end_verse)\
.order_by(Verse.verse)\
.all()
verse_list.extend(verses)
return verse_list
def verse_search(self, text):
"""
Search for verses containing text ``text``.
``text``
The text to search for. If the text contains commas, it will be
split apart and OR'd on the list of values. If the text just
contains spaces, it will split apart and AND'd on the list of
values.
"""
log.debug(u'BibleDB.verse_search("%s")', text)
verses = self.session.query(Verse)
if text.find(u',') > -1:
or_clause = []
keywords = [u'%%%s%%' % keyword.strip() for keyword in text.split(u',')]
for keyword in keywords:
or_clause.append(Verse.text.like(keyword))
verses = verses.filter(or_(*or_clause))
else:
keywords = [u'%%%s%%' % keyword.strip() for keyword in text.split(u' ')]
for keyword in keywords:
verses = verses.filter(Verse.text.like(keyword))
verses = verses.all()
return verses
def get_chapter_count(self, book):
log.debug(u'BibleDB.get_chapter_count("%s")', book)
count = self.session.query(Verse.chapter).join(Book)\
.filter(Book.name==book)\
.distinct().count()
#verse = self.session.query(Verse).join(Book).filter(
# Book.name == bookname).order_by(Verse.chapter.desc()).first()
if not count:
return 0
else:
return count
def get_verse_count(self, book, chapter):
log.debug(u'BibleDB.get_verse_count("%s", %s)', book, chapter)
count = self.session.query(Verse).join(Book)\
.filter(Book.name==book)\
.filter(Verse.chapter==chapter)\
.count()
#verse = self.session.query(Verse).join(Book).filter(
# Book.name == bookname).filter(
# Verse.chapter == chapter).order_by(Verse.verse.desc()).first()
if not count:
return 0
else:
return count
def get_meta(self, key):
log.debug(u'get meta %s', key)
return self.session.query(BibleMeta).get(key)
def delete_meta(self, metakey):
biblemeta = self.get_meta(metakey)
try:
self.session.delete(biblemeta)
self.commit()
return True
except:
return False
def dump_bible(self):
log.debug(u'.........Dumping Bible Database')
log.debug('...............................Books ')
books = self.session.query(Book).all()
log.debug(books)
log.debug(u'...............................Verses ')
verses = self.session.query(Verse).all()
log.debug(verses)

View File

@ -0,0 +1,361 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2010 Raoul Snyman #
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
# Carsten Tinggaard #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
import logging
import urllib2
import os
import sqlite3
from BeautifulSoup import BeautifulSoup
from openlp.core.lib import Receiver
from common import BibleCommon, SearchResults
from db import BibleDB
from openlp.plugins.bibles.lib.models import Book
class HTTPBooks(object):
cursor = None
@staticmethod
def get_cursor():
if HTTPBooks.cursor is None:
filepath = os.path.join(os.path.dirname(os.path.abspath(__file__)),
u'..', u'resources', u'httpbooks.sqlite')
conn = sqlite3.connect(filepath)
HTTPBooks.cursor = conn.cursor()
return HTTPBooks.cursor
@staticmethod
def run_sql(query, parameters=()):
cursor = HTTPBooks.get_cursor()
cursor.execute(query, parameters)
return cursor.fetchall()
@staticmethod
def get_books():
books = HTTPBooks.run_sql(u'SELECT id, testament_id, name, '
u'abbreviation, chapters FROM books ORDER BY id')
book_list = []
for book in books:
book_list.append({
u'id': book[0],
u'testament_id': book[1],
u'name': unicode(book[2]),
u'abbreviation': unicode(book[3]),
u'chapters': book[4]
})
return book_list
@staticmethod
def get_book(name):
if not isinstance(name, unicode):
name = unicode(name)
books = HTTPBooks.run_sql(u'SELECT id, testament_id, name, '
u'abbreviation, chapters FROM books WHERE name = ? OR '
u'abbreviation = ?', (name, name))
if len(books) > 0:
return {
u'id': books[0][0],
u'testament_id': books[0][1],
u'name': unicode(books[0][2]),
u'abbreviation': unicode(books[0][3]),
u'chapters': books[0][4]
}
else:
return None
@staticmethod
def get_chapter(name, chapter):
if not isinstance(name, int):
chapter = int(chapter)
book = HTTPBooks.get_book(name)
chapters = HTTPBooks.run_sql(u'SELECT id, book_id, chapter, '
u'verses FROM chapters WHERE book_id = ?', (book[u'id'],))
if len(chapters) > 0:
return {
u'id': chapters[0][0],
u'book_id': chapters[0][1],
u'chapter': chapters[0][2],
u'verses': chapters[0][3]
}
else:
return None
@staticmethod
def get_chapter_count(book):
details = HTTPBooks.get_book(book)
if details:
return details[u'chapters']
return 0
@staticmethod
def get_verse_count(book, chapter):
details = HTTPBooks.get_chapter(book, chapter)
if details:
return details[u'verses']
return 0
class BGExtract(BibleCommon):
global log
log = logging.getLogger(u'BibleHTTPMgr(BG_extract)')
log.info(u'BG_extract loaded')
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 the BibleGateway website
``Version``
The version of the bible like 31 for New International version
``bookname``
Name of the Book
``chapter``
Chapter number
"""
log.debug(u'get_bible_chapter %s, %s, %s', version, bookname, chapter)
urlstring = u'http://www.biblegateway.com/passage/?search=%s+%s' \
u'&version=%s' % (bookname, chapter, version)
log.debug(u'BibleGateway url = %s' % urlstring)
xml_string = self._get_web_text(urlstring, self.proxyurl)
verseSearch = u'<sup class=\"versenum'
verseFootnote = u'<sup class=\'footnote'
verse = 1
i = xml_string.find(u'result-text-style-normal') + 26
xml_string = xml_string[i:len(xml_string)]
versePos = xml_string.find(verseSearch)
bible = {}
while versePos > -1:
# clear out string
verseText = u''
versePos = xml_string.find(u'</sup>', versePos) + 6
i = xml_string.find(verseSearch, versePos + 1)
# Not sure if this is needed now
if i == -1:
i = xml_string.find(u'</div', versePos + 1)
j = xml_string.find(u'<strong', versePos + 1)
if j > 0 and j < i:
i = j
verseText = xml_string[versePos + 7 : i ]
# store the verse
bible[verse] = self._clean_text(verseText)
versePos = -1
else:
verseText = xml_string[versePos: i]
start_tag = verseText.find(verseFootnote)
while start_tag > -1:
end_tag = verseText.find(u'</sup>')
verseText = verseText[:start_tag] + verseText[end_tag + 6:len(verseText)]
start_tag = verseText.find(verseFootnote)
# Chop off verse and start again
xml_string = xml_string[i:]
#look for the next verse
versePos = xml_string.find(verseSearch)
# store the verse
bible[verse] = self._clean_text(verseText)
verse += 1
return SearchResults(bookname, chapter, bible)
class CWExtract(BibleCommon):
log.info(u'%s loaded', __name__)
def __init__(self, proxyurl=None):
log.debug(u'init %s', proxyurl)
self.proxyurl = proxyurl
def get_bible_chapter(self, version, bookname, chapter):
log.debug(u'%s %s, %s, %s', __name__, version, bookname, chapter)
"""
Access and decode bibles via the Crosswalk website
``version``
The version of the bible like niv for New International Version
``bookname``
Text name of in english e.g. 'gen' for Genesis
``chapter``
Chapter number
"""
log.debug(u'get_bible_chapter %s,%s,%s',
version, bookname, chapter)
bookname = bookname.replace(u' ', u'')
chapter_url = u'http://www.biblestudytools.com/%s/%s/%s.html' % \
(version, bookname.lower(), chapter)
log.debug(u'URL: %s', chapter_url)
page = urllib2.urlopen(chapter_url)
if not page:
return None
soup = BeautifulSoup(page)
htmlverses = soup.findAll(u'span', u'versetext')
verses = {}
for verse in htmlverses:
Receiver.send_message(u'process_events')
versenumber = int(verse.contents[0].contents[0])
versetext = u''
for part in verse.contents:
if str(part)[0] != u'<':
versetext = versetext + part
versetext = versetext.strip(u'\n\r\t ')
verses[versenumber] = versetext
return SearchResults(bookname, chapter, verses)
class HTTPBible(BibleDB):
log.info(u'%s loaded', __name__)
def __init__(self, parent, **kwargs):
"""
Finds all the bibles defined for the system
Creates an Interface Object for each bible containing connection
information
Throws Exception if no Bibles are found.
Init confirms the bible exists and stores the database path.
"""
BibleDB.__init__(self, parent, **kwargs)
if u'download_source' not in kwargs:
raise KeyError(u'Missing keyword argument "download_source"')
if u'download_name' not in kwargs:
raise KeyError(u'Missing keyword argument "download_name"')
self.download_source = kwargs[u'download_source']
self.download_name = kwargs[u'download_name']
if u'proxy_server' in kwargs:
self.proxy_server = kwargs[u'proxy_server']
else:
self.proxy_server = None
if u'proxy_username' in kwargs:
self.proxy_username = kwargs[u'proxy_username']
else:
self.proxy_username = None
if u'proxy_password' in kwargs:
self.proxy_password = kwargs[u'proxy_password']
else:
self.proxy_password = None
def do_import(self):
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)
if self.proxy_server:
self.create_meta(u'proxy server', self.proxy_server)
if self.proxy_username:
# store the proxy userid
self.create_meta(u'proxy username', self.proxy_username)
if self.proxy_password:
# store the proxy password
self.create_meta(u'proxy password', self.proxy_password)
self.wizard.incrementProgressBar('Registered.')
return True
def get_verses(self, reference_list):
"""
A reimplementation of the ``BibleDB.get_verses`` method, this one is
specifically for web Bibles. It first checks to see if the particular
chapter exists in the DB, and if not it pulls it from the web. If the
chapter DOES exist, it simply pulls the verses from the DB using the
ancestor method.
``reference_list``
This is the list of references the media manager item wants. It is
a list of tuples, with the following format::
(book, chapter, start_verse, end_verse)
Therefore, when you are looking for multiple items, simply break
them up into references like this, bundle them into a list. This
function then runs through the list, and returns an amalgamated
list of ``Verse`` objects. For example::
[(u'Genesis', 1, 1, 1), (u'Genesis', 2, 2, 3)]
"""
for reference in reference_list:
log.debug('Reference: %s', reference)
book = reference[0]
db_book = self.get_book(book)
if not db_book:
book_details = self.lookup_book(book)
if not book_details:
Receiver.send_message(u'bible_nobook')
return []
db_book = self.create_book(book_details[u'name'],
book_details[u'abbreviation'], book_details[u'testament_id'])
book = db_book.name
if BibleDB.get_verse_count(self, book, reference[1]) == 0:
Receiver.send_message(u'bible_showprogress')
Receiver.send_message(u'process_events')
search_results = self.get_chapter(self.name, book, reference[1])
if search_results and search_results.has_verselist():
## We have found a book of the bible lets check to see
## if it was there. By reusing the returned book name
## we get a correct book. For example it is possible
## to request ac and get Acts back.
bookname = search_results.get_book()
# check to see if book/chapter exists
db_book = self.get_book(bookname)
self.create_chapter(db_book.id, search_results.get_chapter(),
search_results.get_verselist())
Receiver.send_message(u'bible_hideprogress')
Receiver.send_message(u'process_events')
return BibleDB.get_verses(self, reference_list)
def get_chapter(self, version, book, chapter):
"""
Receive the request and call the relevant handler methods
"""
log.debug(u'get_chapter %s, %s, %s', version, book, chapter)
log.debug(u'source = %s', self.download_source)
try:
if self.download_source.lower() == u'crosswalk':
ev = CWExtract(self.proxy_server)
else:
ev = BGExtract(self.proxy_server)
return ev.get_bible_chapter(self.download_name, book, chapter)
except:
log.exception("Failed to get bible chapter")
return None
def get_books(self):
return [Book.populate(name=book['name']) for book in HTTPBooks.get_books()]
def lookup_book(self, book):
return HTTPBooks.get_book(book)
def get_chapter_count(self, book):
return HTTPBooks.get_chapter_count(book)
def get_verse_count(self, book, chapter):
return HTTPBooks.get_verse_count(book, chapter)
def set_proxy_server(self, server):
self.proxy_server = server

View File

@ -25,38 +25,62 @@
import logging
import os
import csv
from bibleOpenSongimpl import BibleOpenSongImpl
from bibleOSISimpl import BibleOSISImpl
from bibleCSVimpl import BibleCSVImpl
from bibleDBimpl import BibleDBImpl
from bibleHTTPimpl import BibleHTTPImpl
from common import parse_reference
from opensong import OpenSongBible
from osis import OSISBible
from csvbible import CSVBible
from db import BibleDB
from http import HTTPBible
class BibleMode(object):
"""
This is basically an enumeration class which specifies the mode of a Bible.
Mode refers to whether or not a Bible in OpenLP is a full Bible or needs to
be downloaded from the Internet on an as-needed basis.
"""
Full = 1
Partial = 2
class BibleFormat(object):
"""
This is a special enumeration class that holds the various types of Bibles,
plus a few helper functions to facilitate generic handling of Bible types
for importing.
"""
Unknown = -1
OSIS = 0
CSV = 1
OpenSong = 2
WebDownload = 3
@classmethod
def get_handler(class_, id):
if id == class_.OSIS:
return BibleOSISImpl
elif id == class_.CSV:
return BibleCSVImpl
elif id == class_.OpenSong:
return BibleOpenSongImpl
elif id == class_.WebDownload:
return BibleHTTPImpl
@staticmethod
def get_class(id):
"""
Return the appropriate imeplementation class.
"""
if id == BibleFormat.OSIS:
return OSISBible
elif id == BibleFormat.CSV:
return CSVBible
elif id == BibleFormat.OpenSong:
return OpenSongBible
elif id == BibleFormat.WebDownload:
return HTTPBible
else:
return None
@staticmethod
def list():
return [
BibleFormat.OSIS,
BibleFormat.CSV,
BibleFormat.OpenSong,
BibleFormat.WebDownload
]
class BibleManager(object):
"""
@ -66,300 +90,139 @@ class BibleManager(object):
log = logging.getLogger(u'BibleManager')
log.info(u'Bible manager loaded')
def __init__(self, config):
def __init__(self, parent, config):
"""
Finds all the bibles defined for the system and creates an
interface object for each bible containing connection
information. Throws Exception if no Bibles are found.
Finds all the bibles defined for the system and creates an interface
object for each bible containing connection information. Throws
Exception if no Bibles are found.
Init confirms the bible exists and stores the database path.
``config``
The plugin's configuration object.
"""
self.config = config
log.debug(u'Bible Initialising')
self.config = config
self.parent = parent
self.web = u'Web'
# dict of bible database objects
self.bible_db_cache = None
# dict of bible http readers
self.bible_http_cache = None
self.biblePath = self.config.get_data_path()
#get proxy name for screen
self.proxyname = self.config.get_config(u'proxy name')
self.bibleSuffix = u'sqlite'
self.dialogobject = None
self.db_cache = None
self.path = self.config.get_data_path()
self.proxy_name = self.config.get_config(u'proxy name')
self.suffix = u'sqlite'
self.import_wizard = None
self.reload_bibles()
self.media = None
def reload_bibles(self):
"""
Reloads the Bibles from the available Bible databases on disk. If a web
Bible is encountered, an instance of HTTPBible is loaded instead of the
BibleDB class.
"""
log.debug(u'Reload bibles')
files = self.config.get_files(self.bibleSuffix)
files = self.config.get_files(self.suffix)
log.debug(u'Bible Files %s', files)
self.bible_db_cache = {}
self.bible_http_cache = {}
# books of the bible with testaments
self.book_testaments = {}
# books of the bible with chapter count
self.book_chapters = []
# books of the bible with abbreviation
self.book_abbreviations = {}
self.web_bibles_present = False
for f in files:
nme = f.split(u'.')
bname = nme[0]
self.bible_db_cache[bname] = BibleDBImpl(self.biblePath,
bname, self.config)
self.db_cache = {}
for filename in files:
name, extension = os.path.splitext(filename)
self.db_cache[name] = BibleDB(self.parent, path=self.path, name=name, config=self.config)
# look to see if lazy load bible exists and get create getter.
biblesource = self.bible_db_cache[bname].get_meta(u'WEB')
if biblesource:
self.web_bibles_present = True
nhttp = BibleHTTPImpl()
# tell The Server where to get the verses from.
nhttp.set_bible_source(biblesource.value)
self.bible_http_cache [bname] = nhttp
# look to see if lazy load bible exists and get create getter.
meta = self.bible_db_cache[bname].get_meta(u'proxy')
proxy = None
if meta:
proxy = meta.value
# tell The Server where to get the verses from.
nhttp.set_proxy(proxy)
# look to see if lazy load bible exists and get create getter.
bibleid = self.bible_db_cache[bname].get_meta(u'bibleid').value
# tell The Server where to get the verses from.
nhttp.set_bibleid(bibleid)
else:
# makes the Full / partial code easier.
self.bible_http_cache [bname] = None
if self.web_bibles_present:
# books of the bible linked to bibleid {osis, name}
self.book_testaments = {}
# books of the bible linked to bibleid {osis, abbrev}
self.book_abbreviations = {}
filepath = os.path.split(os.path.abspath(__file__))[0]
filepath = os.path.abspath(os.path.join(
filepath, u'..', u'resources',u'httpbooks.csv'))
fbibles = None
try:
fbibles = open(filepath, u'r')
for line in fbibles:
p = line.split(u',')
self.book_abbreviations[p[0]] = p[1].replace(u'\n', '')
self.book_testaments[p[0]] = p[2].replace(u'\n', '')
self.book_chapters.append({u'book':p[0], u'total':p[3].replace(u'\n', '')})
except:
log.exception(u'Failed to load bible')
finally:
if fbibles:
fbibles.close()
log.debug(u'Bible Initialised')
source = self.db_cache[name].get_meta(u'download source')
if source:
download_name = self.db_cache[name].get_meta(u'download name').value
meta_proxy = self.db_cache[name].get_meta(u'proxy url')
web_bible = HTTPBible(self.parent, path=self.path, name=name,
config=self.config, download_source=source.value,
download_name=download_name)
if meta_proxy:
web_bible.set_proxy_server(meta_proxy.value)
#del self.db_cache[name]
self.db_cache[name] = web_bible
log.debug(u'Bibles reloaded')
def set_process_dialog(self, dialogobject):
def set_process_dialog(self, wizard):
"""
Sets the reference to the dialog with the progress bar on it.
``dialogobject``
The reference to the dialog.
``dialog``
The reference to the import wizard.
"""
self.dialogobject = dialogobject
self.import_wizard = wizard
def import_bible(self, type, **kwargs):
"""
Register a bible in the bible cache, and then import the verses.
``type``
What type of Bible,
What type of Bible, one of the ``BibleFormat`` values.
``**kwargs``
Keyword arguments to send to the actual importer class.
"""
pass
class_ = BibleFormat.get_class(type)
kwargs['path'] = self.path
kwargs['config'] = self.config
importer = class_(self.parent, **kwargs)
name = importer.register(self.import_wizard)
self.db_cache[name] = importer
return importer.do_import()
def register_http_bible(self, biblename, biblesource, bibleid,
proxyurl=None, proxyid=None, proxypass=None):
def get_bibles(self):
"""
Return a list of bibles from a given URL. The selected Bible
can then be registered and LazyLoaded into a database.
``biblename``
The name of the bible to register.
``biblesource``
Where this Bible stores it's verses.
``bibleid``
The identifier for a Bible.
``proxyurl``
Defaults to *None*. An optional URL to a proxy server.
``proxyid``
Defaults to *None*. A username for logging into the proxy
server.
``proxypass``
Defaults to *None*. The password to accompany the username.
"""
log.debug(u'register_HTTP_bible %s, %s, %s, %s, %s, %s',
biblename, biblesource, bibleid, proxyurl, proxyid, proxypass)
if self._is_new_bible(biblename):
# Create new Bible
nbible = BibleDBImpl(self.biblePath, biblename, self.config)
# Create Database
nbible.create_tables()
self.bible_db_cache[biblename] = nbible
nhttp = BibleHTTPImpl()
nhttp.set_bible_source(biblesource)
self.bible_http_cache[biblename] = nhttp
# register a lazy loading interest
nbible.save_meta(u'WEB', biblesource)
# store the web id of the bible
nbible.save_meta(u'bibleid', bibleid)
if proxyurl:
# store the proxy URL
nbible.save_meta(u'proxy', proxyurl)
nhttp.set_proxy(proxyurl)
if proxyid:
# store the proxy userid
nbible.save_meta(u'proxyid', proxyid)
if proxypass:
# store the proxy password
nbible.save_meta(u'proxypass', proxypass)
return True
else:
log.debug(u'register_http_file_bible %s not created already exists',
biblename)
return False
def register_csv_file_bible(self, biblename, booksfile, versefile):
"""
Method to load a bible from a set of files into a database.
If the database exists it is deleted and the database is reloaded
from scratch.
"""
log.debug(u'register_CSV_file_bible %s,%s,%s',
biblename, booksfile, versefile)
if self._is_new_bible(biblename):
# Create new Bible
nbible = BibleDBImpl(self.biblePath, biblename, self.config)
# Create database
nbible.create_tables()
# Cache the database for use later
self.bible_db_cache[biblename] = nbible
# Create the loader and pass in the database
bcsv = BibleCSVImpl(nbible)
return bcsv.load_data(booksfile, versefile, self.dialogobject)
else:
log.debug(u'register_csv_file_bible %s not created already exists',
biblename)
return False
def register_osis_file_bible(self, biblename, osisfile):
"""
Method to load a bible from a osis xml file extracted from Sword bible
viewer. If the database exists it is deleted and the database is
reloaded from scratch.
"""
log.debug(u'register_OSIS_file_bible %s, %s', biblename, osisfile)
if self._is_new_bible(biblename):
# Create new Bible
nbible = BibleDBImpl(self.biblePath, biblename, self.config)
# Create Database
nbible.create_tables()
# Cache the database for use later
self.bible_db_cache[biblename] = nbible
# Create the loader and pass in the database
bosis = BibleOSISImpl(self.biblePath, nbible)
return bosis.load_data(osisfile, self.dialogobject)
else:
log.debug(
u'register_OSIS_file_bible %s, %s not created already exists',
biblename, osisfile)
return False
def register_opensong_bible(self, biblename, opensongfile):
"""
Method to load a bible from an OpenSong xml file. If the database
exists it is deleted and the database is reloaded from scratch.
"""
log.debug(u'register_opensong_file_bible %s, %s', biblename, opensongfile)
if self._is_new_bible(biblename):
# Create new Bible
nbible = BibleDBImpl(self.biblePath, biblename, self.config)
# Create Database
nbible.create_tables()
# Cache the database for use later
self.bible_db_cache[biblename] = nbible
# Create the loader and pass in the database
bcsv = BibleOpenSongImpl(self.biblePath, nbible)
bcsv.load_data(opensongfile, self.dialogobject)
return True
else:
log.debug(u'register_opensong_file_bible %s, %s not created '
u'already exists', biblename, opensongfile)
return False
def get_bibles(self, mode=BibleMode.Full):
"""
Returns a list of Books of the bible. When ``mode`` is set to
``BibleMode.Full`` this method returns all the Bibles for the
Advanced Search, and when the mode is ``BibleMode.Partial``
this method returns all the bibles for the Quick Search.
Returns a list of the names of available Bibles.
"""
log.debug(u'get_bibles')
bible_list = []
for bible_name, bible_object in self.bible_db_cache.iteritems():
if self.bible_http_cache[bible_name]:
bible_name = u'%s (%s)' % (bible_name, self.web)
bible_list.append(bible_name)
return bible_list
return [name for name, bible in self.db_cache.iteritems()]
def is_bible_web(self, bible):
pos_end = bible.find(u' (%s)' % self.web)
if pos_end != -1:
return True, bible[:pos_end]
return False, bible
def get_bible_books(self):
def get_books(self, bible):
"""
Returns a list of the books of the bible
"""
log.debug(u'get_bible_books')
return self.book_chapters
Returns a list of Bible books, and the number of chapters in that book.
def get_book_chapter_count(self, book):
``bible``
Unicode. The Bible to get the list of books from.
"""
log.debug(u'BibleManager.get_books("%s")', bible)
return [
{
u'name': book.name,
u'chapters': self.db_cache[bible].get_chapter_count(book.name)
}
for book in self.db_cache[bible].get_books()
]
def get_chapter_count(self, bible, book):
"""
Returns the number of Chapters for a given book
"""
log.debug(u'get_book_chapter_count %s', book)
return self.book_chapters[book]
return self.db_cache[bible].get_chapter_count(book)
def get_book_verse_count(self, bible, book, chapter):
def get_verse_count(self, bible, book, chapter):
"""
Returns all the number of verses for a given
book and chapterMaxBibleBookVerses
"""
log.debug(u'get_book_verse_count %s,%s,%s', bible, book, chapter)
web, bible = self.is_bible_web(bible)
if web:
count = self.bible_db_cache[bible].get_max_bible_book_verses(
book, chapter)
if count == 0:
# Make sure the first chapter has been downloaded
self.get_verse_text(bible, book, chapter, chapter, 1, 1)
count = self.bible_db_cache[bible].get_max_bible_book_verses(
book, chapter)
return count
else:
return self.bible_db_cache[bible].get_max_bible_book_verses(
book, chapter)
log.debug(u'BibleManager.get_verse_count("%s", "%s", %s)', bible, book, chapter)
return self.db_cache[bible].get_verse_count(book, chapter)
def get_verse_from_text(self, bible, versetext):
def get_verses(self, bible, versetext):
"""
Returns all the number of verses for a given
book and chapterMaxBibleBookVerses
Parses a scripture reference, fetches the verses from the Bible
specified, and returns a list of ``Verse`` objects.
``bible``
Unicode. The Bible to use.
``versetext``
Unicode. The scripture reference. Valid scripture references are:
- Genesis 1:1
- Genesis 1:1-10
- Genesis 1:1-2:10
"""
log.debug(u'get_verses_from_text %s,%s', bible, versetext)
web, bible = self.is_bible_web(bible)
return self.bible_db_cache[bible].get_verses_from_text(versetext)
log.debug(u'BibleManager.get_verses("%s", "%s")', bible, versetext)
reflist = parse_reference(versetext)
return self.db_cache[bible].get_verses(reflist)
def save_meta_data(self, bible, version, copyright, permissions):
"""
@ -367,124 +230,28 @@ class BibleManager(object):
"""
log.debug(u'save_meta data %s,%s, %s,%s',
bible, version, copyright, permissions)
self.bible_db_cache[bible].save_meta(u'Version', version)
self.bible_db_cache[bible].save_meta(u'Copyright', copyright)
self.bible_db_cache[bible].save_meta(u'Permissions', permissions)
self.db_cache[bible].create_meta(u'Version', version)
self.db_cache[bible].create_meta(u'Copyright', copyright)
self.db_cache[bible].create_meta(u'Permissions', permissions)
def get_meta_data(self, bible, key):
"""
Returns the meta data for a given key
"""
log.debug(u'get_meta %s,%s', bible, key)
web, bible = self.is_bible_web(bible)
return self.bible_db_cache[bible].get_meta(key)
return self.db_cache[bible].get_meta(key)
def get_verse_text(self, bible, bookname, schapter, echapter, sverse,
everse=0):
"""
Returns a list of verses for a given Book, Chapter and ranges of verses.
If the end verse(everse) is less then the start verse(sverse)
then only one verse is returned
``bible``
The name of the bible to be used
Rest can be guessed at !
"""
text = []
self.media.setQuickMessage(u'')
log.debug(u'get_verse_text %s,%s,%s,%s,%s,%s',
bible, bookname, schapter, echapter, sverse, everse)
# check to see if book/chapter exists fow HTTP bibles and load cache
# if necessary
web, bible = self.is_bible_web(bible)
if self.bible_http_cache[bible]:
book = self.bible_db_cache[bible].get_bible_book(bookname)
if book is None:
log.debug(u'get_verse_text : new book')
for chapter in range(schapter, echapter + 1):
self.media.setQuickMessage(
unicode(self.media.trUtf8('Downloading %s: %s')) %
(bookname, chapter))
search_results = \
self.bible_http_cache[bible].get_bible_chapter(
bible, bookname, chapter)
if search_results.has_verselist() :
## We have found a book of the bible lets check to see
## if it was there. By reusing the returned book name
## we get a correct book. For example it is possible
## to request ac and get Acts back.
bookname = search_results.get_book()
# check to see if book/chapter exists
book = self.bible_db_cache[bible].get_bible_book(
bookname)
if book is None:
## Then create book, chapter and text
book = self.bible_db_cache[bible].create_book(
bookname, self.book_abbreviations[bookname],
self.book_testaments[bookname])
log.debug(u'New http book %s, %s, %s',
book, book.id, book.name)
self.bible_db_cache[bible].create_chapter(
book.id, search_results.get_chapter(),
search_results.get_verselist())
else:
## Book exists check chapter and texts only.
v = self.bible_db_cache[bible].get_bible_chapter(
book.id, chapter)
if v is None:
self.media.setQuickMessage(
unicode(self.media.trUtf8('%Downloading %s: %s'))\
% (bookname, chapter))
self.bible_db_cache[bible].create_chapter(
book.id, chapter,
search_results.get_verselist())
else:
log.debug(u'get_verse_text : old book')
for chapter in range(schapter, echapter + 1):
v = self.bible_db_cache[bible].get_bible_chapter(
book.id, chapter)
if v is None:
try:
self.media.setQuickMessage(\
unicode(self.media.trUtf8('Downloading %s: %s'))
% (bookname, chapter))
search_results = \
self.bible_http_cache[bible].get_bible_chapter(
bible, bookname, chapter)
if search_results.has_verselist():
self.bible_db_cache[bible].create_chapter(
book.id, search_results.get_chapter(),
search_results.get_verselist())
except:
log.exception(u'Problem getting scripture online')
#Now get verses from database
if schapter == echapter:
text = self.bible_db_cache[bible].get_bible_text(bookname,
schapter, sverse, everse)
else:
for i in range (schapter, echapter + 1):
if i == schapter:
start = sverse
end = self.get_book_verse_count(bible, bookname, i)
elif i == echapter:
start = 1
end = everse
else:
start = 1
end = self.get_book_verse_count(bible, bookname, i)
txt = self.bible_db_cache[bible].get_bible_text(
bookname, i, start, end)
text.extend(txt)
return text
def _is_new_bible(self, name):
def exists(self, name):
"""
Check cache to see if new bible
"""
for bible, o in self.bible_db_cache.iteritems():
if not isinstance(name, unicode):
name = unicode(name)
for bible, db_object in self.db_cache.iteritems():
log.debug(u'Bible from cache in is_new_bible %s', bible)
if not isinstance(bible, unicode):
bible = unicode(bible)
if bible == name:
return False
return True
return True
return False

View File

@ -32,12 +32,20 @@ from openlp.core.lib import MediaManagerItem, Receiver, str_to_bool, \
BaseListWithDnD
from openlp.plugins.bibles.forms import ImportWizardForm
from openlp.plugins.bibles.lib.manager import BibleMode
from openlp.plugins.bibles.lib.common import parse_reference
class BibleListView(BaseListWithDnD):
"""
Drag and drop capable list for Bibles.
"""
def __init__(self, parent=None):
self.PluginName = u'Bibles'
BaseListWithDnD.__init__(self, parent)
def resizeEvent(self, event):
self.parent.onListViewResize(event.size().width(), event.size().width())
class BibleMediaItem(MediaManagerItem):
"""
This is the custom media manager item for Bibles.
@ -52,6 +60,7 @@ class BibleMediaItem(MediaManagerItem):
self.IconPath = u'songs/song'
self.ListViewWithDnD_class = BibleListView
self.servicePath = None
self.lastReference = []
MediaManagerItem.__init__(self, parent, icon, title)
# place to store the search results
self.search_results = {}
@ -237,6 +246,24 @@ class BibleMediaItem(MediaManagerItem):
QtCore.SIGNAL(u'pressed()'), self.onQuickSearchButton)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'config_updated'), self.configUpdated)
# Other stuff
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'bible_showprogress'), self.onSearchProgressShow)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'bible_hideprogress'), self.onSearchProgressHide)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'bible_nobook'), self.onNoBookFound)
def addListViewToToolBar(self):
MediaManagerItem.addListViewToToolBar(self)
# Progress Bar
self.SearchProgress = QtGui.QProgressBar(self)
self.SearchProgress.setFormat('%p%')
self.SearchProgress.setMaximum(3)
self.SearchProgress.setGeometry(self.ListView.geometry().left(),
self.ListView.geometry().top(), 81, 23)
self.SearchProgress.setVisible(False)
self.SearchProgress.setObjectName(u'SearchProgress')
def configUpdated(self):
if str_to_bool(
@ -277,7 +304,7 @@ class BibleMediaItem(MediaManagerItem):
def initialise(self):
log.debug(u'bible manager initialise')
self.parent.biblemanager.media = self
self.parent.manager.media = self
self.loadBibles()
self.configUpdated()
log.debug(u'bible manager initialise complete')
@ -297,23 +324,40 @@ class BibleMediaItem(MediaManagerItem):
self.AdvancedSecondBibleComboBox.clear()
self.QuickSecondBibleComboBox.addItem(u'')
self.AdvancedSecondBibleComboBox.addItem(u'')
bibles = self.parent.biblemanager.get_bibles(BibleMode.Full)
bibles = self.parent.manager.get_bibles()
# load bibles into the combo boxes
first = True
for bible in bibles:
self.QuickVersionComboBox.addItem(bible)
self.QuickSecondBibleComboBox.addItem(bible)
# Without HTTP
bibles = self.parent.biblemanager.get_bibles(BibleMode.Partial)
first = True
# load bibles into the combo boxes
for bible in bibles:
self.AdvancedVersionComboBox.addItem(bible)
self.AdvancedSecondBibleComboBox.addItem(bible)
if first:
first = False
# use the first bible as the trigger
self.initialiseBible(bible)
def onListViewResize(self, width, height):
self.SearchProgress.setGeometry(self.ListView.geometry().x(),
(self.ListView.geometry().y() + self.ListView.geometry().height())\
- 23, 81, 23)
def onSearchProgressShow(self):
self.SearchProgress.setVisible(True)
self.SearchProgress.setMinimum(0)
self.SearchProgress.setMaximum(2)
self.SearchProgress.setValue(1)
def onSearchProgressHide(self):
self.SearchProgress.setVisible(False)
def onNoBookFound(self):
QtGui.QMessageBox.critical(self,
self.trUtf8('No Book Found'),
self.trUtf8('No matching book could be found in this Bible.'),
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok),
QtGui.QMessageBox.Ok
)
def onAdvancedVersionComboBox(self):
self.initialiseBible(
unicode(self.AdvancedVersionComboBox.currentText()))
@ -326,11 +370,8 @@ class BibleMediaItem(MediaManagerItem):
self.AdvancedBookComboBox.itemData(item).toInt()[0])
def onNewClick(self):
#self.bibleimportform = BibleImportForm(
# self.parent.config, self.parent.biblemanager, self)
#self.bibleimportform.exec_()
self.bibleimportform = ImportWizardForm(self, self.parent.config,
self.parent.biblemanager, self.parent)
self.parent.manager, self.parent)
self.bibleimportform.exec_()
self.reloadBibles()
@ -339,14 +380,13 @@ class BibleMediaItem(MediaManagerItem):
self.adjustComboBox(frm, self.verses, self.AdvancedToVerse)
def onAdvancedToChapter(self):
text1 = unicode(self.AdvancedFromChapter.currentText())
text2 = unicode(self.AdvancedToChapter.currentText())
if text1 != text2:
frm = unicode(self.AdvancedFromChapter.currentText())
to = unicode(self.AdvancedToChapter.currentText())
if frm != to:
bible = unicode(self.AdvancedVersionComboBox.currentText())
book = unicode(self.AdvancedBookComboBox.currentText())
# get the verse count for new chapter
verses = self.parent.biblemanager.get_book_verse_count(
bible, book, int(text2))
verses = self.parent.manager.get_verse_count(bible, book, int(to))
self.adjustComboBox(1, verses, self.AdvancedToVerse)
def onAdvancedSearchButton(self):
@ -357,10 +397,13 @@ class BibleMediaItem(MediaManagerItem):
chapter_to = int(self.AdvancedToChapter.currentText())
verse_from = int(self.AdvancedFromVerse.currentText())
verse_to = int(self.AdvancedToVerse.currentText())
self.search_results = self.parent.biblemanager.get_verse_text(
bible, book, chapter_from, chapter_to, verse_from, verse_to)
versetext = u'%s %s:%s-%s:%s' % (book, chapter_from, verse_from, \
chapter_to, verse_to)
self.search_results = self.parent.manager.get_verses(bible, versetext)
if self.ClearAdvancedSearchComboBox.currentIndex() == 0:
self.ListView.clear()
self.lastReference = []
self.lastReference.append(versetext)
self.displayResults(bible)
def onAdvancedFromChapter(self):
@ -369,7 +412,7 @@ class BibleMediaItem(MediaManagerItem):
cf = int(self.AdvancedFromChapter.currentText())
self.adjustComboBox(cf, self.chapters_from, self.AdvancedToChapter)
# get the verse count for new chapter
vse = self.parent.biblemanager.get_book_verse_count(bible, book, cf)
vse = self.parent.manager.get_verse_count(bible, book, cf)
self.adjustComboBox(1, vse, self.AdvancedFromVerse)
self.adjustComboBox(1, vse, self.AdvancedToVerse)
@ -379,11 +422,9 @@ class BibleMediaItem(MediaManagerItem):
text = unicode(self.QuickSearchEdit.displayText())
if self.ClearQuickSearchComboBox.currentIndex() == 0:
self.ListView.clear()
if self.QuickSearchComboBox.currentIndex() == 1:
self.search_results = self.parent.biblemanager.get_verse_from_text(
bible, text)
else:
self.searchByReference(bible, text)
self.lastReference = []
self.lastReference.append(text)
self.search_results = self.parent.manager.get_verses(bible, text)
if self.search_results:
self.displayResults(bible)
@ -396,60 +437,63 @@ class BibleMediaItem(MediaManagerItem):
raw_slides = []
raw_footer = []
bible_text = u''
#If we want to use a 2nd translation / version
bible2 = u''
if self.SearchTabWidget.currentIndex() == 0:
bible2 = unicode(self.QuickSecondBibleComboBox.currentText())
else:
bible2 = unicode(self.AdvancedSecondBibleComboBox.currentText())
if bible2:
bible2_verses = []
for scripture in self.lastReference:
bible2_verses.extend(self.parent.manager.get_verses(bible2, scripture))
bible2_version = self.parent.manager.get_meta_data(bible2, u'Version')
bible2_copyright = self.parent.manager.get_meta_data(bible2, u'Copyright')
bible2_permission = self.parent.manager.get_meta_data(bible2, u'Permission')
# Let's loop through the main lot, and assemble our verses
for item in items:
bitem = self.ListView.item(item.row())
text = unicode((bitem.data(QtCore.Qt.UserRole)).toString())
search_verse = text[:text.find(u'(')]
bible = text[text.find(u'(') + 1:-1]
self.searchByReference(bible, search_verse)
book = self.search_results[0].book.name
chapter = unicode(self.search_results[0].chapter)
verse = unicode(self.search_results[0].verse)
text = self.search_results[0].text
reference = bitem.data(QtCore.Qt.UserRole).toPyObject()
bible = unicode(reference[QtCore.QString('bible')])
book = unicode(reference[QtCore.QString('book')])
chapter = unicode(reference[QtCore.QString('chapter')])
verse = unicode(reference[QtCore.QString('verse')])
text = unicode(reference[QtCore.QString('text')])
version = unicode(reference[QtCore.QString('version')])
copyright = unicode(reference[QtCore.QString('copyright')])
permission = unicode(reference[QtCore.QString('permission')])
if self.parent.settings_tab.display_style == 1:
loc = self.formatVerse(old_chapter, chapter, verse, u'(u', u')')
verse_text = self.formatVerse(old_chapter, chapter, verse, u'(u', u')')
elif self.parent.settings_tab.display_style == 2:
loc = self.formatVerse(old_chapter, chapter, verse, u'{', u'}')
verse_text = self.formatVerse(old_chapter, chapter, verse, u'{', u'}')
elif self.parent.settings_tab.display_style == 3:
loc = self.formatVerse(old_chapter, chapter, verse, u'[', u']')
verse_text = self.formatVerse(old_chapter, chapter, verse, u'[', u']')
else:
loc = self.formatVerse(old_chapter, chapter, verse, u'', u'')
verse_text = self.formatVerse(old_chapter, chapter, verse, u'', u'')
old_chapter = chapter
footer = u'%s (%s %s)' % (book, self.version, self.copyright)
footer = u'%s (%s %s)' % (book, version, copyright)
#If not found throws and error so add.s
try:
raw_footer.index(footer)
except:
if footer not in raw_footer:
raw_footer.append(footer)
#If we want to use a 2nd translation / version
bible2 = u''
if self.SearchTabWidget.currentIndex() == 0:
bible2 = unicode(self.QuickSecondBibleComboBox.currentText())
else:
bible2 = unicode(self.AdvancedSecondBibleComboBox.currentText())
if len(bible2) > 0:
self.searchByReference(bible2, search_verse)
footer = u'%s (%s %s)' % (book, self.version, self.copyright)
if bible2:
footer = u'%s (%s %s)' % (book, version, copyright)
#If not found throws and error so add.s
try:
raw_footer.index(footer)
except:
if footer not in raw_footer:
raw_footer.append(footer)
bible_text = u'%s %s \n\n\n %s %s)' % \
(loc, text, loc, self.search_results[0].text)
bible_text = u'%s %s \n\n %s %s' % \
(verse_text, text, verse_text, bible2_verses[item.row()].text)
raw_slides.append(bible_text)
bible_text = u''
else:
#Paragraph style force new line per verse
if self.parent.settings_tab.layout_style == 1:
text = text + u'\n\n'
bible_text = u'%s %s %s' % (bible_text, loc, text)
bible_text = u'%s %s %s' % (bible_text, verse_text, text)
#if we are verse per slide then create slide
if self.parent.settings_tab.layout_style == 0:
raw_slides.append(bible_text)
bible_text = u''
service_item.title = u'%s %s' % (book, loc)
service_item.title = u'%s %s' % (book, verse_text)
if len(self.parent.settings_tab.bible_theme) == 0:
service_item.theme = None
else:
@ -463,40 +507,39 @@ class BibleMediaItem(MediaManagerItem):
return True
def formatVerse(self, old_chapter, chapter, verse, opening, closing):
loc = opening
verse_text = opening
if old_chapter != chapter:
loc += chapter + u':'
verse_text += chapter + u':'
elif not self.parent.settings_tab.show_new_chapters:
loc += chapter + u':'
loc += verse
loc += closing
return loc
verse_text += chapter + u':'
verse_text += verse
verse_text += closing
return verse_text
def reloadBibles(self):
log.debug(u'Reloading Bibles')
self.parent.biblemanager.reload_bibles()
self.parent.manager.reload_bibles()
self.loadBibles()
def initialiseBible(self, bible):
log.debug(u'initialiseBible %s', bible)
book_data = self.parent.biblemanager.get_bible_books()
book_data = self.parent.manager.get_books(bible)
self.AdvancedBookComboBox.clear()
first = True
for book in book_data:
row = self.AdvancedBookComboBox.count()
self.AdvancedBookComboBox.addItem(book[u'book'])
self.AdvancedBookComboBox.addItem(book[u'name'])
self.AdvancedBookComboBox.setItemData(
row, QtCore.QVariant(book[u'total']))
row, QtCore.QVariant(book[u'chapters']))
if first:
first = False
self.initialiseChapterVerse(
bible, book[u'book'], book[u'total'])
bible, book[u'name'], book[u'chapters'])
def initialiseChapterVerse(self, bible, book, chapters):
log.debug(u'initialiseChapterVerse %s, %s', bible, book)
self.chapters_from = chapters
self.verses = self.parent.biblemanager.get_book_verse_count(bible,
book, 1)
self.verses = self.parent.manager.get_verse_count(bible, book, 1)
if self.verses == 0:
self.AdvancedSearchButton.setEnabled(False)
self.AdvancedMessage.setText(self.trUtf8('Bible not fully loaded'))
@ -515,12 +558,30 @@ class BibleMediaItem(MediaManagerItem):
combo.addItem(unicode(i))
def displayResults(self, bible):
version = self.parent.manager.get_meta_data(bible, u'Version')
copyright = self.parent.manager.get_meta_data(bible, u'Copyright')
permission = self.parent.manager.get_meta_data(bible, u'Permission')
if not permission:
permission = u''
else:
permission = permission.value
for count, verse in enumerate(self.search_results):
bible_text = u' %s %d:%d (%s)' % (verse.book.name,
verse.chapter, verse.verse, bible)
bible_text = u' %s %d:%d (%s)' % \
(verse.book.name, verse.chapter, verse.verse, bible)
bible_verse = QtGui.QListWidgetItem(bible_text)
bible_verse.setData(QtCore.Qt.UserRole,
QtCore.QVariant(bible_text))
#bible_verse.setData(QtCore.Qt.UserRole,
# QtCore.QVariant(bible_text))
vdict = {
'bible': QtCore.QVariant(bible),
'version': QtCore.QVariant(version.value),
'copyright': QtCore.QVariant(copyright.value),
'permission': QtCore.QVariant(permission),
'book': QtCore.QVariant(verse.book.name),
'chapter': QtCore.QVariant(verse.chapter),
'verse': QtCore.QVariant(verse.verse),
'text': QtCore.QVariant(verse.text)
}
bible_verse.setData(QtCore.Qt.UserRole, QtCore.QVariant(vdict))
self.ListView.addItem(bible_verse)
row = self.ListView.setCurrentRow(count)
if row:
@ -528,85 +589,4 @@ class BibleMediaItem(MediaManagerItem):
def searchByReference(self, bible, search):
log.debug(u'searchByReference %s, %s', bible, search)
book = u''
start_chapter = u''
end_chapter = u''
start_verse = u''
end_verse = u''
search = search.replace(u' ', u' ').strip()
#original = search
message = None
# Remove book beware 0 index arrays
for i in range (len(search)-1, 0, - 1):
if search[i] == u' ':
book = search[:i]
# remove book from string
search = search[i:]
break
# allow V or v for verse instead of :
search = search.replace(u'v', ':')
search = search.replace(u'V', ':')
search = search.strip()
colon = search.find(u':')
if colon == -1:
# number : found
i = search.rfind(u' ')
if i == -1:
chapter = u''
else:
chapter = search[i:len(search)]
hyphen = chapter.find(u'-')
if hyphen != -1:
start_chapter= chapter[:hyphen]
end_chapter= chapter[hyphen + 1:len(chapter)]
else:
start_chapter = chapter
else:
# more complex
sp = search.split(u'-') #find first
sp1 = sp[0].split(u':')
if len(sp1) == 1:
start_chapter = sp1[0]
start_verse = 1
else:
start_chapter = sp1[0]
start_verse = sp1[1]
if len(sp)== 1:
end_chapter = start_chapter
end_verse = start_verse
else:
sp1 = sp[1].split(u':')
if len(sp1) == 1:
end_chapter = start_chapter
end_verse = sp1[0]
else:
end_chapter = sp1[0]
end_verse = sp1[1]
if end_chapter == u'':
end_chapter = start_chapter.rstrip()
if start_verse == u'':
if end_verse == u'':
start_verse = 1
else:
start_verse = end_verse
if end_verse == u'':
end_verse = 99
if start_chapter == u'':
message = self.trUtf8('No chapter found for search criteria')
log.debug(u'results = %s @ %s : %s @ %s : %s'% \
(unicode(book), unicode(start_chapter), unicode(end_chapter),
unicode(start_verse), unicode(end_verse)))
if message is None:
self.search_results = None
self.search_results = self.parent.biblemanager.get_verse_text(
bible, book, int(start_chapter), int(end_chapter),
int(start_verse), int(end_verse))
self.copyright = unicode(self.parent.biblemanager.get_meta_data(
bible, u'Copyright').value)
self.permissions = unicode(self.parent.biblemanager.get_meta_data(
bible, u'Permissions').value)
self.version = unicode(self.parent.biblemanager.get_meta_data(
bible, u'Version').value)
else:
QtGui.QMessageBox.information(
self, self.trUtf8('Information'), message)
self.search_results = self.parent.manager.get_verses(bible, search)

View File

@ -50,7 +50,7 @@ class BibleMeta(BaseModel):
pass
class ONTestament(BaseModel):
class Testament(BaseModel):
"""
Bible Testaments
"""
@ -101,8 +101,8 @@ verse_table = Table(u'verse', metadata,
Column(u'text', types.UnicodeText, index=True),
)
mapper(BibleMeta, meta_table)
mapper(ONTestament, testament_table,
mapper(Testament, testament_table,
properties={'books': relation(Book, backref='testament')})
mapper(Book, book_table,
properties={'verses': relation(Verse, backref='book')})
mapper(Verse, verse_table)
mapper(Verse, verse_table)

View File

@ -33,94 +33,81 @@ from lxml import objectify
from PyQt4 import QtCore
from openlp.core.lib import Receiver
from db import BibleDB
class BibleOpenSongImpl():
log = logging.getLogger(__name__)
class OpenSongBible(BibleDB):
"""
OSIS Bible format importer class.
OpenSong Bible format importer class.
"""
global log
log = logging.getLogger(__name__)
log.info(u'BibleOpenSongImpl loaded')
def __init__(self, biblepath, bibledb):
def __init__(self, parent, **kwargs):
"""
Constructor to create and set up an instance of the
BibleOpenSongImpl class.
``biblepath``
This does not seem to be used.
``bibledb``
A reference to a Bible database object.
Constructor to create and set up an instance of the OpenSongBible
class. This class is used to import Bibles from OpenSong's XML format.
"""
log.info(u'BibleOpenSongImpl Initialising')
self.bibledb = bibledb
self.loadbible = True
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'openlpstopimport'), self.stop_import)
log.debug(__name__)
BibleDB.__init__(self, parent, **kwargs)
if 'filename' not in kwargs:
raise KeyError(u'You have to supply a file name to import from.')
self.filename = kwargs['filename']
#QtCore.QObject.connect(Receiver.get_receiver(),
# QtCore.SIGNAL(u'openlpstopimport'), self.stop_import)
def stop_import(self):
"""
Stops the import of the Bible.
"""
self.loadbible = False
log.debug('Stopping import!')
self.stop_import = True
def load_data(self, bible_file, dialogobject=None):
def do_import(self):
"""
Loads a Bible from file.
``bible_file``
The file to import from.
``dialogobject``
The Import dialog, so that we can increase the counter on
the progress bar.
"""
log.info(u'Load data for %s' % bible_file)
bible_file = unicode(bible_file)
detect_file = None
try:
detect_file = open(bible_file, u'r')
details = chardet.detect(detect_file.read(2048))
except:
log.exception(u'Failed to detect OpenSong file encoding')
return
finally:
if detect_file:
detect_file.close()
opensong_bible = None
log.debug(u'Starting OpenSong import from "%s"' % self.filename)
self.filename = unicode(self.filename, u'utf-8')
self.wizard.incrementProgressBar(u'Preparing for import...')
file = None
success = True
try:
opensong_bible = codecs.open(bible_file, u'r', details['encoding'])
opensong = objectify.parse(opensong_bible)
# NOTE: We don't need to do any of the normal encoding detection
# here, because lxml does it's own encoding detection, and the two
# mechanisms together interfere with each other.
file = open(self.filename, u'r')
opensong = objectify.parse(file)
bible = opensong.getroot()
for book in bible.b:
if not self.loadbible:
if self.stop_import:
break
dbbook = self.bibledb.create_book(book.attrib[u'n'],
book.attrib[u'n'][:4])
db_book = self.create_book(unicode(book.attrib[u'n']),
unicode(book.attrib[u'n'][:4]))
for chapter in book.c:
if not self.loadbible:
if self.stop_import:
break
for verse in chapter.v:
if not self.loadbible:
if self.stop_import:
break
self.bibledb.add_verse(dbbook.id, chapter.attrib[u'n'],
verse.attrib[u'n'], verse.text)
self.create_verse(
db_book.id,
int(chapter.attrib[u'n']),
int(verse.attrib[u'n']),
unicode(verse.text)
)
Receiver.send_message(u'process_events')
dialogobject.incrementProgressBar(u'Importing %s %s' % \
(dbbook.name, str(chapter.attrib[u'n'])))
self.bibledb.save_verses()
self.wizard.incrementProgressBar(
QtCore.QString('%s %s %s' % (self.trUtf8('Importing'),\
db_book.name, chapter.attrib[u'n'])))
self.commit()
except:
log.exception(u'Loading bible from OpenSong file failed')
success = False
finally:
if opensong_bible:
opensong_bible.close()
if not self.loadbible:
dialogobject.incrementProgressBar(u'Import canceled!')
dialogobject.ImportProgressBar.setValue(
dialogobject.ImportProgressBar.maximum())
if file:
file.close()
if self.stop_import:
self.wizard.incrementProgressBar(u'Import canceled!')
return False
else:
return success

View File

@ -33,8 +33,9 @@ import re
from PyQt4 import QtCore
from openlp.core.lib import Receiver
from db import BibleDB
class BibleOSISImpl():
class OSISBible(BibleDB):
"""
OSIS Bible format importer class.
"""
@ -42,18 +43,16 @@ class BibleOSISImpl():
log = logging.getLogger(u'BibleOSISImpl')
log.info(u'BibleOSISImpl loaded')
def __init__(self, biblepath, bibledb):
def __init__(self, parent, **kwargs):
"""
Constructor to create and set up an instance of the
BibleOSISImpl class.
``biblepath``
This does not seem to be used.
``bibledb``
A reference to a Bible database object.
Constructor to create and set up an instance of the OpenSongBible
class. This class is used to import Bibles from OpenSong's XML format.
"""
log.info(u'BibleOSISImpl Initialising')
log.debug(__name__)
BibleDB.__init__(self, parent, **kwargs)
if u'filename' not in kwargs:
raise KeyError(u'You have to supply a file name to import from.')
self.filename = kwargs[u'filename']
self.verse_regex = re.compile(
r'<verse osisID="([a-zA-Z0-9 ]*).([0-9]*).([0-9]*)">(.*?)</verse>')
self.note_regex = re.compile(r'<note(.*?)>(.*?)</note>')
@ -66,13 +65,11 @@ class BibleOSISImpl():
self.w_regex = re.compile(r'<w (.*?)>')
self.q_regex = re.compile(r'<q (.*?)>')
self.spaces_regex = re.compile(r'([ ]{2,})')
self.bibledb = bibledb
self.books = {}
filepath = os.path.split(os.path.abspath(__file__))[0]
filepath = os.path.abspath(os.path.join(
filepath, u'..', u'resources', u'osisbooks.csv'))
fbibles = None
self.loadbible = True
try:
fbibles = open(filepath, u'r')
for line in fbibles:
@ -84,31 +81,24 @@ class BibleOSISImpl():
finally:
if fbibles:
fbibles.close()
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'openlpstopimport'), self.stop_import)
#QtCore.QObject.connect(Receiver.get_receiver(),
# QtCore.SIGNAL(u'openlpstopimport'), self.stop_import)
def stop_import(self):
"""
Stops the import of the Bible.
"""
log.debug('Stopping import!')
self.loadbible = False
self.stop_import = True
def load_data(self, osisfile_record, dialogobject=None):
def do_import(self):
"""
Loads a Bible from file.
``osisfile_record``
The file to import from.
``dialogobject``
The Import dialog, so that we can increase the counter on
the progress bar.
"""
log.info(u'Load data for %s' % osisfile_record)
log.debug(u'Starting OSIS import from "%s"' % self.filename)
detect_file = None
try:
detect_file = open(osisfile_record, u'r')
detect_file = open(self.filename, u'r')
details = chardet.detect(detect_file.read(3000))
except:
log.exception(u'Failed to detect OSIS file encoding')
@ -119,12 +109,12 @@ class BibleOSISImpl():
osis = None
success = True
try:
osis = codecs.open(osisfile_record, u'r', details['encoding'])
osis = codecs.open(self.filename, u'r', details['encoding'])
last_chapter = 0
testament = 1
db_book = None
for file_record in osis:
if not self.loadbible:
if self.stop_import:
break
match = self.verse_regex.search(file_record)
if match:
@ -142,13 +132,13 @@ class BibleOSISImpl():
testament)
if last_chapter == 0:
if book == u'Gen':
dialogobject.ImportProgressBar.setMaximum(1188)
self.wizard.ImportProgressBar.setMaximum(1188)
else:
dialogobject.ImportProgressBar.setMaximum(260)
self.wizard.ImportProgressBar.setMaximum(260)
if last_chapter != chapter:
if last_chapter != 0:
self.bibledb.save_verses()
dialogobject.incrementProgressBar(
self.wizard.incrementProgressBar(
u'Importing %s %s...' % \
(self.books[match.group(1)][0], chapter))
last_chapter = chapter
@ -170,20 +160,19 @@ class BibleOSISImpl():
.replace(u'</lg>', u'').replace(u'</q>', u'')\
.replace(u'</div>', u'')
verse_text = self.spaces_regex.sub(u' ', verse_text)
self.bibledb.add_verse(db_book.id, chapter, verse, verse_text)
self.create_verse(db_book.id, chapter, verse, verse_text)
Receiver.send_message(u'process_events')
self.bibledb.save_verses()
dialogobject.incrementProgressBar(u'Finishing import...')
self.commit()
self.wizard.incrementProgressBar(u'Finishing import...')
except:
log.exception(u'Loading bible from OSIS file failed')
success = False
finally:
if osis:
osis.close()
if not self.loadbible:
dialogobject.incrementProgressBar(u'Import canceled!')
dialogobject.ImportProgressBar.setValue(
dialogobject.ImportProgressBar.maximum())
if self.stop_import:
self.wizard.incrementProgressBar(u'Import canceled!')
return False
else:
return success
return success

View File

@ -1,66 +0,0 @@
Genesis,Gen,1,50
Exodus,Exod,1,40
Leviticus,Lev,1,27
Numbers,Num,1,36
Deuteronomy,Deut,1,34
Joshua,Josh,1,24
Judges,Judg,1,21
Ruth,Ruth,1,4
1 Samual,1Sam,1,31
2 Samual,2Sam,1,24
1 Kings,1Kgs,1,22
2 Kings,2Kgs,1,25
1 Chronicles,1Chr,1,29
2 Chronicles,2Chr,1,36
Ezra,Esra,1,10
Nehemiah,Neh,1,13
Esther,Esth,1,10
Job,Job,1,42
Psalms,Ps,1,150
Proverbs,Prov,1,31
Ecclesiastes,Eccl,1,12
Song of Songs,Song,1,8
Isaiah,Isa,1,66
Jeremiah,Jer,1,5
Lamentations,Lam,1,5
Ezekiel,Ezek,1,48
Daniel,Dan,1,12
Hosea,Hos,1,14
Joel,Joel,1,3
Amos,Amos,1,9
Obad,Obad,1,1
Jonah,Jonah,1,4
Micah,Mic,1,7
Naham,Nah,1,3
Habakkuk,Hab,1,3
Zephaniah,Zeph,1,3
Haggai,Hag,1,2
Zechariah,Zech,1,3
Malachi,Mal,1,4
Matthew,Matt,2,28
Mark,Mark,2,16
Luke,Luke,2,24
John,John,2,21
Acts,Acts,2,28
Romans,Rom,2,16
1 Corinthans,1Cor,2,16
2 Corinthans,2Cor,2,13
Galatians,Gal,2,6
Ephesians,Eph,2,6
Philippians,Phil,2,4
Colossians,Col,2,4
1 Thessalonians,1Thess,2,5
2 Thessalonians,2Thess,2,3
1 Timothy,1Tim,2,6
2 Timothy,2Tim,2,4
Titus,Titus,2,3
Philemon,Phlm,2,1
Hebrews,Heb,2,13
James,Jas,2,5
1 Peter,1Pet,2,5
2 Peter,2Pet,2,3
1 John,1John,2,5
2 John,2John,2,1
3 John,3John,2,1
Jude,Jude,2,1
Revelation,Rev,2,22
1 Genesis Gen 1 50
2 Exodus Exod 1 40
3 Leviticus Lev 1 27
4 Numbers Num 1 36
5 Deuteronomy Deut 1 34
6 Joshua Josh 1 24
7 Judges Judg 1 21
8 Ruth Ruth 1 4
9 1 Samual 1Sam 1 31
10 2 Samual 2Sam 1 24
11 1 Kings 1Kgs 1 22
12 2 Kings 2Kgs 1 25
13 1 Chronicles 1Chr 1 29
14 2 Chronicles 2Chr 1 36
15 Ezra Esra 1 10
16 Nehemiah Neh 1 13
17 Esther Esth 1 10
18 Job Job 1 42
19 Psalms Ps 1 150
20 Proverbs Prov 1 31
21 Ecclesiastes Eccl 1 12
22 Song of Songs Song 1 8
23 Isaiah Isa 1 66
24 Jeremiah Jer 1 5
25 Lamentations Lam 1 5
26 Ezekiel Ezek 1 48
27 Daniel Dan 1 12
28 Hosea Hos 1 14
29 Joel Joel 1 3
30 Amos Amos 1 9
31 Obad Obad 1 1
32 Jonah Jonah 1 4
33 Micah Mic 1 7
34 Naham Nah 1 3
35 Habakkuk Hab 1 3
36 Zephaniah Zeph 1 3
37 Haggai Hag 1 2
38 Zechariah Zech 1 3
39 Malachi Mal 1 4
40 Matthew Matt 2 28
41 Mark Mark 2 16
42 Luke Luke 2 24
43 John John 2 21
44 Acts Acts 2 28
45 Romans Rom 2 16
46 1 Corinthans 1Cor 2 16
47 2 Corinthans 2Cor 2 13
48 Galatians Gal 2 6
49 Ephesians Eph 2 6
50 Philippians Phil 2 4
51 Colossians Col 2 4
52 1 Thessalonians 1Thess 2 5
53 2 Thessalonians 2Thess 2 3
54 1 Timothy 1Tim 2 6
55 2 Timothy 2Tim 2 4
56 Titus Titus 2 3
57 Philemon Phlm 2 1
58 Hebrews Heb 2 13
59 James Jas 2 5
60 1 Peter 1Pet 2 5
61 2 Peter 2Pet 2 3
62 1 John 1John 2 5
63 2 John 2John 2 1
64 3 John 3John 2 1
65 Jude Jude 2 1
66 Revelation Rev 2 22

Binary file not shown.

View File

@ -153,10 +153,10 @@ class EditCustomForm(QtGui.QDialog, Ui_customEditDialog):
sxml.add_verse_to_lyrics(u'custom', unicode(count),
unicode(self.VerseListView.item(i).text()))
count += 1
self.customSlide.title = unicode(self.TitleEdit.displayText())
self.customSlide.text = unicode(sxml.extract_xml())
self.customSlide.credits = unicode(self.CreditEdit.displayText())
self.customSlide.theme_name = unicode(self.ThemeComboBox.currentText())
self.customSlide.title = unicode(self.TitleEdit.displayText(), u'utf-8')
self.customSlide.text = unicode(sxml.extract_xml(), u'utf-8')
self.customSlide.credits = unicode(self.CreditEdit.displayText(), u'utf-8')
self.customSlide.theme_name = unicode(self.ThemeComboBox.currentText(), u'utf-8')
self.custommanager.save_slide(self.customSlide)
return True
@ -257,4 +257,4 @@ class EditCustomForm(QtGui.QDialog, Ui_customEditDialog):
if len(self.VerseTextEdit.toPlainText()) > 0:
self.VerseTextEdit.setFocus()
return False, self.trUtf8('You have unsaved data')
return True, u''
return True, u''

View File

@ -185,8 +185,13 @@ class SongMediaItem(MediaManagerItem):
if author_list != u'':
author_list = author_list + u', '
author_list = author_list + author.display_name
song_detail = unicode(self.trUtf8('%s (%s)' % \
(unicode(song.title), unicode(author_list))))
if not isinstance(author_list, unicode):
author_list = unicode(author_list, u'utf8')
if isinstance(song.title, unicode):
song_title = song.title
else:
song_title = unicode(song.title, u'utf8')
song_detail = u'%s (%s)' % (song_title, author_list)
song_name = QtGui.QListWidgetItem(song_detail)
song_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(song.id))
self.ListView.addItem(song_name)
@ -339,4 +344,4 @@ class SongMediaItem(MediaManagerItem):
service_item.audit = [
song.title, author_audit, song.copyright, song.ccli_number
]
return True
return True

View File

@ -1 +1 @@
1.9.0-698
1.9.0-700