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]' usage = u'Usage: %prog [options] [qt-options]'
parser = OptionParser(usage=usage) parser = OptionParser(usage=usage)
parser.add_option("-l", "--log-level", dest="loglevel", 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 " help="Set logging to LEVEL level. Valid values are "
"\"debug\", \"info\", \"warning\".") "\"debug\", \"info\", \"warning\".")
parser.add_option("-p", "--portable", dest="portable", parser.add_option("-p", "--portable", dest="portable",

View File

@ -32,6 +32,7 @@ class BaseListWithDnD(QtGui.QListWidget):
def __init__(self, parent=None): def __init__(self, parent=None):
QtGui.QListWidget.__init__(self, parent) QtGui.QListWidget.__init__(self, parent)
self.parent = parent
# this must be set by the class which is inheriting # this must be set by the class which is inheriting
assert(self.PluginName) assert(self.PluginName)
@ -48,3 +49,4 @@ class BaseListWithDnD(QtGui.QListWidget):
drag.setMimeData(mimeData) drag.setMimeData(mimeData)
mimeData.setText(self.PluginName) 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. Get the global ``eventreceiver`` instance.
""" """
return Receiver.eventreceiver return Receiver.eventreceiver

View File

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

View File

@ -40,12 +40,12 @@ class BiblePlugin(Plugin):
self.weight = -9 self.weight = -9
self.icon = build_icon(u':/media/media_bible.png') self.icon = build_icon(u':/media/media_bible.png')
#Register the bible Manager #Register the bible Manager
self.biblemanager = None self.manager = None
def initialise(self): def initialise(self):
log.info(u'bibles Initialising') log.info(u'bibles Initialising')
if self.biblemanager is None: if self.manager is None:
self.biblemanager = BibleManager(self.config) self.manager = BibleManager(self, self.config)
Plugin.initialise(self) Plugin.initialise(self)
self.insert_toolbox_item() self.insert_toolbox_item()
self.ImportBibleItem.setVisible(True) self.ImportBibleItem.setVisible(True)
@ -91,3 +91,4 @@ class BiblePlugin(Plugin):
'plugin allows bible verses from different sources to be ' 'plugin allows bible verses from different sources to be '
'displayed on the screen during the service.') '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.setMargin(0)
self.OsisLayout.setSpacing(8) self.OsisLayout.setSpacing(8)
self.OsisLayout.setObjectName(u'OsisLayout') 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 = QtGui.QLabel(self.OsisPage)
self.OsisLocationLabel.setObjectName(u'OsisLocationLabel') self.OsisLocationLabel.setObjectName(u'OsisLocationLabel')
self.OsisLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.OsisLayout.setWidget(1, QtGui.QFormLayout.LabelRole,
@ -302,13 +293,11 @@ class Ui_BibleImportWizard(object):
self.ImportProgressLabel.setObjectName(u'ImportProgressLabel') self.ImportProgressLabel.setObjectName(u'ImportProgressLabel')
self.ImportLayout.addWidget(self.ImportProgressLabel) self.ImportLayout.addWidget(self.ImportProgressLabel)
self.ImportProgressBar = QtGui.QProgressBar(self.ImportPage) self.ImportProgressBar = QtGui.QProgressBar(self.ImportPage)
self.ImportProgressBar.setProperty(u'value', 0) self.ImportProgressBar.setValue(0)
self.ImportProgressBar.setInvertedAppearance(False)
self.ImportProgressBar.setObjectName(u'ImportProgressBar') self.ImportProgressBar.setObjectName(u'ImportProgressBar')
self.ImportLayout.addWidget(self.ImportProgressBar) self.ImportLayout.addWidget(self.ImportProgressBar)
BibleImportWizard.addPage(self.ImportPage) BibleImportWizard.addPage(self.ImportPage)
self.retranslateUi(BibleImportWizard) self.retranslateUi(BibleImportWizard)
self.FormatWidget.setCurrentIndex(0) self.FormatWidget.setCurrentIndex(0)
self.WebDownloadTabWidget.setCurrentIndex(0) self.WebDownloadTabWidget.setCurrentIndex(0)
@ -334,7 +323,6 @@ class Ui_BibleImportWizard(object):
self.FormatComboBox.setItemText(1, self.trUtf8('CSV')) self.FormatComboBox.setItemText(1, self.trUtf8('CSV'))
self.FormatComboBox.setItemText(2, self.trUtf8('OpenSong')) self.FormatComboBox.setItemText(2, self.trUtf8('OpenSong'))
self.FormatComboBox.setItemText(3, self.trUtf8('Web Download')) self.FormatComboBox.setItemText(3, self.trUtf8('Web Download'))
self.OsisBibleNameLabel.setText(self.trUtf8('Bible Name:'))
self.OsisLocationLabel.setText(self.trUtf8('File Location:')) self.OsisLocationLabel.setText(self.trUtf8('File Location:'))
self.BooksLocationLabel.setText(self.trUtf8('Books Location:')) self.BooksLocationLabel.setText(self.trUtf8('Books Location:'))
self.VerseLocationLabel.setText(self.trUtf8('Verse Location:')) self.VerseLocationLabel.setText(self.trUtf8('Verse Location:'))
@ -362,4 +350,4 @@ class Ui_BibleImportWizard(object):
self.ImportPage.setSubTitle( self.ImportPage.setSubTitle(
self.trUtf8('Please wait while your Bible is imported.')) self.trUtf8('Please wait while your Bible is imported.'))
self.ImportProgressLabel.setText(self.trUtf8('Ready.')) 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
import os.path import os.path
from time import sleep from time import sleep
import csv
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
@ -59,7 +60,7 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
log = logging.getLogger(u'BibleImportForm') log = logging.getLogger(u'BibleImportForm')
log.info(u'BibleImportForm loaded') log.info(u'BibleImportForm loaded')
def __init__(self, parent, config, biblemanager, bibleplugin): def __init__(self, parent, config, manager, bibleplugin):
''' '''
Constructor Constructor
''' '''
@ -68,10 +69,10 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
self.registerFields() self.registerFields()
self.finishButton = self.button(QtGui.QWizard.FinishButton) self.finishButton = self.button(QtGui.QWizard.FinishButton)
self.cancelButton = self.button(QtGui.QWizard.CancelButton) self.cancelButton = self.button(QtGui.QWizard.CancelButton)
self.biblemanager = biblemanager self.manager = manager
self.config = config self.config = config
self.bibleplugin = bibleplugin self.bibleplugin = bibleplugin
self.biblemanager.set_process_dialog(self) self.manager.set_process_dialog(self)
self.web_bible_list = {} self.web_bible_list = {}
self.loadWebBibles() self.loadWebBibles()
QtCore.QObject.connect(self.LocationComboBox, QtCore.QObject.connect(self.LocationComboBox,
@ -96,9 +97,9 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
QtCore.SIGNAL(u'currentIdChanged(int)'), QtCore.SIGNAL(u'currentIdChanged(int)'),
self.onCurrentIdChanged) self.onCurrentIdChanged)
def show(self): def exec_(self):
self.setDefaults() self.setDefaults()
return QtGui.QWizard.show() return QtGui.QWizard.exec_(self)
def validateCurrentPage(self): def validateCurrentPage(self):
if self.currentId() == 0: if self.currentId() == 0:
@ -107,14 +108,6 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
elif self.currentId() == 1: elif self.currentId() == 1:
# Select page # Select page
if self.field(u'source_format').toInt()[0] == BibleFormat.OSIS: 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'': if self.field(u'osis_location').toString() == u'':
QtGui.QMessageBox.critical(self, QtGui.QMessageBox.critical(self,
self.trUtf8('Invalid Bible Location'), self.trUtf8('Invalid Bible Location'),
@ -169,6 +162,15 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok)) QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok))
self.CopyrightEdit.setFocus() self.CopyrightEdit.setFocus()
return False 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 return True
if self.currentId() == 3: if self.currentId() == 3:
# Progress page # Progress page
@ -209,8 +211,6 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
def registerFields(self): def registerFields(self):
self.SelectPage.registerField( self.SelectPage.registerField(
u'source_format', self.FormatComboBox) u'source_format', self.FormatComboBox)
self.SelectPage.registerField(
u'osis_biblename', self.OsisBibleNameEdit)
self.SelectPage.registerField( self.SelectPage.registerField(
u'osis_location', self.OSISLocationEdit) u'osis_location', self.OSISLocationEdit)
self.SelectPage.registerField( self.SelectPage.registerField(
@ -238,23 +238,22 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
def setDefaults(self): def setDefaults(self):
self.setField(u'source_format', 0) self.setField(u'source_format', 0)
self.setField(u'osis_biblename', u'') self.setField(u'osis_location', '')
self.setField(u'osis_location', u'') self.setField(u'csv_booksfile', '')
self.setField(u'csv_booksfile', u'') self.setField(u'csv_versefile', '')
self.setField(u'csv_versefile', u'') self.setField(u'opensong_file', '')
self.setField(u'opensong_file', u'') self.setField(u'web_location', DownloadLocation.Crosswalk)
self.setField(u'web_location', 0)
self.setField(u'web_biblename', self.BibleComboBox) self.setField(u'web_biblename', self.BibleComboBox)
self.setField(u'proxy_server', 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.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.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_version', self.VersionNameEdit)
self.setField(u'license_copyright', self.CopyrightEdit) self.setField(u'license_copyright', self.CopyrightEdit)
self.setField(u'license_permission', self.PermissionEdit) self.setField(u'license_permission', self.PermissionEdit)
self.onLocationComboBoxChanged(0) self.onLocationComboBoxChanged(DownloadLocation.Crosswalk)
def loadWebBibles(self): def loadWebBibles(self):
""" """
@ -267,29 +266,33 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
fbibles = None fbibles = None
try: try:
self.web_bible_list[DownloadLocation.Crosswalk] = {} self.web_bible_list[DownloadLocation.Crosswalk] = {}
fbibles = open(os.path.join(filepath, u'crosswalkbooks.csv'), 'r') books_file = open(os.path.join(filepath, u'crosswalkbooks.csv'), 'r')
for line in fbibles: dialect = csv.Sniffer().sniff(books_file.read(1024))
parts = line.split(u',') books_file.seek(0)
self.web_bible_list[DownloadLocation.Crosswalk][parts[0]] = \ books_reader = csv.reader(books_file, dialect)
parts[1].rstrip() for line in books_reader:
self.web_bible_list[DownloadLocation.Crosswalk][line[0]] = \
unicode(line[1], u'utf-8').strip()
except: except:
log.exception(u'Crosswalk resources missing') log.exception(u'Crosswalk resources missing')
finally: finally:
if fbibles: if books_file:
fbibles.close() books_file.close()
#Load and store BibleGateway Bibles #Load and store BibleGateway Bibles
try: try:
self.web_bible_list[DownloadLocation.BibleGateway] = {} self.web_bible_list[DownloadLocation.BibleGateway] = {}
fbibles = open(os.path.join(filepath, u'biblegateway.csv'), 'r') books_file = open(os.path.join(filepath, u'biblegateway.csv'), 'r')
for line in fbibles: dialect = csv.Sniffer().sniff(books_file.read(1024))
parts = line.split(u',') books_file.seek(0)
self.web_bible_list[DownloadLocation.BibleGateway][parts[0]] = \ books_reader = csv.reader(books_file, dialect)
parts[1].rstrip() for line in books_reader:
self.web_bible_list[DownloadLocation.BibleGateway][line[0]] = \
unicode(line[1], u'utf-8').strip()
except: except:
log.exception(u'Biblegateway resources missing') log.exception(u'Biblegateway resources missing')
finally: finally:
if fbibles: if books_file:
fbibles.close() books_file.close()
def getFileName(self, title, editbox): def getFileName(self, title, editbox):
filename = QtGui.QFileDialog.getOpenFileName(self, title, filename = QtGui.QFileDialog.getOpenFileName(self, title,
@ -317,22 +320,22 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
success = False success = False
if bible_type == BibleFormat.OSIS: if bible_type == BibleFormat.OSIS:
# Import an OSIS bible # Import an OSIS bible
success = self.biblemanager.register_osis_file_bible( success = self.manager.import_bible(BibleFormat.OSIS,
unicode(self.field(u'license_version').toString()), name=unicode(self.field(u'license_version').toString()),
unicode(self.field(u'osis_location').toString()) filename=unicode(self.field(u'osis_location').toString())
) )
elif bible_type == BibleFormat.CSV: elif bible_type == BibleFormat.CSV:
# Import a CSV bible # Import a CSV bible
success = self.biblemanager.register_csv_file_bible( success = self.manager.import_bible(BibleFormat.CSV,
unicode(self.field(u'license_version').toString()), name=unicode(self.field(u'license_version').toString()),
self.field(u'csv_booksfile').toString(), booksfile=self.field(u'csv_booksfile').toString(),
self.field(u'csv_versefile').toString() versefile=self.field(u'csv_versefile').toString()
) )
elif bible_type == BibleFormat.OpenSong: elif bible_type == BibleFormat.OpenSong:
# Import an OpenSong bible # Import an OpenSong bible
success = self.biblemanager.register_opensong_bible( success = self.manager.import_bible(BibleFormat.OpenSong,
unicode(self.field(u'license_version').toString()), name=unicode(self.field(u'license_version').toString()),
self.field(u'opensong_file').toString() filename=self.field(u'opensong_file').toString()
) )
elif bible_type == BibleFormat.WebDownload: elif bible_type == BibleFormat.WebDownload:
# Import a bible from the web # Import a bible from the web
@ -344,21 +347,22 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
elif download_location == DownloadLocation.BibleGateway: elif download_location == DownloadLocation.BibleGateway:
bible = self.web_bible_list[DownloadLocation.BibleGateway][ bible = self.web_bible_list[DownloadLocation.BibleGateway][
unicode(self.BibleComboBox.currentText())] unicode(self.BibleComboBox.currentText())]
success = self.biblemanager.register_http_bible( success = self.manager.import_bible(BibleFormat.WebDownload,
unicode(self.field(u'license_version').toString()), name=unicode(self.field(u'license_version').toString()),
unicode(DownloadLocation.get_name(download_location)), download_source=unicode(DownloadLocation.get_name(download_location)),
unicode(bible), download_name=unicode(bible),
unicode(self.field(u'proxy_server').toString()), proxy_server=unicode(self.field(u'proxy_server').toString()),
unicode(self.field(u'proxy_username').toString()), proxy_username=unicode(self.field(u'proxy_username').toString()),
unicode(self.field(u'proxy_password').toString()) proxy_password=unicode(self.field(u'proxy_password').toString())
) )
if success: 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_version').toString()), unicode(self.field(u'license_version').toString()),
unicode(self.field(u'license_copyright').toString()), unicode(self.field(u'license_copyright').toString()),
unicode(self.field(u'license_permission').toString()) unicode(self.field(u'license_permission').toString())
) )
self.manager.reload_bibles()
self.ImportProgressLabel.setText(self.trUtf8('Finished import.')) self.ImportProgressLabel.setText(self.trUtf8('Finished import.'))
else: else:
self.ImportProgressLabel.setText( self.ImportProgressLabel.setText(

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 urllib2
import chardet import chardet
import logging 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. Encapsulate a set of search results. This is Bible-type independant.
""" """
@ -81,12 +171,6 @@ class BibleCommon(object):
log = logging.getLogger(u'BibleCommon') log = logging.getLogger(u'BibleCommon')
log.info(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): def _get_web_text(self, urlstring, proxyurl):
""" """
Get the HTML from the web page. Get the HTML from the web page.

View File

@ -25,96 +25,97 @@
import logging import logging
import chardet import chardet
import csv
from openlp.plugins.bibles.lib.common import BibleCommon
from openlp.core.lib import Receiver from openlp.core.lib import Receiver
from db import BibleDB
class BibleCSVImpl(BibleCommon): log = logging.getLogger(__name__)
global log
log = logging.getLogger(u'BibleCSVImpl') class CSVBible(BibleDB):
log.info(u'BibleCVSImpl loaded') """
def __init__(self, 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 Loads a Bible from a pair of CVS files passed in
This class assumes the files contain all the information and This class assumes the files contain all the information and
a clean bible is being loaded. a clean bible is being loaded.
""" """
self.bibledb = bibledb BibleDB.__init__(self, parent, **kwargs)
self.loadbible = True log.info(self.__class__.__name__)
QtCore.QObject.connect(Receiver.get_receiver(), if u'booksfile' not in kwargs:
QtCore.SIGNAL(u'openlpstopimport'), self.stop_import) 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): 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 #Populate the Tables
success = True success = True
fbooks = None books_file = None
try: try:
fbooks = open(booksfile, 'r') books_file = open(self.booksfile, 'r')
count = 0 dialect = csv.Sniffer().sniff(books_file.read(1024))
for line in fbooks: books_file.seek(0)
books_reader = csv.reader(books_file, dialect)
for line in books_reader:
# cancel pressed # cancel pressed
if not self.loadbible: if self.stop_import:
break break
details = chardet.detect(line) details = chardet.detect(line[1])
line = unicode(line, details['encoding']) self.create_book(unicode(line[1], details['encoding']),
p = line.split(u',') line[2], int(line[0]))
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') Receiver.send_message(u'process_events')
count = 0
except: except:
log.exception(u'Loading books from file failed') log.exception(u'Loading books from file failed')
success = False success = False
finally: finally:
if fbooks: if books_file:
fbooks.close() books_file.close()
if not success: if not success:
return False return False
fverse = None verse_file = None
try: try:
fverse = open(versesfile, 'r')
count = 0
book_ptr = None book_ptr = None
for line in fverse: verse_file = open(versesfile, 'r')
if not self.loadbible: # cancel pressed 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 break
details = chardet.detect(line) details = chardet.detect(line[3])
line = unicode(line, details['encoding']) if book_ptr != line[0]:
# split into 3 units and leave the rest as a single field book = self.get_book(line[0])
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)
book_ptr = book.name book_ptr = book.name
# increament the progress bar self.wizard.incrementProgressBar(
dialogobject.incrementProgressBar(u'Importing %s %s' % \ u'Importing %s %s' % (book.name, line[1]))
book.name) self.commit()
self.bibledb.add_verse(book.id, p[1], p[2], p3) self.create_verse(book.id, line[1], line[2],
count += 1 unicode(line[3], details['encoding']))
#Every x verses repaint the screen
if count % 3 == 0:
Receiver.send_message(u'process_events') Receiver.send_message(u'process_events')
count = 0 self.commit()
self.bibledb.save_verses()
except: except:
log.exception(u'Loading verses from file failed') log.exception(u'Loading verses from file failed')
success = False success = False
finally: finally:
if fverse: if verse_file:
fverse.close() verse_file.close()
if not self.loadbible: if self.stop_import:
dialogobject.incrementProgressBar(u'Import canceled!') self.wizard.incrementProgressBar(u'Import canceled!')
dialogobject.ImportProgressBar.setValue(
dialogobject.ImportProgressBar.maximum())
return False return False
else: 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 logging
import os import os
import csv
from bibleOpenSongimpl import BibleOpenSongImpl from common import parse_reference
from bibleOSISimpl import BibleOSISImpl from opensong import OpenSongBible
from bibleCSVimpl import BibleCSVImpl from osis import OSISBible
from bibleDBimpl import BibleDBImpl from csvbible import CSVBible
from bibleHTTPimpl import BibleHTTPImpl from db import BibleDB
from http import HTTPBible
class BibleMode(object): 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 Full = 1
Partial = 2 Partial = 2
class BibleFormat(object): 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 Unknown = -1
OSIS = 0 OSIS = 0
CSV = 1 CSV = 1
OpenSong = 2 OpenSong = 2
WebDownload = 3 WebDownload = 3
@classmethod @staticmethod
def get_handler(class_, id): def get_class(id):
if id == class_.OSIS: """
return BibleOSISImpl Return the appropriate imeplementation class.
elif id == class_.CSV: """
return BibleCSVImpl if id == BibleFormat.OSIS:
elif id == class_.OpenSong: return OSISBible
return BibleOpenSongImpl elif id == BibleFormat.CSV:
elif id == class_.WebDownload: return CSVBible
return BibleHTTPImpl elif id == BibleFormat.OpenSong:
return OpenSongBible
elif id == BibleFormat.WebDownload:
return HTTPBible
else: else:
return None return None
@staticmethod
def list():
return [
BibleFormat.OSIS,
BibleFormat.CSV,
BibleFormat.OpenSong,
BibleFormat.WebDownload
]
class BibleManager(object): class BibleManager(object):
""" """
@ -66,300 +90,139 @@ class BibleManager(object):
log = logging.getLogger(u'BibleManager') log = logging.getLogger(u'BibleManager')
log.info(u'Bible manager loaded') 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 Finds all the bibles defined for the system and creates an interface
interface object for each bible containing connection object for each bible containing connection information. Throws
information. Throws Exception if no Bibles are found. Exception if no Bibles are found.
Init confirms the bible exists and stores the database path. Init confirms the bible exists and stores the database path.
``config`` ``config``
The plugin's configuration object. The plugin's configuration object.
""" """
self.config = config
log.debug(u'Bible Initialising') log.debug(u'Bible Initialising')
self.config = config
self.parent = parent
self.web = u'Web' self.web = u'Web'
# dict of bible database objects self.db_cache = None
self.bible_db_cache = None self.path = self.config.get_data_path()
# dict of bible http readers self.proxy_name = self.config.get_config(u'proxy name')
self.bible_http_cache = None self.suffix = u'sqlite'
self.biblePath = self.config.get_data_path() self.import_wizard = None
#get proxy name for screen
self.proxyname = self.config.get_config(u'proxy name')
self.bibleSuffix = u'sqlite'
self.dialogobject = None
self.reload_bibles() self.reload_bibles()
self.media = None self.media = None
def reload_bibles(self): 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') 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) log.debug(u'Bible Files %s', files)
self.bible_db_cache = {} self.db_cache = {}
self.bible_http_cache = {} for filename in files:
# books of the bible with testaments name, extension = os.path.splitext(filename)
self.book_testaments = {} self.db_cache[name] = BibleDB(self.parent, path=self.path, name=name, config=self.config)
# 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)
# look to see if lazy load bible exists and get create getter. # look to see if lazy load bible exists and get create getter.
biblesource = self.bible_db_cache[bname].get_meta(u'WEB') source = self.db_cache[name].get_meta(u'download source')
if biblesource: if source:
self.web_bibles_present = True download_name = self.db_cache[name].get_meta(u'download name').value
nhttp = BibleHTTPImpl() meta_proxy = self.db_cache[name].get_meta(u'proxy url')
# tell The Server where to get the verses from. web_bible = HTTPBible(self.parent, path=self.path, name=name,
nhttp.set_bible_source(biblesource.value) config=self.config, download_source=source.value,
self.bible_http_cache [bname] = nhttp download_name=download_name)
# look to see if lazy load bible exists and get create getter. if meta_proxy:
meta = self.bible_db_cache[bname].get_meta(u'proxy') web_bible.set_proxy_server(meta_proxy.value)
proxy = None #del self.db_cache[name]
if meta: self.db_cache[name] = web_bible
proxy = meta.value log.debug(u'Bibles reloaded')
# 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')
def set_process_dialog(self, dialogobject): def set_process_dialog(self, wizard):
""" """
Sets the reference to the dialog with the progress bar on it. Sets the reference to the dialog with the progress bar on it.
``dialogobject`` ``dialog``
The reference to the dialog. The reference to the import wizard.
""" """
self.dialogobject = dialogobject self.import_wizard = wizard
def import_bible(self, type, **kwargs): def import_bible(self, type, **kwargs):
""" """
Register a bible in the bible cache, and then import the verses. Register a bible in the bible cache, and then import the verses.
``type`` ``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, def get_bibles(self):
proxyurl=None, proxyid=None, proxypass=None):
""" """
Return a list of bibles from a given URL. The selected Bible Returns a list of the names of available Bibles.
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.
""" """
log.debug(u'get_bibles') log.debug(u'get_bibles')
bible_list = [] return [name for name, bible in self.db_cache.iteritems()]
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
def is_bible_web(self, bible): def get_books(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):
""" """
Returns a list of the books of the bible Returns a list of Bible books, and the number of chapters in that book.
"""
log.debug(u'get_bible_books')
return self.book_chapters
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 Returns the number of Chapters for a given book
""" """
log.debug(u'get_book_chapter_count %s', 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 Returns all the number of verses for a given
book and chapterMaxBibleBookVerses book and chapterMaxBibleBookVerses
""" """
log.debug(u'get_book_verse_count %s,%s,%s', bible, book, chapter) log.debug(u'BibleManager.get_verse_count("%s", "%s", %s)', bible, book, chapter)
web, bible = self.is_bible_web(bible) return self.db_cache[bible].get_verse_count(book, chapter)
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)
def get_verse_from_text(self, bible, versetext): def get_verses(self, bible, versetext):
""" """
Returns all the number of verses for a given Parses a scripture reference, fetches the verses from the Bible
book and chapterMaxBibleBookVerses 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) log.debug(u'BibleManager.get_verses("%s", "%s")', bible, versetext)
web, bible = self.is_bible_web(bible) reflist = parse_reference(versetext)
return self.bible_db_cache[bible].get_verses_from_text(versetext) return self.db_cache[bible].get_verses(reflist)
def save_meta_data(self, bible, version, copyright, permissions): 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', log.debug(u'save_meta data %s,%s, %s,%s',
bible, version, copyright, permissions) bible, version, copyright, permissions)
self.bible_db_cache[bible].save_meta(u'Version', version) self.db_cache[bible].create_meta(u'Version', version)
self.bible_db_cache[bible].save_meta(u'Copyright', copyright) self.db_cache[bible].create_meta(u'Copyright', copyright)
self.bible_db_cache[bible].save_meta(u'Permissions', permissions) self.db_cache[bible].create_meta(u'Permissions', permissions)
def get_meta_data(self, bible, key): def get_meta_data(self, bible, key):
""" """
Returns the meta data for a given key Returns the meta data for a given key
""" """
log.debug(u'get_meta %s,%s', bible, key) log.debug(u'get_meta %s,%s', bible, key)
web, bible = self.is_bible_web(bible) return self.db_cache[bible].get_meta(key)
return self.bible_db_cache[bible].get_meta(key)
def get_verse_text(self, bible, bookname, schapter, echapter, sverse, def exists(self, name):
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):
""" """
Check cache to see if new bible 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) log.debug(u'Bible from cache in is_new_bible %s', bible)
if not isinstance(bible, unicode):
bible = unicode(bible)
if bible == name: 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 BaseListWithDnD
from openlp.plugins.bibles.forms import ImportWizardForm from openlp.plugins.bibles.forms import ImportWizardForm
from openlp.plugins.bibles.lib.manager import BibleMode from openlp.plugins.bibles.lib.manager import BibleMode
from openlp.plugins.bibles.lib.common import parse_reference
class BibleListView(BaseListWithDnD): class BibleListView(BaseListWithDnD):
"""
Drag and drop capable list for Bibles.
"""
def __init__(self, parent=None): def __init__(self, parent=None):
self.PluginName = u'Bibles' self.PluginName = u'Bibles'
BaseListWithDnD.__init__(self, parent) BaseListWithDnD.__init__(self, parent)
def resizeEvent(self, event):
self.parent.onListViewResize(event.size().width(), event.size().width())
class BibleMediaItem(MediaManagerItem): class BibleMediaItem(MediaManagerItem):
""" """
This is the custom media manager item for Bibles. This is the custom media manager item for Bibles.
@ -52,6 +60,7 @@ class BibleMediaItem(MediaManagerItem):
self.IconPath = u'songs/song' self.IconPath = u'songs/song'
self.ListViewWithDnD_class = BibleListView self.ListViewWithDnD_class = BibleListView
self.servicePath = None self.servicePath = None
self.lastReference = []
MediaManagerItem.__init__(self, parent, icon, title) MediaManagerItem.__init__(self, parent, icon, title)
# place to store the search results # place to store the search results
self.search_results = {} self.search_results = {}
@ -237,6 +246,24 @@ class BibleMediaItem(MediaManagerItem):
QtCore.SIGNAL(u'pressed()'), self.onQuickSearchButton) QtCore.SIGNAL(u'pressed()'), self.onQuickSearchButton)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'config_updated'), self.configUpdated) 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): def configUpdated(self):
if str_to_bool( if str_to_bool(
@ -277,7 +304,7 @@ class BibleMediaItem(MediaManagerItem):
def initialise(self): def initialise(self):
log.debug(u'bible manager initialise') log.debug(u'bible manager initialise')
self.parent.biblemanager.media = self self.parent.manager.media = self
self.loadBibles() self.loadBibles()
self.configUpdated() self.configUpdated()
log.debug(u'bible manager initialise complete') log.debug(u'bible manager initialise complete')
@ -297,23 +324,40 @@ class BibleMediaItem(MediaManagerItem):
self.AdvancedSecondBibleComboBox.clear() self.AdvancedSecondBibleComboBox.clear()
self.QuickSecondBibleComboBox.addItem(u'') self.QuickSecondBibleComboBox.addItem(u'')
self.AdvancedSecondBibleComboBox.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 # load bibles into the combo boxes
first = True
for bible in bibles: for bible in bibles:
self.QuickVersionComboBox.addItem(bible) self.QuickVersionComboBox.addItem(bible)
self.QuickSecondBibleComboBox.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.AdvancedVersionComboBox.addItem(bible)
self.AdvancedSecondBibleComboBox.addItem(bible) self.AdvancedSecondBibleComboBox.addItem(bible)
if first: if first:
first = False first = False
# use the first bible as the trigger
self.initialiseBible(bible) 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): def onAdvancedVersionComboBox(self):
self.initialiseBible( self.initialiseBible(
unicode(self.AdvancedVersionComboBox.currentText())) unicode(self.AdvancedVersionComboBox.currentText()))
@ -326,11 +370,8 @@ class BibleMediaItem(MediaManagerItem):
self.AdvancedBookComboBox.itemData(item).toInt()[0]) self.AdvancedBookComboBox.itemData(item).toInt()[0])
def onNewClick(self): def onNewClick(self):
#self.bibleimportform = BibleImportForm(
# self.parent.config, self.parent.biblemanager, self)
#self.bibleimportform.exec_()
self.bibleimportform = ImportWizardForm(self, self.parent.config, self.bibleimportform = ImportWizardForm(self, self.parent.config,
self.parent.biblemanager, self.parent) self.parent.manager, self.parent)
self.bibleimportform.exec_() self.bibleimportform.exec_()
self.reloadBibles() self.reloadBibles()
@ -339,14 +380,13 @@ class BibleMediaItem(MediaManagerItem):
self.adjustComboBox(frm, self.verses, self.AdvancedToVerse) self.adjustComboBox(frm, self.verses, self.AdvancedToVerse)
def onAdvancedToChapter(self): def onAdvancedToChapter(self):
text1 = unicode(self.AdvancedFromChapter.currentText()) frm = unicode(self.AdvancedFromChapter.currentText())
text2 = unicode(self.AdvancedToChapter.currentText()) to = unicode(self.AdvancedToChapter.currentText())
if text1 != text2: if frm != to:
bible = unicode(self.AdvancedVersionComboBox.currentText()) bible = unicode(self.AdvancedVersionComboBox.currentText())
book = unicode(self.AdvancedBookComboBox.currentText()) book = unicode(self.AdvancedBookComboBox.currentText())
# get the verse count for new chapter # get the verse count for new chapter
verses = self.parent.biblemanager.get_book_verse_count( verses = self.parent.manager.get_verse_count(bible, book, int(to))
bible, book, int(text2))
self.adjustComboBox(1, verses, self.AdvancedToVerse) self.adjustComboBox(1, verses, self.AdvancedToVerse)
def onAdvancedSearchButton(self): def onAdvancedSearchButton(self):
@ -357,10 +397,13 @@ class BibleMediaItem(MediaManagerItem):
chapter_to = int(self.AdvancedToChapter.currentText()) chapter_to = int(self.AdvancedToChapter.currentText())
verse_from = int(self.AdvancedFromVerse.currentText()) verse_from = int(self.AdvancedFromVerse.currentText())
verse_to = int(self.AdvancedToVerse.currentText()) verse_to = int(self.AdvancedToVerse.currentText())
self.search_results = self.parent.biblemanager.get_verse_text( versetext = u'%s %s:%s-%s:%s' % (book, chapter_from, verse_from, \
bible, book, chapter_from, chapter_to, verse_from, verse_to) chapter_to, verse_to)
self.search_results = self.parent.manager.get_verses(bible, versetext)
if self.ClearAdvancedSearchComboBox.currentIndex() == 0: if self.ClearAdvancedSearchComboBox.currentIndex() == 0:
self.ListView.clear() self.ListView.clear()
self.lastReference = []
self.lastReference.append(versetext)
self.displayResults(bible) self.displayResults(bible)
def onAdvancedFromChapter(self): def onAdvancedFromChapter(self):
@ -369,7 +412,7 @@ class BibleMediaItem(MediaManagerItem):
cf = int(self.AdvancedFromChapter.currentText()) cf = int(self.AdvancedFromChapter.currentText())
self.adjustComboBox(cf, self.chapters_from, self.AdvancedToChapter) self.adjustComboBox(cf, self.chapters_from, self.AdvancedToChapter)
# get the verse count for new chapter # 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.AdvancedFromVerse)
self.adjustComboBox(1, vse, self.AdvancedToVerse) self.adjustComboBox(1, vse, self.AdvancedToVerse)
@ -379,11 +422,9 @@ class BibleMediaItem(MediaManagerItem):
text = unicode(self.QuickSearchEdit.displayText()) text = unicode(self.QuickSearchEdit.displayText())
if self.ClearQuickSearchComboBox.currentIndex() == 0: if self.ClearQuickSearchComboBox.currentIndex() == 0:
self.ListView.clear() self.ListView.clear()
if self.QuickSearchComboBox.currentIndex() == 1: self.lastReference = []
self.search_results = self.parent.biblemanager.get_verse_from_text( self.lastReference.append(text)
bible, text) self.search_results = self.parent.manager.get_verses(bible, text)
else:
self.searchByReference(bible, text)
if self.search_results: if self.search_results:
self.displayResults(bible) self.displayResults(bible)
@ -396,60 +437,63 @@ class BibleMediaItem(MediaManagerItem):
raw_slides = [] raw_slides = []
raw_footer = [] raw_footer = []
bible_text = u'' bible_text = u''
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
if self.parent.settings_tab.display_style == 1:
loc = 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'}')
elif self.parent.settings_tab.display_style == 3:
loc = self.formatVerse(old_chapter, chapter, verse, u'[', u']')
else:
loc = self.formatVerse(old_chapter, chapter, verse, u'', u'')
old_chapter = chapter
footer = u'%s (%s %s)' % (book, self.version, self.copyright)
#If not found throws and error so add.s
try:
raw_footer.index(footer)
except:
raw_footer.append(footer)
#If we want to use a 2nd translation / version #If we want to use a 2nd translation / version
bible2 = u'' bible2 = u''
if self.SearchTabWidget.currentIndex() == 0: if self.SearchTabWidget.currentIndex() == 0:
bible2 = unicode(self.QuickSecondBibleComboBox.currentText()) bible2 = unicode(self.QuickSecondBibleComboBox.currentText())
else: else:
bible2 = unicode(self.AdvancedSecondBibleComboBox.currentText()) bible2 = unicode(self.AdvancedSecondBibleComboBox.currentText())
if len(bible2) > 0: if bible2:
self.searchByReference(bible2, search_verse) bible2_verses = []
footer = u'%s (%s %s)' % (book, self.version, self.copyright) 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())
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:
verse_text = self.formatVerse(old_chapter, chapter, verse, u'(u', u')')
elif self.parent.settings_tab.display_style == 2:
verse_text = self.formatVerse(old_chapter, chapter, verse, u'{', u'}')
elif self.parent.settings_tab.display_style == 3:
verse_text = self.formatVerse(old_chapter, chapter, verse, u'[', u']')
else:
verse_text = self.formatVerse(old_chapter, chapter, verse, u'', u'')
old_chapter = chapter
footer = u'%s (%s %s)' % (book, version, copyright)
#If not found throws and error so add.s #If not found throws and error so add.s
try: if footer not in raw_footer:
raw_footer.index(footer)
except:
raw_footer.append(footer) raw_footer.append(footer)
bible_text = u'%s %s \n\n\n %s %s)' % \ if bible2:
(loc, text, loc, self.search_results[0].text) footer = u'%s (%s %s)' % (book, version, copyright)
#If not found throws and error so add.s
if footer not in raw_footer:
raw_footer.append(footer)
bible_text = u'%s %s \n\n %s %s' % \
(verse_text, text, verse_text, bible2_verses[item.row()].text)
raw_slides.append(bible_text) raw_slides.append(bible_text)
bible_text = u'' bible_text = u''
else: else:
#Paragraph style force new line per verse #Paragraph style force new line per verse
if self.parent.settings_tab.layout_style == 1: if self.parent.settings_tab.layout_style == 1:
text = text + u'\n\n' 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 we are verse per slide then create slide
if self.parent.settings_tab.layout_style == 0: if self.parent.settings_tab.layout_style == 0:
raw_slides.append(bible_text) raw_slides.append(bible_text)
bible_text = u'' 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: if len(self.parent.settings_tab.bible_theme) == 0:
service_item.theme = None service_item.theme = None
else: else:
@ -463,40 +507,39 @@ class BibleMediaItem(MediaManagerItem):
return True return True
def formatVerse(self, old_chapter, chapter, verse, opening, closing): def formatVerse(self, old_chapter, chapter, verse, opening, closing):
loc = opening verse_text = opening
if old_chapter != chapter: if old_chapter != chapter:
loc += chapter + u':' verse_text += chapter + u':'
elif not self.parent.settings_tab.show_new_chapters: elif not self.parent.settings_tab.show_new_chapters:
loc += chapter + u':' verse_text += chapter + u':'
loc += verse verse_text += verse
loc += closing verse_text += closing
return loc return verse_text
def reloadBibles(self): def reloadBibles(self):
log.debug(u'Reloading Bibles') log.debug(u'Reloading Bibles')
self.parent.biblemanager.reload_bibles() self.parent.manager.reload_bibles()
self.loadBibles() self.loadBibles()
def initialiseBible(self, bible): def initialiseBible(self, bible):
log.debug(u'initialiseBible %s', 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() self.AdvancedBookComboBox.clear()
first = True first = True
for book in book_data: for book in book_data:
row = self.AdvancedBookComboBox.count() row = self.AdvancedBookComboBox.count()
self.AdvancedBookComboBox.addItem(book[u'book']) self.AdvancedBookComboBox.addItem(book[u'name'])
self.AdvancedBookComboBox.setItemData( self.AdvancedBookComboBox.setItemData(
row, QtCore.QVariant(book[u'total'])) row, QtCore.QVariant(book[u'chapters']))
if first: if first:
first = False first = False
self.initialiseChapterVerse( self.initialiseChapterVerse(
bible, book[u'book'], book[u'total']) bible, book[u'name'], book[u'chapters'])
def initialiseChapterVerse(self, bible, book, chapters): def initialiseChapterVerse(self, bible, book, chapters):
log.debug(u'initialiseChapterVerse %s, %s', bible, book) log.debug(u'initialiseChapterVerse %s, %s', bible, book)
self.chapters_from = chapters self.chapters_from = chapters
self.verses = self.parent.biblemanager.get_book_verse_count(bible, self.verses = self.parent.manager.get_verse_count(bible, book, 1)
book, 1)
if self.verses == 0: if self.verses == 0:
self.AdvancedSearchButton.setEnabled(False) self.AdvancedSearchButton.setEnabled(False)
self.AdvancedMessage.setText(self.trUtf8('Bible not fully loaded')) self.AdvancedMessage.setText(self.trUtf8('Bible not fully loaded'))
@ -515,12 +558,30 @@ class BibleMediaItem(MediaManagerItem):
combo.addItem(unicode(i)) combo.addItem(unicode(i))
def displayResults(self, bible): 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): for count, verse in enumerate(self.search_results):
bible_text = u' %s %d:%d (%s)' % (verse.book.name, bible_text = u' %s %d:%d (%s)' % \
verse.chapter, verse.verse, bible) (verse.book.name, verse.chapter, verse.verse, bible)
bible_verse = QtGui.QListWidgetItem(bible_text) bible_verse = QtGui.QListWidgetItem(bible_text)
bible_verse.setData(QtCore.Qt.UserRole, #bible_verse.setData(QtCore.Qt.UserRole,
QtCore.QVariant(bible_text)) # 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) self.ListView.addItem(bible_verse)
row = self.ListView.setCurrentRow(count) row = self.ListView.setCurrentRow(count)
if row: if row:
@ -528,85 +589,4 @@ class BibleMediaItem(MediaManagerItem):
def searchByReference(self, bible, search): def searchByReference(self, bible, search):
log.debug(u'searchByReference %s, %s', bible, search) log.debug(u'searchByReference %s, %s', bible, search)
book = u'' self.search_results = self.parent.manager.get_verses(bible, search)
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)

View File

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

View File

@ -33,94 +33,81 @@ from lxml import objectify
from PyQt4 import QtCore from PyQt4 import QtCore
from openlp.core.lib import Receiver from openlp.core.lib import Receiver
from db import BibleDB
class BibleOpenSongImpl():
"""
OSIS Bible format importer class.
"""
global log
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
log.info(u'BibleOpenSongImpl loaded')
def __init__(self, biblepath, bibledb): class OpenSongBible(BibleDB):
""" """
Constructor to create and set up an instance of the OpenSong Bible format importer class.
BibleOpenSongImpl class.
``biblepath``
This does not seem to be used.
``bibledb``
A reference to a Bible database object.
""" """
log.info(u'BibleOpenSongImpl Initialising')
self.bibledb = bibledb def __init__(self, parent, **kwargs):
self.loadbible = True """
QtCore.QObject.connect(Receiver.get_receiver(), Constructor to create and set up an instance of the OpenSongBible
QtCore.SIGNAL(u'openlpstopimport'), self.stop_import) class. This class is used to import Bibles from OpenSong's XML format.
"""
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): def stop_import(self):
""" """
Stops the import of the Bible. 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. 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) log.debug(u'Starting OpenSong import from "%s"' % self.filename)
bible_file = unicode(bible_file) self.filename = unicode(self.filename, u'utf-8')
detect_file = None self.wizard.incrementProgressBar(u'Preparing for import...')
try: file = None
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
success = True success = True
try: try:
opensong_bible = codecs.open(bible_file, u'r', details['encoding']) # NOTE: We don't need to do any of the normal encoding detection
opensong = objectify.parse(opensong_bible) # 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() bible = opensong.getroot()
for book in bible.b: for book in bible.b:
if not self.loadbible: if self.stop_import:
break break
dbbook = self.bibledb.create_book(book.attrib[u'n'], db_book = self.create_book(unicode(book.attrib[u'n']),
book.attrib[u'n'][:4]) unicode(book.attrib[u'n'][:4]))
for chapter in book.c: for chapter in book.c:
if not self.loadbible: if self.stop_import:
break break
for verse in chapter.v: for verse in chapter.v:
if not self.loadbible: if self.stop_import:
break break
self.bibledb.add_verse(dbbook.id, chapter.attrib[u'n'], self.create_verse(
verse.attrib[u'n'], verse.text) db_book.id,
int(chapter.attrib[u'n']),
int(verse.attrib[u'n']),
unicode(verse.text)
)
Receiver.send_message(u'process_events') Receiver.send_message(u'process_events')
dialogobject.incrementProgressBar(u'Importing %s %s' % \ self.wizard.incrementProgressBar(
(dbbook.name, str(chapter.attrib[u'n']))) QtCore.QString('%s %s %s' % (self.trUtf8('Importing'),\
self.bibledb.save_verses() db_book.name, chapter.attrib[u'n'])))
self.commit()
except: except:
log.exception(u'Loading bible from OpenSong file failed') log.exception(u'Loading bible from OpenSong file failed')
success = False success = False
finally: finally:
if opensong_bible: if file:
opensong_bible.close() file.close()
if not self.loadbible: if self.stop_import:
dialogobject.incrementProgressBar(u'Import canceled!') self.wizard.incrementProgressBar(u'Import canceled!')
dialogobject.ImportProgressBar.setValue(
dialogobject.ImportProgressBar.maximum())
return False return False
else: else:
return success return success

View File

@ -33,8 +33,9 @@ import re
from PyQt4 import QtCore from PyQt4 import QtCore
from openlp.core.lib import Receiver from openlp.core.lib import Receiver
from db import BibleDB
class BibleOSISImpl(): class OSISBible(BibleDB):
""" """
OSIS Bible format importer class. OSIS Bible format importer class.
""" """
@ -42,18 +43,16 @@ class BibleOSISImpl():
log = logging.getLogger(u'BibleOSISImpl') log = logging.getLogger(u'BibleOSISImpl')
log.info(u'BibleOSISImpl loaded') 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 Constructor to create and set up an instance of the OpenSongBible
BibleOSISImpl class. class. This class is used to import Bibles from OpenSong's XML format.
``biblepath``
This does not seem to be used.
``bibledb``
A reference to a Bible database object.
""" """
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( self.verse_regex = re.compile(
r'<verse osisID="([a-zA-Z0-9 ]*).([0-9]*).([0-9]*)">(.*?)</verse>') r'<verse osisID="([a-zA-Z0-9 ]*).([0-9]*).([0-9]*)">(.*?)</verse>')
self.note_regex = re.compile(r'<note(.*?)>(.*?)</note>') self.note_regex = re.compile(r'<note(.*?)>(.*?)</note>')
@ -66,13 +65,11 @@ class BibleOSISImpl():
self.w_regex = re.compile(r'<w (.*?)>') self.w_regex = re.compile(r'<w (.*?)>')
self.q_regex = re.compile(r'<q (.*?)>') self.q_regex = re.compile(r'<q (.*?)>')
self.spaces_regex = re.compile(r'([ ]{2,})') self.spaces_regex = re.compile(r'([ ]{2,})')
self.bibledb = bibledb
self.books = {} self.books = {}
filepath = os.path.split(os.path.abspath(__file__))[0] filepath = os.path.split(os.path.abspath(__file__))[0]
filepath = os.path.abspath(os.path.join( filepath = os.path.abspath(os.path.join(
filepath, u'..', u'resources', u'osisbooks.csv')) filepath, u'..', u'resources', u'osisbooks.csv'))
fbibles = None fbibles = None
self.loadbible = True
try: try:
fbibles = open(filepath, u'r') fbibles = open(filepath, u'r')
for line in fbibles: for line in fbibles:
@ -84,31 +81,24 @@ class BibleOSISImpl():
finally: finally:
if fbibles: if fbibles:
fbibles.close() fbibles.close()
QtCore.QObject.connect(Receiver.get_receiver(), #QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'openlpstopimport'), self.stop_import) # QtCore.SIGNAL(u'openlpstopimport'), self.stop_import)
def stop_import(self): def stop_import(self):
""" """
Stops the import of the Bible. Stops the import of the Bible.
""" """
log.debug('Stopping import!') 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. 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 detect_file = None
try: try:
detect_file = open(osisfile_record, u'r') detect_file = open(self.filename, u'r')
details = chardet.detect(detect_file.read(3000)) details = chardet.detect(detect_file.read(3000))
except: except:
log.exception(u'Failed to detect OSIS file encoding') log.exception(u'Failed to detect OSIS file encoding')
@ -119,12 +109,12 @@ class BibleOSISImpl():
osis = None osis = None
success = True success = True
try: try:
osis = codecs.open(osisfile_record, u'r', details['encoding']) osis = codecs.open(self.filename, u'r', details['encoding'])
last_chapter = 0 last_chapter = 0
testament = 1 testament = 1
db_book = None db_book = None
for file_record in osis: for file_record in osis:
if not self.loadbible: if self.stop_import:
break break
match = self.verse_regex.search(file_record) match = self.verse_regex.search(file_record)
if match: if match:
@ -142,13 +132,13 @@ class BibleOSISImpl():
testament) testament)
if last_chapter == 0: if last_chapter == 0:
if book == u'Gen': if book == u'Gen':
dialogobject.ImportProgressBar.setMaximum(1188) self.wizard.ImportProgressBar.setMaximum(1188)
else: else:
dialogobject.ImportProgressBar.setMaximum(260) self.wizard.ImportProgressBar.setMaximum(260)
if last_chapter != chapter: if last_chapter != chapter:
if last_chapter != 0: if last_chapter != 0:
self.bibledb.save_verses() self.bibledb.save_verses()
dialogobject.incrementProgressBar( self.wizard.incrementProgressBar(
u'Importing %s %s...' % \ u'Importing %s %s...' % \
(self.books[match.group(1)][0], chapter)) (self.books[match.group(1)][0], chapter))
last_chapter = chapter last_chapter = chapter
@ -170,20 +160,19 @@ class BibleOSISImpl():
.replace(u'</lg>', u'').replace(u'</q>', u'')\ .replace(u'</lg>', u'').replace(u'</q>', u'')\
.replace(u'</div>', u'') .replace(u'</div>', u'')
verse_text = self.spaces_regex.sub(u' ', verse_text) 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') Receiver.send_message(u'process_events')
self.bibledb.save_verses() self.commit()
dialogobject.incrementProgressBar(u'Finishing import...') self.wizard.incrementProgressBar(u'Finishing import...')
except: except:
log.exception(u'Loading bible from OSIS file failed') log.exception(u'Loading bible from OSIS file failed')
success = False success = False
finally: finally:
if osis: if osis:
osis.close() osis.close()
if not self.loadbible: if self.stop_import:
dialogobject.incrementProgressBar(u'Import canceled!') self.wizard.incrementProgressBar(u'Import canceled!')
dialogobject.ImportProgressBar.setValue(
dialogobject.ImportProgressBar.maximum())
return False return False
else: 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), sxml.add_verse_to_lyrics(u'custom', unicode(count),
unicode(self.VerseListView.item(i).text())) unicode(self.VerseListView.item(i).text()))
count += 1 count += 1
self.customSlide.title = unicode(self.TitleEdit.displayText()) self.customSlide.title = unicode(self.TitleEdit.displayText(), u'utf-8')
self.customSlide.text = unicode(sxml.extract_xml()) self.customSlide.text = unicode(sxml.extract_xml(), u'utf-8')
self.customSlide.credits = unicode(self.CreditEdit.displayText()) self.customSlide.credits = unicode(self.CreditEdit.displayText(), u'utf-8')
self.customSlide.theme_name = unicode(self.ThemeComboBox.currentText()) self.customSlide.theme_name = unicode(self.ThemeComboBox.currentText(), u'utf-8')
self.custommanager.save_slide(self.customSlide) self.custommanager.save_slide(self.customSlide)
return True return True

View File

@ -185,8 +185,13 @@ class SongMediaItem(MediaManagerItem):
if author_list != u'': if author_list != u'':
author_list = author_list + u', ' author_list = author_list + u', '
author_list = author_list + author.display_name author_list = author_list + author.display_name
song_detail = unicode(self.trUtf8('%s (%s)' % \ if not isinstance(author_list, unicode):
(unicode(song.title), unicode(author_list)))) 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 = QtGui.QListWidgetItem(song_detail)
song_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(song.id)) song_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(song.id))
self.ListView.addItem(song_name) self.ListView.addItem(song_name)

View File

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