← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~raoul-snyman/openlp/biblesplugin into lp:openlp

 

Raoul Snyman has proposed merging lp:~raoul-snyman/openlp/biblesplugin into lp:openlp.

    Requested reviews:
    OpenLP Core (openlp-core)

-- 
https://code.launchpad.net/~raoul-snyman/openlp/biblesplugin/+merge/18757
Your team OpenLP Core is subscribed to branch lp:openlp.
=== modified file 'openlp.pyw'
--- openlp.pyw	2010-01-29 16:38:28 +0000
+++ openlp.pyw	2010-02-06 13:38:12 +0000
@@ -148,7 +148,7 @@
     usage = u'Usage: %prog [options] [qt-options]'
     parser = OptionParser(usage=usage)
     parser.add_option("-l", "--log-level", dest="loglevel",
-                      default="info", metavar="LEVEL",
+                      default="warning", metavar="LEVEL",
                       help="Set logging to LEVEL level. Valid values are "
                            "\"debug\", \"info\", \"warning\".")
     parser.add_option("-p", "--portable", dest="portable",

=== modified file 'openlp/core/lib/baselistwithdnd.py'
--- openlp/core/lib/baselistwithdnd.py	2009-12-31 12:52:01 +0000
+++ openlp/core/lib/baselistwithdnd.py	2010-02-06 13:38:12 +0000
@@ -32,6 +32,7 @@
 
     def __init__(self, parent=None):
         QtGui.QListWidget.__init__(self, parent)
+        self.parent = parent
         # this must be set by the class which is inheriting
         assert(self.PluginName)
 
@@ -47,4 +48,5 @@
         mimeData = QtCore.QMimeData()
         drag.setMimeData(mimeData)
         mimeData.setText(self.PluginName)
-        dropAction = drag.start(QtCore.Qt.CopyAction)
\ No newline at end of file
+        dropAction = drag.start(QtCore.Qt.CopyAction)
+

=== modified file 'openlp/core/lib/eventreceiver.py'
--- openlp/core/lib/eventreceiver.py	2010-01-29 13:06:47 +0000
+++ openlp/core/lib/eventreceiver.py	2010-02-06 13:38:12 +0000
@@ -164,4 +164,9 @@
         """
         Get the global ``eventreceiver`` instance.
         """
-        return Receiver.eventreceiver
+<<<<<<< TREE
+        return Receiver.eventreceiver
+=======
+        return Receiver.eventreceiver
+
+>>>>>>> MERGE-SOURCE

=== modified file 'openlp/core/lib/mediamanageritem.py'
--- openlp/core/lib/mediamanageritem.py	2009-12-31 12:52:01 +0000
+++ openlp/core/lib/mediamanageritem.py	2010-02-06 13:38:12 +0000
@@ -253,7 +253,7 @@
 
     def addListViewToToolBar(self):
         #Add the List widget
-        self.ListView = self.ListViewWithDnD_class()
+        self.ListView = self.ListViewWithDnD_class(self)
         self.ListView.uniformItemSizes = True
         self.ListView.setGeometry(QtCore.QRect(10, 100, 256, 591))
         self.ListView.setSpacing(1)
@@ -400,4 +400,4 @@
         if self.generateSlideData(service_item):
             return service_item
         else:
-            return None
\ No newline at end of file
+            return None

=== modified file 'openlp/plugins/bibles/bibleplugin.py'
--- openlp/plugins/bibles/bibleplugin.py	2009-12-31 12:52:01 +0000
+++ openlp/plugins/bibles/bibleplugin.py	2010-02-06 13:38:12 +0000
@@ -40,12 +40,12 @@
         self.weight = -9
         self.icon = build_icon(u':/media/media_bible.png')
         #Register the bible Manager
-        self.biblemanager = None
+        self.manager = None
 
     def initialise(self):
         log.info(u'bibles Initialising')
-        if self.biblemanager is None:
-            self.biblemanager = BibleManager(self.config)
+        if self.manager is None:
+            self.manager = BibleManager(self, self.config)
         Plugin.initialise(self)
         self.insert_toolbox_item()
         self.ImportBibleItem.setVisible(True)
@@ -90,4 +90,5 @@
         about_text = self.trUtf8('<strong>Bible Plugin</strong><br />This '
             'plugin allows bible verses from different sources to be '
             'displayed on the screen during the service.')
-        return about_text
\ No newline at end of file
+        return about_text
+

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

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

=== modified file 'openlp/plugins/bibles/lib/common.py'
--- openlp/plugins/bibles/lib/common.py	2009-12-31 12:52:01 +0000
+++ openlp/plugins/bibles/lib/common.py	2010-02-06 13:38:12 +0000
@@ -26,8 +26,98 @@
 import urllib2
 import chardet
 import logging
-
-class SearchResults:
+import re
+import sqlite3
+
+only_verses = re.compile(r'([\w .]+)[ ]+([0-9]+)[ ]*[:|v|V][ ]*([0-9]+)'
+    r'(?:[ ]*-[ ]*([0-9]+|end))?(?:[ ]*,[ ]*([0-9]+)(?:[ ]*-[ ]*([0-9]+|end))?)?',
+    re.UNICODE)
+chapter_range = re.compile(r'([\w .]+)[ ]+([0-9]+)[ ]*[:|v|V][ ]*'
+    r'([0-9]+)[ ]*-[ ]*([0-9]+)[ ]*[:|v|V][ ]*([0-9]+)',
+    re.UNICODE)
+
+log = logging.getLogger(__name__)
+
+def parse_reference(reference):
+    """
+    This is the über-awesome function that takes a person's typed in string
+    and converts it to a reference list, a list of references to be queried
+    from the Bible database files.
+
+    The reference list is a list of tuples, with each tuple structured like
+    this::
+
+        (book, chapter, start_verse, end_verse)
+    """
+    reference = reference.strip()
+    log.debug('parse_reference("%s")', reference)
+    reference_list = []
+    # We start with the most "complicated" match first, so that they are found
+    # first, and we don't have any "false positives".
+    match = chapter_range.match(reference)
+    if match:
+        log.debug('Found a chapter range.')
+        book = match.group(1)
+        from_verse = match.group(3)
+        to_verse = match.group(5)
+        if int(match.group(2)) == int(match.group(4)):
+            reference_list.append(
+                (match.group(1), int(match.group(2)), from_verse, to_verse)
+            )
+        else:
+            if int(match.group(2)) > int(match.group(4)):
+                from_chapter = int(match.group(4))
+                to_chapter = int(match.group(2))
+            else:
+                from_chapter = int(match.group(2))
+                to_chapter = int(match.group(4))
+            for chapter in xrange(from_chapter, to_chapter + 1):
+                if chapter == from_chapter:
+                    reference_list.append(
+                        (match.group(1), chapter, from_verse, -1)
+                    )
+                elif chapter == to_chapter:
+                    reference_list.append(
+                        (match.group(1), chapter, 1, to_verse)
+                    )
+                else:
+                    reference_list.append(
+                        (match.group(1), chapter, 1, -1)
+                    )
+    else:
+        match = only_verses.match(reference)
+        if match:
+            log.debug('Found a verse range.')
+            book = match.group(1)
+            chapter = match.group(2)
+            verse = match.group(3)
+            if match.group(4) is None:
+                reference_list.append((book, chapter, verse, verse))
+            elif match.group(5) is None:
+                end_verse = match.group(4)
+                if end_verse == u'end':
+                    end_verse = -1
+                reference_list.append((book, chapter, verse, end_verse))
+            elif match.group(6) is None:
+                reference_list.extend([
+                    (book, chapter, verse, match.group(4)),
+                    (book, chapter, match.group(5), match.group(5))
+                ])
+            else:
+                end_verse = match.group(6)
+                if end_verse == u'end':
+                    end_verse = -1
+                reference_list.extend([
+                    (book, chapter, verse, match.group(4)),
+                    (book, chapter, match.group(5), end_verse)
+                ])
+        else:
+            log.debug('Didn\'t find anything.')
+    log.debug(reference_list)
+    return reference_list
+
+
+class SearchResults(object):
     """
     Encapsulate a set of search results. This is Bible-type independant.
     """
@@ -81,12 +171,6 @@
     log = logging.getLogger(u'BibleCommon')
     log.info(u'BibleCommon')
 
-    def __init__(self):
-        """
-        An empty constructor... not sure why I'm here.
-        """
-        pass
-
     def _get_web_text(self, urlstring, proxyurl):
         """
         Get the HTML from the web page.
@@ -165,4 +249,4 @@
             text = text[:start_tag] + text[end_tag + 1:]
             start_tag = text.find(u'<')
         text = text.replace(u'>', u'')
-        return text.rstrip().lstrip()
\ No newline at end of file
+        return text.rstrip().lstrip()

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

=== renamed file 'openlp/plugins/bibles/lib/bibleDBimpl.py' => 'openlp/plugins/bibles/lib/db.py'
--- openlp/plugins/bibles/lib/bibleDBimpl.py	2009-12-31 12:52:01 +0000
+++ openlp/plugins/bibles/lib/db.py	2010-02-06 13:38:12 +0000
@@ -25,24 +25,58 @@
 
 import os
 import logging
-
-from common import BibleCommon
+import chardet
+
+from sqlalchemy import or_
+from PyQt4 import QtCore
+
 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)
+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.biblefile
+            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'),
@@ -52,139 +86,201 @@
         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.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.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 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):
+    def create_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()
+        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.session.commit()
+            self.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 ')
+        log.debug(u'.........Dumping Bible Database')
+        log.debug('...............................Books ')
         books = self.session.query(Book).all()
         log.debug(books)
-        log.debug( u'...............................Verses ')
+        log.debug(u'...............................Verses ')
         verses = self.session.query(Verse).all()
-        log.debug(verses)
\ No newline at end of file
+        log.debug(verses)
+

=== renamed file 'openlp/plugins/bibles/lib/bibleHTTPimpl.py' => 'openlp/plugins/bibles/lib/http.py'
--- openlp/plugins/bibles/lib/bibleHTTPimpl.py	2009-12-31 12:52:01 +0000
+++ openlp/plugins/bibles/lib/http.py	2010-02-06 13:38:12 +0000
@@ -24,15 +24,106 @@
 ###############################################################################
 
 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):
+    def __init__(self, proxyurl=None):
         log.debug(u'init %s', proxyurl)
         self.proxyurl = proxyurl
 
@@ -49,12 +140,10 @@
         ``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)
+        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'
@@ -95,17 +184,14 @@
         return SearchResults(bookname, chapter, bible)
 
 class CWExtract(BibleCommon):
-    global log
-    log = logging.getLogger(u'BibleHTTPMgr(CWExtract)')
-    log.info(u'CWExtract loaded')
+    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'getBibleChapter %s,%s,%s',
-            version,bookname, chapter)
+    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
 
@@ -121,61 +207,31 @@
         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):
+        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
@@ -185,44 +241,121 @@
 
         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):
+        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_bible_chapter %s,%s,%s',
-            version, bookname, chapter)
-        log.debug(u'biblesource = %s', self.biblesource)
+        log.debug(u'get_chapter %s, %s, %s', version, book, chapter)
+        log.debug(u'source = %s', self.download_source)
         try:
-            if self.biblesource.lower() == u'crosswalk':
-                ev = CWExtract(self.proxyurl)
+            if self.download_source.lower() == u'crosswalk':
+                ev = CWExtract(self.proxy_server)
             else:
-                ev = BGExtract(self.proxyurl)
-            return ev.get_bible_chapter(self.bibleid, bookname, chapter)
+                ev = BGExtract(self.proxy_server)
+            return ev.get_bible_chapter(self.download_name, book, chapter)
         except:
-            log.exception("Failed to get bible chapter")
\ No newline at end of file
+            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
+

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

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

=== modified file 'openlp/plugins/bibles/lib/models.py'
--- openlp/plugins/bibles/lib/models.py	2009-12-31 12:52:01 +0000
+++ openlp/plugins/bibles/lib/models.py	2010-02-06 13:38:12 +0000
@@ -50,7 +50,7 @@
     pass
 
 
-class ONTestament(BaseModel):
+class Testament(BaseModel):
     """
     Bible Testaments
     """
@@ -101,8 +101,8 @@
     Column(u'text', types.UnicodeText, index=True),
 )
 mapper(BibleMeta, meta_table)
-mapper(ONTestament, testament_table,
+mapper(Testament, testament_table,
     properties={'books': relation(Book, backref='testament')})
 mapper(Book, book_table,
     properties={'verses': relation(Verse, backref='book')})
-mapper(Verse, verse_table)
\ No newline at end of file
+mapper(Verse, verse_table)

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

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

=== removed file 'openlp/plugins/bibles/resources/httpbooks.csv'
--- openlp/plugins/bibles/resources/httpbooks.csv	2009-10-12 10:18:54 +0000
+++ openlp/plugins/bibles/resources/httpbooks.csv	1970-01-01 00:00:00 +0000
@@ -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

=== added file 'openlp/plugins/bibles/resources/httpbooks.sqlite'
Binary files openlp/plugins/bibles/resources/httpbooks.sqlite	1970-01-01 00:00:00 +0000 and openlp/plugins/bibles/resources/httpbooks.sqlite	2010-02-06 13:38:12 +0000 differ
=== modified file 'openlp/plugins/custom/forms/editcustomform.py'
--- openlp/plugins/custom/forms/editcustomform.py	2009-12-31 12:52:01 +0000
+++ openlp/plugins/custom/forms/editcustomform.py	2010-02-06 13:38:12 +0000
@@ -153,10 +153,10 @@
             sxml.add_verse_to_lyrics(u'custom', unicode(count),
                 unicode(self.VerseListView.item(i).text()))
             count += 1
-        self.customSlide.title = unicode(self.TitleEdit.displayText())
-        self.customSlide.text = unicode(sxml.extract_xml())
-        self.customSlide.credits = unicode(self.CreditEdit.displayText())
-        self.customSlide.theme_name = unicode(self.ThemeComboBox.currentText())
+        self.customSlide.title = unicode(self.TitleEdit.displayText(), u'utf-8')
+        self.customSlide.text = unicode(sxml.extract_xml(), u'utf-8')
+        self.customSlide.credits = unicode(self.CreditEdit.displayText(), u'utf-8')
+        self.customSlide.theme_name = unicode(self.ThemeComboBox.currentText(), u'utf-8')
         self.custommanager.save_slide(self.customSlide)
         return True
 
@@ -257,4 +257,4 @@
         if len(self.VerseTextEdit.toPlainText()) > 0:
             self.VerseTextEdit.setFocus()
             return False, self.trUtf8('You have unsaved data')
-        return True,  u''
\ No newline at end of file
+        return True,  u''

=== modified file 'openlp/plugins/songs/lib/mediaitem.py'
--- openlp/plugins/songs/lib/mediaitem.py	2009-12-31 12:52:01 +0000
+++ openlp/plugins/songs/lib/mediaitem.py	2010-02-06 13:38:12 +0000
@@ -185,8 +185,13 @@
                 if author_list != u'':
                     author_list = author_list + u', '
                 author_list = author_list + author.display_name
-            song_detail = unicode(self.trUtf8('%s (%s)' % \
-                (unicode(song.title), unicode(author_list))))
+            if not isinstance(author_list, unicode):
+                author_list = unicode(author_list, u'utf8')
+            if isinstance(song.title, unicode):
+                song_title = song.title
+            else:
+                song_title = unicode(song.title, u'utf8')
+            song_detail = u'%s (%s)' % (song_title, author_list)
             song_name = QtGui.QListWidgetItem(song_detail)
             song_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(song.id))
             self.ListView.addItem(song_name)
@@ -339,4 +344,4 @@
         service_item.audit = [
             song.title, author_audit, song.copyright, song.ccli_number
         ]
-        return True
\ No newline at end of file
+        return True


Follow ups