From 34ab7ea901a50279dfd44bb224ef8bd32c9ca1d8 Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Mon, 28 Dec 2009 01:54:00 +0200 Subject: [PATCH 01/33] Started moving Bible formats to a generic system. --- openlp/plugins/bibles/lib/common.py | 4 +- .../bibles/lib/{bibleCSVimpl.py => csv.py} | 21 ++--- .../bibles/lib/{bibleDBimpl.py => db.py} | 29 +++++-- .../bibles/lib/{bibleHTTPimpl.py => http.py} | 2 +- openlp/plugins/bibles/lib/manager.py | 78 ++++++++++++------- .../lib/{bibleOpenSongimpl.py => opensong.py} | 6 +- .../bibles/lib/{bibleOSISimpl.py => osis.py} | 2 +- 7 files changed, 92 insertions(+), 50 deletions(-) rename openlp/plugins/bibles/lib/{bibleCSVimpl.py => csv.py} (92%) rename openlp/plugins/bibles/lib/{bibleDBimpl.py => db.py} (89%) rename openlp/plugins/bibles/lib/{bibleHTTPimpl.py => http.py} (99%) rename openlp/plugins/bibles/lib/{bibleOpenSongimpl.py => opensong.py} (97%) rename openlp/plugins/bibles/lib/{bibleOSISimpl.py => osis.py} (99%) diff --git a/openlp/plugins/bibles/lib/common.py b/openlp/plugins/bibles/lib/common.py index fe8d18ff4..027cf6314 100644 --- a/openlp/plugins/bibles/lib/common.py +++ b/openlp/plugins/bibles/lib/common.py @@ -85,7 +85,9 @@ class BibleCommon(object): """ An empty constructor... not sure why I'm here. """ - pass + self.loadbible = True + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'openlpstopimport'), self.stop_import) def _get_web_text(self, urlstring, proxyurl): """ diff --git a/openlp/plugins/bibles/lib/bibleCSVimpl.py b/openlp/plugins/bibles/lib/csv.py similarity index 92% rename from openlp/plugins/bibles/lib/bibleCSVimpl.py rename to openlp/plugins/bibles/lib/csv.py index 0f168bd10..e829f99a0 100644 --- a/openlp/plugins/bibles/lib/bibleCSVimpl.py +++ b/openlp/plugins/bibles/lib/csv.py @@ -26,23 +26,24 @@ import logging import chardet -from openlp.plugins.bibles.lib.common import BibleCommon +from openlp.plugins.bibles.lib.db import BibleDB 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): +log = logging.getLogger(__name__) + +class CSVBible(BibleDB): + """ + This class provides a specialisation for importing of CSV Bibles. + """ + + def __init__(self, **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) + log.info(__name__) + BibleDB.__init__(self, **kwargs) def stop_import(self): self.loadbible = False diff --git a/openlp/plugins/bibles/lib/bibleDBimpl.py b/openlp/plugins/bibles/lib/db.py similarity index 89% rename from openlp/plugins/bibles/lib/bibleDBimpl.py rename to openlp/plugins/bibles/lib/db.py index ffc2f5c9b..260b3bda4 100644 --- a/openlp/plugins/bibles/lib/bibleDBimpl.py +++ b/openlp/plugins/bibles/lib/db.py @@ -27,17 +27,30 @@ import os import logging from common import BibleCommon -from openlp.plugins.bibles.lib.models import * +from models import * -class BibleDBImpl(BibleCommon): - global log - log = logging.getLogger(u'BibleDBImpl') - log.info(u'BibleDBimpl loaded') +log = logging.getLogger(__name__) - def __init__(self, biblepath, biblename, config): +class BibleDB(BibleCommon): + """ + 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, **kwargs): + log.info(u'BibleDBimpl loaded') + if u'biblepath' not in kwargs: + raise KeyError(u'Missing keyword argument "path".') + if u'biblename' not in kwargs: + raise KeyError(u'Missing keyword argument "name".') + if u'config' not in kwargs: + raise KeyError(u'Missing keyword argument "config".') # Connect to database - self.config = config - self.biblefile = os.path.join(biblepath, biblename + u'.sqlite') + self.config = kwargs[u'config'] + self.db_file = os.path.join(kwargs[u'path'], + u'%s.sqlite' % kwargs[u'biblename']) log.debug(u'Load bible %s on path %s', biblename, self.biblefile) db_type = self.config.get_config(u'db type', u'sqlite') db_url = u'' diff --git a/openlp/plugins/bibles/lib/bibleHTTPimpl.py b/openlp/plugins/bibles/lib/http.py similarity index 99% rename from openlp/plugins/bibles/lib/bibleHTTPimpl.py rename to openlp/plugins/bibles/lib/http.py index 6d57698c4..e20a2ca64 100644 --- a/openlp/plugins/bibles/lib/bibleHTTPimpl.py +++ b/openlp/plugins/bibles/lib/http.py @@ -171,7 +171,7 @@ class CWExtract(BibleCommon): bible[verse] = self._clean_text(verseText) return SearchResults(book_title, book_chapter, bible) -class BibleHTTPImpl(): +class HTTPBible(object): global log log = logging.getLogger(u'BibleHTTPMgr') log.info(u'BibleHTTP manager loaded') diff --git a/openlp/plugins/bibles/lib/manager.py b/openlp/plugins/bibles/lib/manager.py index 9d0da8374..4d77bc32d 100644 --- a/openlp/plugins/bibles/lib/manager.py +++ b/openlp/plugins/bibles/lib/manager.py @@ -26,37 +26,59 @@ import logging import os -from bibleOpenSongimpl import BibleOpenSongImpl -from bibleOSISimpl import BibleOSISImpl -from bibleCSVimpl import BibleCSVImpl +from opensong import OpenSongBible +from osis import OSISBible +from csv import CSVBible from bibleDBimpl import BibleDBImpl from bibleHTTPimpl import BibleHTTPImpl 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: + @staticmethod + def get_class(id): + """ + Return the appropriate imeplementation class. + """ + if id == BibleFormat.OSIS: return BibleOSISImpl - elif id == class_.CSV: + elif id == BibleFormat.CSV: return BibleCSVImpl - elif id == class_.OpenSong: + elif id == BibleFormat.OpenSong: return BibleOpenSongImpl - elif id == class_.WebDownload: + elif id == BibleFormat.WebDownload: return BibleHTTPImpl else: return None + @staticmethod + def list(): + return [ + BibleFormat.OSIS, + BibleFormat.CSV, + BibleFormat.OpenSong, + BibleFormat.WebDownload + ] + class BibleManager(object): """ @@ -84,11 +106,11 @@ class BibleManager(object): self.bible_db_cache = None # dict of bible http readers self.bible_http_cache = None - self.biblePath = self.config.get_data_path() + self.bible_path = 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.proxy_name = self.config.get_config(u'proxy name') + self.bible_suffix = u'sqlite' + self.import_wizard = None self.reload_bibles() self.media = None @@ -108,7 +130,7 @@ class BibleManager(object): for f in files: nme = f.split(u'.') bname = nme[0] - self.bible_db_cache[bname] = BibleDBImpl(self.biblePath, + self.bible_db_cache[bname] = BibleDBImpl(self.bible_path, bname, self.config) # look to see if lazy load bible exists and get create getter. biblesource = self.bible_db_cache[bname].get_meta(u'WEB') @@ -139,7 +161,7 @@ class BibleManager(object): 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')) + filepath, u'..', u'resources', u'httpbooks.csv')) fbibles = None try: fbibles = open(filepath, u'r') @@ -155,14 +177,14 @@ class BibleManager(object): fbibles.close() log.debug(u'Bible Initialised') - def set_process_dialog(self, dialogobject): + def set_process_dialog(self, wizard): """ Sets the reference to the dialog with the progress bar on it. - ``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): """ @@ -171,7 +193,11 @@ class BibleManager(object): ``type`` What type of Bible, """ - pass + impl_class = BibleFormat.get_handler(type) + bible_impl = impl_class(**kwargs) + bible_name = bible_impl.register() + BibleDBImpl(self.biblePath, bible_name, self.config) + bible_impl.do_import() def register_http_bible(self, biblename, biblesource, bibleid, proxyurl=None, proxyid=None, proxypass=None): @@ -202,7 +228,7 @@ class BibleManager(object): biblename, biblesource, bibleid, proxyurl, proxyid, proxypass) if self._is_new_bible(biblename): # Create new Bible - nbible = BibleDBImpl(self.biblePath, biblename, self.config) + nbible = BibleDBImpl(self.bible_path, biblename, self.config) # Create Database nbible.create_tables() self.bible_db_cache[biblename] = nbible @@ -239,7 +265,7 @@ class BibleManager(object): biblename, booksfile, versefile) if self._is_new_bible(biblename): # Create new Bible - nbible = BibleDBImpl(self.biblePath, biblename, self.config) + nbible = BibleDBImpl(self.bible_path, biblename, self.config) # Create database nbible.create_tables() # Cache the database for use later @@ -261,13 +287,13 @@ class BibleManager(object): 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) + nbible = BibleDBImpl(self.bible_path, 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) + bosis = BibleOSISImpl(self.bible_path, nbible) return bosis.load_data(osisfile, self.dialogobject) else: log.debug( @@ -283,13 +309,13 @@ class BibleManager(object): 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) + nbible = BibleDBImpl(self.bible_path, 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 = BibleOpenSongImpl(self.bible_path, nbible) bcsv.load_data(opensongfile, self.dialogobject) return True else: diff --git a/openlp/plugins/bibles/lib/bibleOpenSongimpl.py b/openlp/plugins/bibles/lib/opensong.py similarity index 97% rename from openlp/plugins/bibles/lib/bibleOpenSongimpl.py rename to openlp/plugins/bibles/lib/opensong.py index 58b9ffcd0..7ede58249 100644 --- a/openlp/plugins/bibles/lib/bibleOpenSongimpl.py +++ b/openlp/plugins/bibles/lib/opensong.py @@ -34,7 +34,7 @@ from PyQt4 import QtCore from openlp.core.lib import Receiver -class BibleOpenSongImpl(): +class OpenSongBible(object): """ OSIS Bible format importer class. """ @@ -81,10 +81,10 @@ class BibleOpenSongImpl(): detect_file = None try: detect_file = open(bible_file, u'r') - details = chardet.detect(detect_file.read(2048)) + details = chardet.detect(detect_file.read(3000)) except: log.exception(u'Failed to detect OpenSong file encoding') - return + return False finally: if detect_file: detect_file.close() diff --git a/openlp/plugins/bibles/lib/bibleOSISimpl.py b/openlp/plugins/bibles/lib/osis.py similarity index 99% rename from openlp/plugins/bibles/lib/bibleOSISimpl.py rename to openlp/plugins/bibles/lib/osis.py index 15b16c072..62beb6e15 100644 --- a/openlp/plugins/bibles/lib/bibleOSISimpl.py +++ b/openlp/plugins/bibles/lib/osis.py @@ -34,7 +34,7 @@ from PyQt4 import QtCore from openlp.core.lib import Receiver -class BibleOSISImpl(): +class OSISBible(object): """ OSIS Bible format importer class. """ From 0374233db6137b2ea33c86a865ca8af6b3443e8e Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Wed, 30 Dec 2009 19:29:08 +0200 Subject: [PATCH 02/33] Lots of changes here, I think. - Pluggable import system - The enumeration class provides the correct importer class - Reworked Bible verse parsing, using regular expressions - Reworked verse query method to accept multiple verse ranges - Renamed lots of methods, which is probably gonna break lots of stuff --- .../plugins/bibles/forms/importwizardform.py | 44 ++- openlp/plugins/bibles/lib/common.py | 65 +++- openlp/plugins/bibles/lib/csv.py | 52 ++- openlp/plugins/bibles/lib/db.py | 323 +++++++++++------- openlp/plugins/bibles/lib/http.py | 81 +++-- openlp/plugins/bibles/lib/manager.py | 111 +++--- openlp/plugins/bibles/lib/mediaitem.py | 9 +- openlp/plugins/bibles/lib/models.py | 4 +- openlp/plugins/bibles/lib/opensong.py | 84 ++--- openlp/plugins/bibles/lib/osis.py | 67 ++-- 10 files changed, 474 insertions(+), 366 deletions(-) diff --git a/openlp/plugins/bibles/forms/importwizardform.py b/openlp/plugins/bibles/forms/importwizardform.py index 22fbea989..9bf6b51c1 100644 --- a/openlp/plugins/bibles/forms/importwizardform.py +++ b/openlp/plugins/bibles/forms/importwizardform.py @@ -169,6 +169,15 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok)) self.CopyrightEdit.setFocus() return False + elif self.biblemanager.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 @@ -317,22 +326,22 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): success = False if bible_type == BibleFormat.OSIS: # Import an OSIS bible - success = self.biblemanager.register_osis_file_bible( - unicode(self.field(u'license_version').toString()), - unicode(self.field(u'osis_location').toString()) + success = self.biblemanager.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.biblemanager.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.biblemanager.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,13 +353,13 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): elif download_location == DownloadLocation.BibleGateway: bible = self.web_bible_list[DownloadLocation.BibleGateway][ unicode(self.BibleComboBox.currentText())] - success = self.biblemanager.register_http_bible( - unicode(self.field(u'license_version').toString()), - unicode(DownloadLocation.get_name(download_location)), - unicode(bible), - unicode(self.field(u'proxy_server').toString()), - unicode(self.field(u'proxy_username').toString()), - unicode(self.field(u'proxy_password').toString()) + success = self.biblemanager.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( @@ -359,6 +368,7 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): unicode(self.field(u'license_copyright').toString()), unicode(self.field(u'license_permission').toString()) ) + self.biblemanager.reload_bibles() self.ImportProgressLabel.setText(self.trUtf8('Finished import.')) else: self.ImportProgressLabel.setText( diff --git a/openlp/plugins/bibles/lib/common.py b/openlp/plugins/bibles/lib/common.py index 027cf6314..b40c483ba 100644 --- a/openlp/plugins/bibles/lib/common.py +++ b/openlp/plugins/bibles/lib/common.py @@ -26,6 +26,63 @@ import urllib2 import chardet import logging +import re + +only_verses = re.compile(r'([a-zA-Z0-9 ]+)[ ]+([0-9]+)[ ]*[:|v|V][ ]*([0-9]+)' + r'(?:[ ]*-[ ]*([0-9]+|end))?(?:[ ]*,[ ]*([0-9]+)(?:[ ]*-[ ]*([0-9]+|end))?)?', + re.UNICODE) +chapter_range = re.compile(r'([a-zA-Z0-9 ]+)[ ]+([0-9]+)[ ]*[:|v|V][ ]*' + r'([0-9]+)[ ]*-[ ]*([0-9]+)[ ]*[:|v|V][ ]*([0-9]+)', + re.UNICODE) + +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() + 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: + reference_list.extend([ + (match.group(1), match.group(2), match.group(3), -1), + (match.group(1), match.group(4), 1, match.group(5)) + ]) + else: + match = only_verses.match(reference) + if match: + 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) + ]) + return reference_list class SearchResults: """ @@ -81,14 +138,6 @@ class BibleCommon(object): log = logging.getLogger(u'BibleCommon') log.info(u'BibleCommon') - def __init__(self): - """ - An empty constructor... not sure why I'm here. - """ - self.loadbible = True - QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'openlpstopimport'), self.stop_import) - def _get_web_text(self, urlstring, proxyurl): """ Get the HTML from the web page. diff --git a/openlp/plugins/bibles/lib/csv.py b/openlp/plugins/bibles/lib/csv.py index e829f99a0..c74452fd3 100644 --- a/openlp/plugins/bibles/lib/csv.py +++ b/openlp/plugins/bibles/lib/csv.py @@ -26,8 +26,8 @@ import logging import chardet -from openlp.plugins.bibles.lib.db import BibleDB from openlp.core.lib import Receiver +from db import BibleDB log = logging.getLogger(__name__) @@ -44,20 +44,22 @@ class CSVBible(BibleDB): """ log.info(__name__) BibleDB.__init__(self, **kwargs) + 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'] - def stop_import(self): - self.loadbible = False - - def load_data(self, booksfile, versesfile, dialogobject): + def do_import(self): #Populate the Tables success = True fbooks = None try: - fbooks = open(booksfile, 'r') - count = 0 + fbooks = open(self.booksfile, 'r') for line in fbooks: # cancel pressed - if not self.loadbible: + if self.stop_import: break details = chardet.detect(line) line = unicode(line, details['encoding']) @@ -65,12 +67,8 @@ class CSVBible(BibleDB): 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 + self.create_book(p2, p3, int(p1)) + Receiver.send_message(u'process_events') except: log.exception(u'Loading books from file failed') success = False @@ -82,10 +80,9 @@ class CSVBible(BibleDB): fverse = None try: fverse = open(versesfile, 'r') - count = 0 book_ptr = None for line in fverse: - if not self.loadbible: # cancel pressed + if self.stop_import: # cancel pressed break details = chardet.detect(line) line = unicode(line, details['encoding']) @@ -94,28 +91,23 @@ class CSVBible(BibleDB): p0 = p[0].replace(u'"', u'') p3 = p[3].replace(u'"', u'') if book_ptr is not p0: - book = self.bibledb.get_bible_book(p0) + book = self.get_book(p0) 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) + self.commit() + self.add_verse(book.id, p[1], p[2], p3) + 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 self.stop_import: + self.wizard.incrementProgressBar(u'Import canceled!') return False else: return success diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py index 260b3bda4..b1e228ee4 100644 --- a/openlp/plugins/bibles/lib/db.py +++ b/openlp/plugins/bibles/lib/db.py @@ -26,12 +26,15 @@ import os import logging -from common import BibleCommon +from sqlalchemy import or_ +from PyQt4 import QtCore + +from openlp.core.lib import Receiver from models import * log = logging.getLogger(__name__) -class BibleDB(BibleCommon): +class BibleDB(): """ 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 @@ -40,22 +43,39 @@ class BibleDB(BibleCommon): """ def __init__(self, **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') - if u'biblepath' not in kwargs: + if u'path' not in kwargs: raise KeyError(u'Missing keyword argument "path".') - if u'biblename' not in kwargs: + 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".') - # Connect to database + 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'biblename']) - log.debug(u'Load bible %s on path %s', biblename, self.biblefile) + 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'), @@ -65,134 +85,200 @@ class BibleDB(BibleCommon): self.metadata, self.session = init_models(db_url) self.metadata.create_all(checkfirst=True) + def register(self): + """ + 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. + """ + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'openlpstopimport'), self.stop_import) + self.create_tables() + return self.name + + def stop_import(self): + """ + Stops the import of the Bible. + """ + log.debug('Stopping import!') + self.stop_import = True + + 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') + self.create_testament(u'Old Testament') + self.create_testament(u'New Testament') + self.create_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 + def create_testament(self, testament): + log.debug(u'%s: %s', __name__, 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', bookname, bookabbrev) + 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', bookid, chap) + #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 = chap, + verse = verse_number, + text = verse_text + ) + self.session.add(verse) + self.commit() + + def create_verse(self, book_id, chapter, verse, text): + 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() + self.session.add(BibleMeta.populate(key=key, value=value)) + self.commit() - def get_meta(self, metakey): - log.debug(u'get meta %s', metakey) - return self.session.query(BibleMeta).filter_by(key=metakey).first() + def get_books(self): + log.debug(__name__) + return self.session.query(Book).order_by(Book.id).all() + + def get_book(self, book): + log.debug(u'%s: %s', __name__, book) + db_book = self.session.query(Book)\ + .filter_by(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'%s: %s, %s', __name__, 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'%s: %s', __name__, 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_chapter_count(book) + if db_book: + book = book.name + log.debug(u'Book name corrected to "%s"' % book) + verses = self.session.query(Verse)\ + .filter_by(book_id=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'%s: %s', __name__, 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'%s: %s', __name__, 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'%s: %s, %s', __name__, 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 ') @@ -201,3 +287,4 @@ class BibleDB(BibleCommon): log.debug( u'...............................Verses ') verses = self.session.query(Verse).all() log.debug(verses) + diff --git a/openlp/plugins/bibles/lib/http.py b/openlp/plugins/bibles/lib/http.py index e20a2ca64..57e6e4a16 100644 --- a/openlp/plugins/bibles/lib/http.py +++ b/openlp/plugins/bibles/lib/http.py @@ -26,17 +26,18 @@ import logging from common import BibleCommon, SearchResults +from db import BibleDB 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 - def get_bible_chapter(self, version, bookname, chapter) : + def get_chapter(self, version, bookname, chapter) : """ Access and decode bibles via the BibleGateway website @@ -49,12 +50,10 @@ class BGExtract(BibleCommon): ``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+%d' \ + u'&version=%s' % (bookname, chapter, version) + log.debug(u'BibleGateway url = %s' % urlstring) xml_string = self._get_web_text(urlstring, self.proxyurl) verseSearch = u'(.*?)') self.note_regex = re.compile(r'(.*?)') @@ -66,13 +65,11 @@ class OSISBible(object): self.w_regex = re.compile(r'') self.q_regex = re.compile(r'') 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,15 @@ class OSISBible(object): finally: if fbibles: fbibles.close() - 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 - - 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 +100,12 @@ class OSISBible(object): 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 +123,13 @@ class OSISBible(object): 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 +151,18 @@ class OSISBible(object): .replace(u'', u'').replace(u'', u'')\ .replace(u'', u'') verse_text = self.spaces_regex.sub(u' ', verse_text) - self.bibledb.add_verse(db_book.id, chapter, verse, verse_text) + self.add_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 From 027d6d3e4e7a3fc91af217a8b53a0fe42c327ece Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Mon, 11 Jan 2010 17:03:16 +0200 Subject: [PATCH 03/33] Moved the stop import out of the base class, since Qt doesn't like it. --- openlp/plugins/bibles/lib/csv.py | 9 +++++++++ openlp/plugins/bibles/lib/db.py | 12 +----------- openlp/plugins/bibles/lib/opensong.py | 9 +++++++++ openlp/plugins/bibles/lib/osis.py | 9 +++++++++ 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/openlp/plugins/bibles/lib/csv.py b/openlp/plugins/bibles/lib/csv.py index c74452fd3..099b3f1fa 100644 --- a/openlp/plugins/bibles/lib/csv.py +++ b/openlp/plugins/bibles/lib/csv.py @@ -50,6 +50,15 @@ class CSVBible(BibleDB): 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): + """ + Stops the import of the Bible. + """ + log.debug('Stopping import!') + self.stop_import = True def do_import(self): #Populate the Tables diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py index b1e228ee4..088bd68e8 100644 --- a/openlp/plugins/bibles/lib/db.py +++ b/openlp/plugins/bibles/lib/db.py @@ -29,8 +29,7 @@ import logging from sqlalchemy import or_ from PyQt4 import QtCore -from openlp.core.lib import Receiver -from models import * +from openlp.plugins.bibles.lib.models import * log = logging.getLogger(__name__) @@ -92,18 +91,9 @@ class BibleDB(): may want to override this method to supply their own custom initialisation as well. """ - QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'openlpstopimport'), self.stop_import) self.create_tables() return self.name - def stop_import(self): - """ - Stops the import of the Bible. - """ - log.debug('Stopping import!') - self.stop_import = True - def commit(self): log.debug('Committing...') self.session.commit() diff --git a/openlp/plugins/bibles/lib/opensong.py b/openlp/plugins/bibles/lib/opensong.py index 2442040de..a73d0e3c6 100644 --- a/openlp/plugins/bibles/lib/opensong.py +++ b/openlp/plugins/bibles/lib/opensong.py @@ -52,6 +52,15 @@ class OpenSongBible(BibleDB): if u'filename' not in kwargs: raise KeyError(u'You have to supply a file name to import from.') self.filename = kwargs[u'filename'] + 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.stop_import = True def do_import(self): """ diff --git a/openlp/plugins/bibles/lib/osis.py b/openlp/plugins/bibles/lib/osis.py index 17cb34180..f16c1cd02 100644 --- a/openlp/plugins/bibles/lib/osis.py +++ b/openlp/plugins/bibles/lib/osis.py @@ -81,6 +81,15 @@ class OSISBible(BibleDB): finally: if fbibles: fbibles.close() + 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.stop_import = True def do_import(self): """ From a976d6b59ac54754c670175b182a5daa3f1af1ff Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Sun, 17 Jan 2010 18:48:45 +0200 Subject: [PATCH 04/33] A few fixes after renaming some functions. --- openlp/plugins/bibles/lib/csv.py | 5 +- openlp/plugins/bibles/lib/db.py | 11 +++-- openlp/plugins/bibles/lib/http.py | 3 +- openlp/plugins/bibles/lib/manager.py | 69 ++++++++++++++------------- openlp/plugins/bibles/lib/opensong.py | 25 ++++++---- openlp/plugins/bibles/lib/osis.py | 5 +- 6 files changed, 68 insertions(+), 50 deletions(-) diff --git a/openlp/plugins/bibles/lib/csv.py b/openlp/plugins/bibles/lib/csv.py index ac53f46cc..cd3b7efeb 100644 --- a/openlp/plugins/bibles/lib/csv.py +++ b/openlp/plugins/bibles/lib/csv.py @@ -106,7 +106,7 @@ class CSVBible(BibleDB): self.wizard.incrementProgressBar( u'Importing %s %s' % book.name) self.commit() - self.add_verse(book.id, p[1], p[2], p3) + self.create_verse(book.id, p[1], p[2], p3) Receiver.send_message(u'process_events') self.commit() except: @@ -119,4 +119,5 @@ class CSVBible(BibleDB): self.wizard.incrementProgressBar(u'Import canceled!') return False else: - return success \ No newline at end of file + return success + diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py index cf272d6e9..6de5217bb 100644 --- a/openlp/plugins/bibles/lib/db.py +++ b/openlp/plugins/bibles/lib/db.py @@ -25,6 +25,7 @@ import os import logging +import chardet from sqlalchemy import or_ from PyQt4 import QtCore @@ -84,13 +85,14 @@ class BibleDB(): self.metadata, self.session = init_models(db_url) self.metadata.create_all(checkfirst=True) - def register(self): + 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 @@ -100,7 +102,7 @@ class BibleDB(): def create_tables(self): log.debug(u'createTables') - self.save_meta(u'dbversion', u'2') + self.create_meta(u'dbversion', u'2') self.create_testament(u'Old Testament') self.create_testament(u'New Testament') self.create_testament(u'Apocrypha') @@ -111,7 +113,7 @@ class BibleDB(): self.commit() def create_book(self, name, abbrev, testament=1): - log.debug(u'create_book %s,%s', bookname, bookabbrev) + log.debug(u'create_book %s,%s', name, abbrev) book = Book.populate(name=name, abbreviation=abbrev, testament_id=testament) self.session.add(book) @@ -132,6 +134,9 @@ class BibleDB(): 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, diff --git a/openlp/plugins/bibles/lib/http.py b/openlp/plugins/bibles/lib/http.py index 7f1c835f8..5c3ac53b0 100644 --- a/openlp/plugins/bibles/lib/http.py +++ b/openlp/plugins/bibles/lib/http.py @@ -232,4 +232,5 @@ class HTTPBible(BibleDB): ev = BGExtract(self.proxyurl) return ev.get_bible_chapter(self.bibleid, book, chapter) except: - log.exception("Failed to get bible chapter") \ No newline at end of file + log.exception("Failed to get bible chapter") + diff --git a/openlp/plugins/bibles/lib/manager.py b/openlp/plugins/bibles/lib/manager.py index 9a667d916..1a9d01d9d 100644 --- a/openlp/plugins/bibles/lib/manager.py +++ b/openlp/plugins/bibles/lib/manager.py @@ -61,13 +61,13 @@ class BibleFormat(object): Return the appropriate imeplementation class. """ if id == BibleFormat.OSIS: - return BibleOSISImpl + return OSISBible elif id == BibleFormat.CSV: - return BibleCSVImpl + return CSVBible elif id == BibleFormat.OpenSong: - return BibleOpenSongImpl + return OpenSongBible elif id == BibleFormat.WebDownload: - return BibleHTTPImpl + return HTTPBible else: return None @@ -161,10 +161,13 @@ class BibleManager(object): 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', '')}) + parts = line.split(u',') + self.book_abbreviations[parts[0]] = parts[1].replace(u'\n', '') + self.book_testaments[parts[0]] = parts[2].replace(u'\n', '') + self.book_chapters.append({ + u'book': parts[0], + u'total': parts[3].replace(u'\n', '') + }) except: log.exception(u'Failed to load bible') finally: @@ -192,10 +195,10 @@ class BibleManager(object): Keyword arguments to send to the actualy importer class. """ class_ = BibleFormat.get_class(type) - kwargs[u'path'] = self.path - kwargs[u'config'] = self.config + kwargs['path'] = self.path + kwargs['config'] = self.config importer = class_(**kwargs) - name = importer.register() + name = importer.register(self.import_wizard) self.db_cache[name] = importer return importer.do_import() @@ -231,7 +234,7 @@ class BibleManager(object): nbible = BibleDBImpl(self.bible_path, biblename, self.config) # Create Database nbible.create_tables() - self.bible_db_cache[biblename] = nbible + self.db_cache[biblename] = nbible nhttp = BibleHTTPImpl() nhttp.set_bible_source(biblesource) self.bible_http_cache[biblename] = nhttp @@ -366,16 +369,16 @@ class BibleManager(object): 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( + count = self.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( + count = self.db_cache[bible].get_max_bible_book_verses( book, chapter) return count else: - return self.bible_db_cache[bible].get_max_bible_book_verses( + return self.db_cache[bible].get_max_bible_book_verses( book, chapter) def get_verses(self, bible, versetext): @@ -386,7 +389,7 @@ class BibleManager(object): log.debug(u'get_verses_from_text %s,%s', bible, versetext) reflist = parse_reference(versetext) web, bible = self.is_bible_web(bible) - return self.bible_db_cache[bible].get_verses(reflist) + return self.db_cache[bible].get_verses(reflist) def save_meta_data(self, bible, version, copyright, permissions): """ @@ -394,9 +397,9 @@ class BibleManager(object): """ log.debug(u'save_meta data %s,%s, %s,%s', bible, version, copyright, permissions) - self.bible_db_cache[bible].save_meta(u'Version', version) - self.bible_db_cache[bible].save_meta(u'Copyright', copyright) - self.bible_db_cache[bible].save_meta(u'Permissions', permissions) + self.db_cache[bible].create_meta(u'Version', version) + self.db_cache[bible].create_meta(u'Copyright', copyright) + self.db_cache[bible].create_meta(u'Permissions', permissions) def get_meta_data(self, bible, key): """ @@ -404,7 +407,7 @@ class BibleManager(object): """ log.debug(u'get_meta %s,%s', bible, key) web, bible = self.is_bible_web(bible) - return self.bible_db_cache[bible].get_meta(key) + return self.db_cache[bible].get_meta(key) def get_verse_text(self, bible, bookname, schapter, echapter, sverse, everse=0): @@ -425,8 +428,8 @@ class BibleManager(object): # 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 self.http_cache[bible]: + book = self.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): @@ -434,7 +437,7 @@ class BibleManager(object): unicode(self.media.trUtf8('Downloading %s: %s')) % (bookname, chapter)) search_results = \ - self.bible_http_cache[bible].get_bible_chapter( + self.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 @@ -443,33 +446,33 @@ class BibleManager(object): ## 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( + book = self.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( + book = self.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( + self.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( + v = self.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( + self.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( + v = self.db_cache[bible].get_bible_chapter( book.id, chapter) if v is None: try: @@ -477,17 +480,17 @@ class BibleManager(object): unicode(self.media.trUtf8('Downloading %s: %s')) % (bookname, chapter)) search_results = \ - self.bible_http_cache[bible].get_bible_chapter( + self.http_cache[bible].get_bible_chapter( bible, bookname, chapter) if search_results.has_verselist(): - self.bible_db_cache[bible].create_chapter( + self.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, + text = self.db_cache[bible].get_bible_text(bookname, schapter, sverse, everse) else: for i in range (schapter, echapter + 1): @@ -501,7 +504,7 @@ class BibleManager(object): start = 1 end = self.get_book_verse_count(bible, bookname, i) - txt = self.bible_db_cache[bible].get_bible_text( + txt = self.db_cache[bible].get_bible_text( bookname, i, start, end) text.extend(txt) return text diff --git a/openlp/plugins/bibles/lib/opensong.py b/openlp/plugins/bibles/lib/opensong.py index 93820be48..64eeeb0f9 100644 --- a/openlp/plugins/bibles/lib/opensong.py +++ b/openlp/plugins/bibles/lib/opensong.py @@ -49,11 +49,11 @@ class OpenSongBible(BibleDB): """ log.debug(__name__) BibleDB.__init__(self, **kwargs) - if u'filename' not in kwargs: + if 'filename' not in kwargs: raise KeyError(u'You have to supply a file name to import from.') - self.filename = kwargs[u'filename'] - QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'openlpstopimport'), self.stop_import) + self.filename = kwargs['filename'] + #QtCore.QObject.connect(Receiver.get_receiver(), + # QtCore.SIGNAL(u'openlpstopimport'), self.stop_import) def stop_import(self): """ @@ -67,10 +67,12 @@ class OpenSongBible(BibleDB): Loads a Bible from file. """ 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...') detect_file = None try: detect_file = open(self.filename, u'r') - details = chardet.detect(detect_file.read(3000)) + details = chardet.detect(detect_file.read()) except: log.exception(u'Failed to detect OpenSong file encoding') return False @@ -94,11 +96,16 @@ class OpenSongBible(BibleDB): for verse in chapter.v: if self.stop_import: break - self.add_verse(db_book.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']), + verse.text + ) Receiver.send_message(u'process_events') - self.wizard.incrementProgressBar(u'Importing %s %s' % \ - (dbbook.name, str(chapter.attrib[u'n']))) + self.wizard.incrementProgressBar( + QtCore.QString('Importing %s %s' % \ + (db_book.name, chapter.attrib[u'n']))) self.commit() except: log.exception(u'Loading bible from OpenSong file failed') diff --git a/openlp/plugins/bibles/lib/osis.py b/openlp/plugins/bibles/lib/osis.py index 4f18b27c5..a7e4ba374 100644 --- a/openlp/plugins/bibles/lib/osis.py +++ b/openlp/plugins/bibles/lib/osis.py @@ -160,7 +160,7 @@ class OSISBible(BibleDB): .replace(u'', u'').replace(u'', u'')\ .replace(u'', u'') verse_text = self.spaces_regex.sub(u' ', verse_text) - self.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.commit() self.wizard.incrementProgressBar(u'Finishing import...') @@ -174,4 +174,5 @@ class OSISBible(BibleDB): self.wizard.incrementProgressBar(u'Import canceled!') return False else: - return success \ No newline at end of file + return success + From 4a9a8149c425e9ac5d7fdc61d406a38019f6ee72 Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Sun, 24 Jan 2010 09:08:14 +0200 Subject: [PATCH 05/33] Fixed up web Bibles. Renamed "csv.py" to "csvbible.py" to resolve a namespace conflict with the Python csv module. --- .../bibles/lib/{csv.py => csvbible.py} | 56 ++-- openlp/plugins/bibles/lib/db.py | 12 +- openlp/plugins/bibles/lib/http.py | 172 ++++++---- openlp/plugins/bibles/lib/manager.py | 306 +++++------------- openlp/plugins/bibles/lib/mediaitem.py | 198 ++++++------ 5 files changed, 328 insertions(+), 416 deletions(-) rename openlp/plugins/bibles/lib/{csv.py => csvbible.py} (76%) diff --git a/openlp/plugins/bibles/lib/csv.py b/openlp/plugins/bibles/lib/csvbible.py similarity index 76% rename from openlp/plugins/bibles/lib/csv.py rename to openlp/plugins/bibles/lib/csvbible.py index cd3b7efeb..f98ef0c86 100644 --- a/openlp/plugins/bibles/lib/csv.py +++ b/openlp/plugins/bibles/lib/csvbible.py @@ -25,6 +25,7 @@ import logging import chardet +import csv from openlp.core.lib import Receiver from db import BibleDB @@ -42,8 +43,8 @@ class CSVBible(BibleDB): This class assumes the files contain all the information and a clean bible is being loaded. """ - log.info(__name__) BibleDB.__init__(self, **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'] @@ -63,58 +64,55 @@ class CSVBible(BibleDB): def do_import(self): #Populate the Tables success = True - fbooks = None + books_file = None try: - fbooks = open(self.booksfile, 'r') - 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 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.create_book(p2, p3, int(p1)) + 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') book_ptr = None - for line in fverse: + 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.get_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 self.wizard.incrementProgressBar( - u'Importing %s %s' % book.name) + u'Importing %s %s' % (book.name, line[1])) self.commit() - self.create_verse(book.id, p[1], p[2], p3) + 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 verse_file: + verse_file.close() if self.stop_import: self.wizard.incrementProgressBar(u'Import canceled!') return False diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py index 6de5217bb..2131737fd 100644 --- a/openlp/plugins/bibles/lib/db.py +++ b/openlp/plugins/bibles/lib/db.py @@ -34,7 +34,7 @@ from openlp.plugins.bibles.lib.models import * log = logging.getLogger(__name__) -class BibleDB(): +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 @@ -121,12 +121,12 @@ class BibleDB(): return book def create_chapter(self, book_id, chapter, textlist): - log.debug(u'create_chapter %s,%s', bookid, chap) + 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 = chap, + chapter = chapter, verse = verse_number, text = verse_text ) @@ -158,7 +158,7 @@ class BibleDB(): def get_book(self, book): log.debug(u'%s: %s', __name__, book) db_book = self.session.query(Book)\ - .filter_by(Book.name.like(book + u'%'))\ + .filter(Book.name.like(book + u'%'))\ .first() if db_book is None: db_book = self.session.query(Book)\ @@ -198,10 +198,10 @@ class BibleDB(): if end_verse == -1: end_verse = self.get_chapter_count(book) if db_book: - book = book.name + book = db_book.name log.debug(u'Book name corrected to "%s"' % book) verses = self.session.query(Verse)\ - .filter_by(book_id=book.id)\ + .filter_by(book_id=db_book.id)\ .filter_by(chapter=chapter)\ .filter(Verse.verse >= start_verse)\ .filter(Verse.verse <= end_verse)\ diff --git a/openlp/plugins/bibles/lib/http.py b/openlp/plugins/bibles/lib/http.py index 5c3ac53b0..ff3045107 100644 --- a/openlp/plugins/bibles/lib/http.py +++ b/openlp/plugins/bibles/lib/http.py @@ -24,9 +24,13 @@ ############################################################################### import logging +import urllib2 + +from BeautifulSoup import BeautifulSoup from common import BibleCommon, SearchResults from db import BibleDB +from openlp.plugins.bibles.lib.models import Book class BGExtract(BibleCommon): global log @@ -51,7 +55,7 @@ class BGExtract(BibleCommon): Chapter number """ log.debug(u'get_bible_chapter %s, %s, %s', version, bookname, chapter) - urlstring = u'http://www.biblegateway.com/passage/?search=%s+%d' \ + 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) @@ -94,17 +98,14 @@ class BGExtract(BibleCommon): 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 @@ -120,60 +121,24 @@ class CWExtract(BibleCommon): 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'') - 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 + page = urllib2.urlopen(u'http://www.biblestudytools.com/%s/%s/%s.html' % \ + (version, bookname.lower(), chapter)) + soup = BeautifulSoup(page) + htmlverses = soup.findAll(u'span', u'versetext') + verses = {} + for verse in htmlverses: + 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) - 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 HTTPBible(BibleDB): - global log - log = logging.getLogger(u'BibleHTTPMgr') - log.info(u'BibleHTTP manager loaded') + log.info(u'%s loaded', __name__) def __init__(self, **kwargs): """ @@ -185,6 +150,7 @@ class HTTPBible(BibleDB): Init confirms the bible exists and stores the database path. """ + BibleDB.__init__(self, **kwargs) if u'download_source' not in kwargs: raise KeyError(u'Missing keyword argument "download_source"') if u'download_name' not in kwargs: @@ -204,8 +170,9 @@ class HTTPBible(BibleDB): else: self.proxy_password = None - def register(self): - name = BibleDB.register(self) + 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: @@ -216,21 +183,88 @@ class HTTPBible(BibleDB): if self.proxy_password: # store the proxy password self.create_meta(u'proxy password', self.proxy_password) - return name + self.wizard.incrementProgressBar('Registered.') + return True - def get_bible_chapter(self, version, book, chapter): + 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) + db_book = self.create_book(book_details[u'name'], + book_details[u'abbr'], book_details[u'test']) + book = db_book.name + if self.get_verse_count(book, reference[1]) == 0: + 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()) + 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, book, 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, book, chapter) + ev = BGExtract(self.proxy_server) + return ev.get_bible_chapter(self.download_name, book, chapter) except: log.exception("Failed to get bible chapter") + return None + + def get_books(self): + return [Book.populate(name=book[u'name']) for book in self.books] + + def get_chapter_count(self, book): + return self.books[book][u'chap'] + + def set_proxy_server(self, server): + self.proxy_server = server + + def set_books(self, books): + self.books = books + + def lookup_book(self, book): + log.debug('Looking up "%s" in %s', (book, self.books)) + if book in self.books: + return self.books[book] + else: + for details in self.books: + if details[u'abbr'] == book: + return details + return None diff --git a/openlp/plugins/bibles/lib/manager.py b/openlp/plugins/bibles/lib/manager.py index 1a9d01d9d..f6e7fc4ea 100644 --- a/openlp/plugins/bibles/lib/manager.py +++ b/openlp/plugins/bibles/lib/manager.py @@ -25,11 +25,12 @@ import logging import os +import csv from common import parse_reference from opensong import OpenSongBible from osis import OSISBible -from csv import CSVBible +from csvbible import CSVBible from db import BibleDB from http import HTTPBible @@ -103,77 +104,66 @@ class BibleManager(object): self.config = config log.debug(u'Bible Initialising') self.web = u'Web' - # dict of bible database objects self.db_cache = None - # dict of bible http readers self.http_cache = None + self.http_books = {} self.path = self.config.get_data_path() - #get proxy name for screen 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 load_http_books(self): + filepath = os.path.split(os.path.abspath(__file__))[0] + filepath = os.path.abspath(os.path.join( + filepath, u'..', u'resources', u'httpbooks.csv')) + books_file = None + try: + self.http_books = {} + books_file = open(filepath, u'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.http_books[line[0]] = { + u'name': line[0], + u'abbr': line[1], + u'test': line[2], + u'chap': line[3] + } + except: + log.exception(u'Failed to load http books.') + finally: + if books_file: + books_file.close() + def reload_bibles(self): log.debug(u'Reload bibles') files = self.config.get_files(self.suffix) log.debug(u'Bible Files %s', files) self.db_cache = {} self.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.load_http_books() self.web_bibles_present = False for filename in files: name, extension = os.path.splitext(filename) self.db_cache[name] = BibleDB(path=self.path, name=name, config=self.config) # look to see if lazy load bible exists and get create getter. - source = self.db_cache[name].get_meta(u'web') + source = self.db_cache[name].get_meta(u'download source') if source: self.web_bibles_present = True - web_bible = HTTPBible() - # tell The Server where to get the verses from. - web_bible.set_source(source.value) - self.http_cache[name] = web_bible - # look to see if lazy load bible exists and get create getter. + download_name = self.db_cache[name].get_meta(u'download name').value + web_bible = HTTPBible(path=self.path, name=name, + config=self.config, download_source=source.value, + download_name=download_name) meta_proxy = self.db_cache[name].get_meta(u'proxy url') - proxy_url = None if meta_proxy: - proxy_url = meta_proxy.value - # tell The Server where to get the verses from. - web_bible.set_proxy_url(proxy_url) - # look to see if lazy load bible exists and get create getter. - bible_id = self.db_cache[name].get_meta(u'bible id').value - # tell The Server where to get the verses from. - web_bible.set_bible_id(bible_id) - #else: - # # makes the Full / partial code easier. - # self.http_cache[name] = None - if self.web_bibles_present: - 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: - parts = line.split(u',') - self.book_abbreviations[parts[0]] = parts[1].replace(u'\n', '') - self.book_testaments[parts[0]] = parts[2].replace(u'\n', '') - self.book_chapters.append({ - u'book': parts[0], - u'total': parts[3].replace(u'\n', '') - }) - except: - log.exception(u'Failed to load bible') - finally: - if fbibles: - fbibles.close() - log.debug(u'Bible Initialised') + web_bible.set_proxy_server(meta_proxy.value) + web_bible.set_books(self.http_books) + del self.db_cache[name] + self.db_cache[name] = web_bible + log.debug(u'Bibles reloaded') def set_process_dialog(self, wizard): """ @@ -202,130 +192,6 @@ class BibleManager(object): self.db_cache[name] = importer return importer.do_import() - 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.bible_path, biblename, self.config) - # Create Database - nbible.create_tables() - self.db_cache[biblename] = nbible - nhttp = BibleHTTPImpl() - nhttp.set_bible_source(biblesource) - self.bible_http_cache[biblename] = nhttp - # register a lazy loading interest - nbible.create_meta(u'WEB', biblesource) - # store the web id of the bible - nbible.create_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.bible_path, 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.bible_path, 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.bible_path, 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.bible_path, 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.bible_path, 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 @@ -336,7 +202,7 @@ class BibleManager(object): log.debug(u'get_bibles') bible_list = [] for bible_name, bible_object in self.db_cache.iteritems(): - if bible_name in self.http_cache and self.http_cache[bible_name]: + if getattr(bible_object, 'download_source', None): bible_name = u'%s (%s)' % (bible_name, self.web) bible_list.append(bible_name) return bible_list @@ -347,12 +213,12 @@ class BibleManager(object): return True, bible[:pos_end] return False, bible - def get_bible_books(self): + def get_bible_books(self, bible): """ Returns a list of the books of the bible """ log.debug(u'get_bible_books') - return self.book_chapters + return [{'name': book.name, 'total': self.db_cache[bible].get_chapter_count(book.name)} for book in self.db_cache[bible].get_books()] def get_book_chapter_count(self, book): """ @@ -369,17 +235,14 @@ class BibleManager(object): log.debug(u'get_book_verse_count %s,%s,%s', bible, book, chapter) web, bible = self.is_bible_web(bible) if web: - count = self.db_cache[bible].get_max_bible_book_verses( - book, chapter) + count = self.db_cache[bible].get_verse_count(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.db_cache[bible].get_max_bible_book_verses( - book, chapter) + count = self.db_cache[bible].get_verse_count(book, chapter) return count else: - return self.db_cache[bible].get_max_bible_book_verses( - book, chapter) + return self.db_cache[bible].get_verse_count(book, chapter) def get_verses(self, bible, versetext): """ @@ -388,7 +251,14 @@ class BibleManager(object): """ log.debug(u'get_verses_from_text %s,%s', bible, versetext) reflist = parse_reference(versetext) - web, bible = self.is_bible_web(bible) + web_index = bible.find('(%s)' % self.web) + if web_index >= 0: + bible = bible[:web_index - 1] + log.debug('Updated bible name: %s', bible) + #web, bible = self.is_bible_web(bible) + #if web: + # return self.http_cache[bible].get_verses(reflist) + #else: return self.db_cache[bible].get_verses(reflist) def save_meta_data(self, bible, version, copyright, permissions): @@ -409,8 +279,7 @@ class BibleManager(object): web, bible = self.is_bible_web(bible) return self.db_cache[bible].get_meta(key) - def get_verse_text(self, bible, bookname, schapter, echapter, sverse, - everse=0): + def get_verse_text(self, bible, book, 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) @@ -424,89 +293,88 @@ class BibleManager(object): text = [] self.media.setQuickMessage(u'') log.debug(u'get_verse_text %s,%s,%s,%s,%s,%s', - bible, bookname, schapter, echapter, sverse, everse) + bible, book, 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) + web_bible = False + log.debug('Web Bibles: %s', self.http_cache) if self.http_cache[bible]: - book = self.db_cache[bible].get_bible_book(bookname) - if book is None: - log.debug(u'get_verse_text : new book') + web_bible = True + db_book = self.db_cache[bible].get_book(book) + if db_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)) + (book, chapter)) search_results = \ - self.http_cache[bible].get_bible_chapter( - bible, bookname, chapter) - if search_results.has_verselist() : + self.http_cache[bible].get_chapter(bible, book, chapter) + 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 - book = self.db_cache[bible].get_bible_book( - bookname) - if book is None: + db_book = self.db_cache[bible].get_book(bookname) + if db_book is None: ## Then create book, chapter and text - book = self.db_cache[bible].create_book( + db_book = self.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) + db_book, db_book.id, db_book.name) self.db_cache[bible].create_chapter( - book.id, search_results.get_chapter(), + db_book.id, search_results.get_chapter(), search_results.get_verselist()) else: ## Book exists check chapter and texts only. - v = self.db_cache[bible].get_bible_chapter( - book.id, chapter) + v = self.db_cache[bible].get_chapter( + db_book.id, chapter) if v is None: self.media.setQuickMessage( unicode(self.media.trUtf8('%Downloading %s: %s'))\ - % (bookname, chapter)) + % (book, chapter)) self.db_cache[bible].create_chapter( - book.id, chapter, + db_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.db_cache[bible].get_bible_chapter( - book.id, chapter) + v = self.db_cache[bible].get_chapter(db_book.id, chapter) if v is None: try: self.media.setQuickMessage(\ unicode(self.media.trUtf8('Downloading %s: %s')) - % (bookname, chapter)) + % (book, chapter)) search_results = \ - self.http_cache[bible].get_bible_chapter( - bible, bookname, chapter) + self.http_cache[bible].get_chapter( + bible, bookn, chapter) if search_results.has_verselist(): self.db_cache[bible].create_chapter( - book.id, search_results.get_chapter(), + db_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.db_cache[bible].get_bible_text(bookname, - schapter, sverse, everse) + text = self.db_cache[bible].get_verses( + [(book, schapter, sverse, everse)]) else: - for i in range (schapter, echapter + 1): - if i == schapter: + verse_list = [] + for chapter in range(schapter, echapter + 1): + if chapter == schapter: start = sverse - end = self.get_book_verse_count(bible, bookname, i) - elif i == echapter: + end = self.get_verse_count(bible, book, chapter) + elif chapter == echapter: start = 1 end = everse else: start = 1 - end = self.get_book_verse_count(bible, bookname, i) - - txt = self.db_cache[bible].get_bible_text( - bookname, i, start, end) - text.extend(txt) + end = self.get_verse_count(bible, book, chapter) + verse_list.append((bible, chapter, start, end)) + text = self.db_cache[bible].get_verses(verse_list) return text def exists(self, name): diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index 64a4e2462..cc2cb90e8 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -308,7 +308,7 @@ class BibleMediaItem(MediaManagerItem): self.QuickVersionComboBox.addItem(bible) self.QuickSecondBibleComboBox.addItem(bible) # Without HTTP - bibles = self.parent.biblemanager.get_bibles(BibleMode.Partial) + #bibles = self.parent.biblemanager.get_bibles(BibleMode.Partial) first = True # load bibles into the combo boxes for bible in bibles: @@ -362,8 +362,9 @@ class BibleMediaItem(MediaManagerItem): chapter_to = int(self.AdvancedToChapter.currentText()) verse_from = int(self.AdvancedFromVerse.currentText()) verse_to = int(self.AdvancedToVerse.currentText()) - self.search_results = self.parent.biblemanager.get_verse_text( - bible, book, chapter_from, chapter_to, verse_from, verse_to) + versetext = u'%s %s:%s-%s:%s' % (book, chapter_from, verse_from, \ + chapter_to, verse_to) + self.search_results = self.parent.manager.get_verses(bible, versetext) if self.ClearAdvancedSearchComboBox.currentIndex() == 0: self.ListView.clear() self.displayResults(bible) @@ -384,11 +385,12 @@ class BibleMediaItem(MediaManagerItem): text = unicode(self.QuickSearchEdit.displayText()) if self.ClearQuickSearchComboBox.currentIndex() == 0: self.ListView.clear() - if self.QuickSearchComboBox.currentIndex() == 1: - self.search_results = \ - self.parent.biblemanager.get_verses(bible, text) - else: - self.searchByReference(bible, text) + #if self.QuickSearchComboBox.currentIndex() == 1: + # self.search_results = \ + # self.parent.biblemanager.get_verses(bible, text) + #else: + # self.searchByReference(bible, text) + self.search_results = self.parent.biblemanager.get_verses(bible, text) if self.search_results: self.displayResults(bible) @@ -484,18 +486,18 @@ class BibleMediaItem(MediaManagerItem): def initialiseBible(self, bible): log.debug(u'initialiseBible %s', bible) - book_data = self.parent.biblemanager.get_bible_books() + book_data = self.parent.biblemanager.get_bible_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'])) if first: first = False self.initialiseChapterVerse( - bible, book[u'book'], book[u'total']) + bible, book[u'name'], book[u'total']) def initialiseChapterVerse(self, bible, book, chapters): log.debug(u'initialiseChapterVerse %s, %s', bible, book) @@ -533,85 +535,95 @@ class BibleMediaItem(MediaManagerItem): def searchByReference(self, bible, search): log.debug(u'searchByReference %s, %s', bible, search) - book = u'' - start_chapter = u'' - end_chapter = u'' - start_verse = u'' - end_verse = u'' - search = search.replace(u' ', u' ').strip() - #original = search - message = None - # Remove book beware 0 index arrays - for i in range (len(search)-1, 0, - 1): - if search[i] == u' ': - book = search[:i] - # remove book from string - search = search[i:] - break - # allow V or v for verse instead of : - search = search.replace(u'v', ':') - search = search.replace(u'V', ':') - search = search.strip() - colon = search.find(u':') - if colon == -1: - # number : found - i = search.rfind(u' ') - if i == -1: - chapter = u'' - else: - chapter = search[i:len(search)] - hyphen = chapter.find(u'-') - if hyphen != -1: - start_chapter= chapter[:hyphen] - end_chapter= chapter[hyphen + 1:len(chapter)] - else: - start_chapter = chapter - else: - # more complex - sp = search.split(u'-') #find first - sp1 = sp[0].split(u':') - if len(sp1) == 1: - start_chapter = sp1[0] - start_verse = 1 - else: - start_chapter = sp1[0] - start_verse = sp1[1] - if len(sp)== 1: - end_chapter = start_chapter - end_verse = start_verse - else: - sp1 = sp[1].split(u':') - if len(sp1) == 1: - end_chapter = start_chapter - end_verse = sp1[0] - else: - end_chapter = sp1[0] - end_verse = sp1[1] - if end_chapter == u'': - end_chapter = start_chapter.rstrip() - if start_verse == u'': - if end_verse == u'': - start_verse = 1 - else: - start_verse = end_verse - if end_verse == u'': - end_verse = 99 - if start_chapter == u'': - message = self.trUtf8('No chapter found for search criteria') - log.debug(u'results = %s @ %s : %s @ %s : %s'% \ - (unicode(book), unicode(start_chapter), unicode(end_chapter), - unicode(start_verse), unicode(end_verse))) - if message is None: - self.search_results = None - self.search_results = self.parent.biblemanager.get_verse_text( - bible, book, int(start_chapter), int(end_chapter), - int(start_verse), int(end_verse)) - self.copyright = unicode(self.parent.biblemanager.get_meta_data( - bible, u'Copyright').value) - self.permissions = unicode(self.parent.biblemanager.get_meta_data( - bible, u'Permissions').value) - self.version = unicode(self.parent.biblemanager.get_meta_data( - bible, u'Version').value) - else: - QtGui.QMessageBox.information( - self, self.trUtf8('Information'), message) \ No newline at end of file + self.search_results = self.parent.biblemanager.get_verses(bible, search) + 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) + +# 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) From 9beb6c7db54674ff2724a472ac9daa862254cda0 Mon Sep 17 00:00:00 2001 From: Tim Bentley <tim.bentley@gmail.com> Date: Mon, 25 Jan 2010 20:34:47 +0000 Subject: [PATCH 06/33] Add Image layer and rename text layer --- openlp/core/ui/maindisplay.py | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index a4ff53567..933aa93d7 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -96,8 +96,10 @@ class MainDisplay(DisplayWidget): self.audio = Phonon.AudioOutput(Phonon.VideoCategory, self.mediaObject) Phonon.createPath(self.mediaObject, self.video) Phonon.createPath(self.mediaObject, self.audio) - self.display = QtGui.QLabel(self) - self.display.setScaledContents(True) + self.display_image = QtGui.QLabel(self) + self.display_image.setScaledContents(True) + self.display_text = QtGui.QLabel(self) + self.display_text.setScaledContents(True) self.alertDisplay = QtGui.QLabel(self) self.alertDisplay.setScaledContents(True) self.primary = True @@ -123,7 +125,7 @@ class MainDisplay(DisplayWidget): QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'media_play'), self.onMediaPlay) QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'media_pause'), self.onMediaPaws) + QtCore.SIGNAL(u'media_pause'), self.onMediaPause) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'media_stop'), self.onMediaStop) @@ -143,7 +145,9 @@ class MainDisplay(DisplayWidget): QtCore.QRect(0, self.alertScreenPosition, self.screen[u'size'].width(),self.alertHeight)) self.video.setGeometry(self.screen[u'size']) - self.display.resize(self.screen[u'size'].width(), + self.display_image.resize(self.screen[u'size'].width(), + self.screen[u'size'].height()) + self.display_text.resize(self.screen[u'size'].width(), self.screen[u'size'].height()) #Build a custom splash screen self.InitialFrame = QtGui.QImage( @@ -200,18 +204,18 @@ class MainDisplay(DisplayWidget): if not self.displayBlank: if transition: if self.frame is not None: - self.display.setPixmap(QtGui.QPixmap.fromImage(self.frame)) + self.display_text.setPixmap(QtGui.QPixmap.fromImage(self.frame)) self.repaint() self.frame = None if frame[u'trans'] is not None: - self.display.setPixmap(QtGui.QPixmap.fromImage(frame[u'trans'])) + self.display_text.setPixmap(QtGui.QPixmap.fromImage(frame[u'trans'])) self.repaint() self.frame = frame[u'trans'] - self.display.setPixmap(QtGui.QPixmap.fromImage(frame[u'main'])) + self.display_text.setPixmap(QtGui.QPixmap.fromImage(frame[u'main'])) self.display_frame = frame[u'main'] self.repaint() else: - self.display.setPixmap(QtGui.QPixmap.fromImage(frame)) + self.display_text.setPixmap(QtGui.QPixmap.fromImage(frame)) self.display_frame = frame if not self.isVisible(): self.setVisible(True) @@ -220,10 +224,10 @@ class MainDisplay(DisplayWidget): def blankDisplay(self, blanked=True): if blanked: self.displayBlank = True - self.display.setPixmap(QtGui.QPixmap.fromImage(self.blankFrame)) + self.display_text.setPixmap(QtGui.QPixmap.fromImage(self.blankFrame)) else: self.displayBlank = False - if self.display_frame: + if self.display_text_frame: self.frameView(self.display_frame) # if blanked != self.parent.LiveController.blankButton.isChecked(): # self.parent.LiveController.blankButton.setChecked(self.displayBlank) @@ -285,7 +289,7 @@ class MainDisplay(DisplayWidget): def onMediaQueue(self, message): log.debug(u'Queue new media message %s' % message) - self.display.close() + self.display_text.close() file = os.path.join(message[1], message[2]) if self.firstTime: self.mediaObject.setCurrentSource(Phonon.MediaSource(file)) @@ -301,7 +305,8 @@ class MainDisplay(DisplayWidget): self.display_frame = self.blankFrame self.firstTime = True self.mediaLoaded = True - self.display.hide() + self.display_image.hide() + self.display_text.hide() self.alertDisplay.hide() self.video.setFullScreen(True) self.video.setVisible(True) @@ -309,7 +314,7 @@ class MainDisplay(DisplayWidget): if self.primary: self.setVisible(True) - def onMediaPaws(self): + def onMediaPause(self): log.debug(u'Media paused by user') self.mediaObject.pause() @@ -326,5 +331,5 @@ class MainDisplay(DisplayWidget): self.mediaObject.clearQueue() self.mediaLoaded = False self.video.setVisible(False) - self.display.show() + self.display_text.show() self.blankDisplay(False) From 04c68a075eec20c5ac6a755534f30ba4372be3a0 Mon Sep 17 00:00:00 2001 From: Tim Bentley <tim.bentley@gmail.com> Date: Tue, 26 Jan 2010 19:16:47 +0000 Subject: [PATCH 07/33] More Image Layer changes --- openlp/core/lib/rendermanager.py | 18 ------------------ openlp/core/ui/maindisplay.py | 22 ++++++++++++++++++---- openlp/plugins/images/lib/mediaitem.py | 5 ++--- 3 files changed, 20 insertions(+), 25 deletions(-) diff --git a/openlp/core/lib/rendermanager.py b/openlp/core/lib/rendermanager.py index 78e99506a..600a029c0 100644 --- a/openlp/core/lib/rendermanager.py +++ b/openlp/core/lib/rendermanager.py @@ -64,8 +64,6 @@ class RenderManager(object): self.theme_level = u'' self.override_background = None self.themedata = None - self.save_bg_frame = None - self.override_background_changed = False def update_display(self, screen_number): """ @@ -134,22 +132,6 @@ class RenderManager(object): self.calculate_default(self.screens.current[u'size']) self.renderer.set_theme(self.themedata) self.build_text_rectangle(self.themedata) - #Replace the background image from renderer with one from image - if self.override_background: - if self.save_bg_frame is None: - self.save_bg_frame = self.renderer.bg_frame - if self.override_background_changed: - self.renderer.bg_frame = resize_image( - self.override_background, self.width, self.height) - self.override_background_changed = False - else: - if self.override_background_changed: - self.renderer.bg_frame = resize_image( - self.override_background, self.width, self.height) - self.override_background_changed = False - if self.save_bg_frame: - self.renderer.bg_frame = self.save_bg_frame - self.save_bg_frame = None def build_text_rectangle(self, theme): """ diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 933aa93d7..62d5b2f21 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -30,7 +30,7 @@ import time from PyQt4 import QtCore, QtGui from PyQt4.phonon import Phonon -from openlp.core.lib import Receiver +from openlp.core.lib import Receiver, resize_image class DisplayWidget(QtGui.QWidget): """ @@ -162,7 +162,7 @@ class MainDisplay(DisplayWidget): (self.screen[u'size'].width() - splash_image.width()) / 2, (self.screen[u'size'].height() - splash_image.height()) / 2, splash_image) - self.frameView(self.InitialFrame) + self.display_image.setPixmap(QtGui.QPixmap.fromImage(self.InitialFrame)) #Build a Black screen painter = QtGui.QPainter() self.blankFrame = QtGui.QImage( @@ -171,10 +171,11 @@ class MainDisplay(DisplayWidget): QtGui.QImage.Format_ARGB32_Premultiplied) painter.begin(self.blankFrame) painter.fillRect(self.blankFrame.rect(), QtCore.Qt.red) - #buid a blank transparent image + #build a blank transparent image self.transparent = QtGui.QPixmap(self.screen[u'size'].width(), self.screen[u'size'].height()) self.transparent.fill(QtCore.Qt.transparent) + self.frameView(self.transparent) # To display or not to display? if not self.screen[u'primary']: self.showFullScreen() @@ -194,6 +195,16 @@ class MainDisplay(DisplayWidget): if not self.primary: self.setVisible(True) + def addImageWithText(self, frame): + frame = resize_image(frame, + self.screen[u'size'].width(), + self.screen[u'size'].height() ) + self.display_image.setPixmap(QtGui.QPixmap.fromImage(frame)) +# self.display_image.show() +# if not self.isVisible(): +# self.setVisible(True) +# self.showFullScreen() + def frameView(self, frame, transition=False): """ Called from a slide controller to display a frame @@ -215,7 +226,10 @@ class MainDisplay(DisplayWidget): self.display_frame = frame[u'main'] self.repaint() else: - self.display_text.setPixmap(QtGui.QPixmap.fromImage(frame)) + if isinstance(frame, QtGui.QPixmap): + self.display_text.setPixmap(frame) + else: + self.display_text.setPixmap(QtGui.QPixmap.fromImage(frame)) self.display_frame = frame if not self.isVisible(): self.setVisible(True) diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py index 9ee3a0c6f..8ea1df64b 100644 --- a/openlp/plugins/images/lib/mediaitem.py +++ b/openlp/plugins/images/lib/mediaitem.py @@ -172,7 +172,6 @@ class ImageMediaItem(MediaManagerItem): filename = unicode((bitem.data(QtCore.Qt.UserRole)).toString()) self.OverrideLabel.setText(bitem.text()) frame = QtGui.QImage(unicode(filename)) - self.parent.render_manager.override_background = frame - self.parent.render_manager.override_background_changed = True + self.parent.live_controller.parent.mainDisplay.addImageWithText(frame) else: - MediaManagerItem.onPreviewClick(self) \ No newline at end of file + MediaManagerItem.onPreviewClick(self) From 262ff559534b82ffff463142ddde6f3b22b35d4a Mon Sep 17 00:00:00 2001 From: Raoul Snyman <raoul.snyman@saturnlaboratories.co.za> Date: Wed, 27 Jan 2010 14:35:42 +0200 Subject: [PATCH 08/33] Added bible conversion script. --- scripts/bible-1to2-converter.py | 306 ++++++++++++++++++++++++++++++++ 1 file changed, 306 insertions(+) create mode 100755 scripts/bible-1to2-converter.py diff --git a/scripts/bible-1to2-converter.py b/scripts/bible-1to2-converter.py new file mode 100755 index 000000000..226c1ec2e --- /dev/null +++ b/scripts/bible-1to2-converter.py @@ -0,0 +1,306 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2010 Raoul Snyman # +# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # +# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # +# Carsten Tinggaard # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### + +import sys +import os +import sqlite +import sqlite3 +import re +from optparse import OptionParser +from traceback import format_tb as get_traceback + +# Some global options to be used throughout the import process +verbose = False +debug = False +old_cursor = None +new_cursor = None + +# SQL create statments +create_statements = [ + (u'table "book"', u"""CREATE TABLE book ( + id INTEGER NOT NULL, + testament_id INTEGER, + name VARCHAR(30), + abbreviation VARCHAR(5), + PRIMARY KEY (id), + FOREIGN KEY(testament_id) REFERENCES testament (id) +)"""), + (u'table "metadata"', u"""CREATE TABLE metadata ( + "key" VARCHAR(255) NOT NULL, + value VARCHAR(255), + PRIMARY KEY ("key") +)"""), + (u'table "testament"', u"""CREATE TABLE testament ( + id INTEGER NOT NULL, + name VARCHAR(30), + PRIMARY KEY (id) +)"""), + (u'table "verse"', u"""CREATE TABLE verse ( + id INTEGER NOT NULL, + book_id INTEGER, + chapter INTEGER, + verse INTEGER, + text TEXT, + PRIMARY KEY (id), + FOREIGN KEY(book_id) REFERENCES book (id) +)"""), + (u'index "idx_abbrev"', + u"""CREATE INDEX idx_abbrev ON book (abbreviation, id)"""), + (u'index "idx_chapter_verse_book', + u"""CREATE INDEX idx_chapter_verse_book ON verse (chapter, verse, book_id, id)"""), + (u'index "idx_chapter_verse_text"', + u"""CREATE INDEX idx_chapter_verse_text ON verse (text, verse, book_id, id)"""), + (u'index "idx_name"', + u"""CREATE INDEX idx_name ON book (name, id)""") +] + +def display_sql(sql, params): + prepared_params = [] + for param in params: + if isinstance(param, basestring): + prepared_params.append(u'"%s"' % param) + elif isinstance(param, (int, long)): + prepared_params.append(u'%d' % param) + elif isinstance(param, (float, complex)): + prepared_params.append(u'%f' % param) + else: + prepared_params.append(u'"%s"' % str(param)) + for prepared_param in prepared_params: + sql = sql.replace(u'?', prepared_param, 1) + return sql + +def create_database(): + global new_cursor, create_statements + if debug or verbose: + print 'Creating new database:' + else: + print 'Creating new database...', + for statement_type, sql_create in create_statements: + if debug: + print '... ', sql_create.replace('\n', ' ').replace(' ', ' ') + elif verbose: + print '... creating %s...' % statement_type, + new_cursor.execute(sql_create) + if verbose and not debug: + print 'done.' + if not verbose and not debug: + print 'done.' + +def import_bible(): + global old_cursor, new_cursor, debug, verbose + if debug or verbose: + print 'Importing metadata:' + else: + print 'Importing metadata...', + if debug: + print '... SELECT "key", "value" FROM metadata' + elif verbose: + print '... fetching metadata from old database...', + old_cursor.execute(u'SELECT "key", "value" FROM metadata') + rows = old_cursor.fetchall() + if not debug and verbose: + print 'done.' + for row in rows: + key = unicode(row[0], u'cp1252') + value = unicode(row[1], u'cp1252') + sql_insert = u'INSERT INTO metadata '\ + '("key", "value") '\ + 'VALUES (?, ?)' + sql_params = (key, value) + if debug: + print '...', display_sql(sql_insert, sql_params) + elif verbose: + print '... importing "%s"' % key + new_cursor.execute(sql_insert, sql_params) + if not verbose and not debug: + print 'done.' + if debug or verbose: + print 'Importing testaments:' + else: + print 'Importing testaments...', + if debug: + print '... SELECT id, name FROM testament' + elif verbose: + print '... fetching testaments from old database...', + old_cursor.execute(u'SELECT id, name FROM testament') + rows = old_cursor.fetchall() + if not debug and verbose: + print 'done.' + for row in rows: + id = int(row[0]) + name = unicode(row[1], u'cp1252') + sql_insert = u'INSERT INTO testament '\ + '(id, name) '\ + 'VALUES (?, ?)' + sql_params = (id, name) + if debug: + print '...', display_sql(sql_insert, sql_params) + elif verbose: + print '... importing "%s"' % name + new_cursor.execute(sql_insert, sql_params) + if not verbose and not debug: + print 'done.' + if debug or verbose: + print 'Importing books:' + else: + print 'Importing books...', + if debug: + print '... SELECT id, testament_id, name, abbreviation FROM book' + elif verbose: + print '... fetching books from old database...', + old_cursor.execute(u'SELECT id, testament_id, name, abbreviation FROM book') + rows = old_cursor.fetchall() + if not debug and verbose: + print 'done.' + book_map = {} + for row in rows: + testament_id = int(row[1]) + name = unicode(row[2], u'cp1252') + abbreviation = unicode(row[3], u'cp1252') + sql_insert = u'INSERT INTO book '\ + '(id, testament_id, name, abbreviation) '\ + 'VALUES (NULL, ?, ?, ?)' + sql_params = (testament_id, name, abbreviation) + if debug: + print '...', display_sql(sql_insert, sql_params) + elif verbose: + print '... importing "%s"' % name + new_cursor.execute(sql_insert, sql_params) + book_map[row[0]] = new_cursor.lastrowid + if debug: + print ' >>> (old) books.id =', row[0], ' (new) books.id =', book_map[row[0]] + if not verbose and not debug: + print 'done.' + if debug or verbose: + print 'Importing verses:' + else: + print 'Importing verses...', + if debug: + print '... SELECT id, book_id, chapter, verse, text || \'\' AS text FROM verse...', + elif verbose: + print '... fetching verses from old database...', + old_cursor.execute(u'SELECT id, book_id, chapter, verse, text || \'\' AS text FROM verse') + rows = old_cursor.fetchall() + if debug or verbose: + print 'done.' + song_map = {} + for row in rows: + book_id = int(row[1]) + chapter = int(row[2]) + verse = int(row[3]) + text = unicode(row[4], u'cp1252') + sql_insert = u'INSERT INTO verse '\ + '(id, book_id, chapter, verse, text) '\ + 'VALUES (NULL, ?, ?, ?, ?)' + sql_params = (book_map[book_id], chapter, verse, text) + if debug: + print '...', display_sql(sql_insert, sql_params) + elif verbose: + print '... importing "%s..."' % text[:17] + new_cursor.execute(sql_insert, sql_params) + if not verbose and not debug: + print 'done.' + +def main(old_db, new_db): + global old_cursor, new_cursor, debug + old_connection = None + new_connection = None + try: + old_connection = sqlite.connect(old_db) + except: + if debug: + errormsg = '\n' + ''.join(get_traceback(sys.exc_info()[2]))\ + + str(sys.exc_info()[1]) + else: + errormsg = sys.exc_info()[1] + print 'There was a problem connecting to the old database:', errormsg + return 1 + try: + new_connection = sqlite3.connect(new_db) + except: + if debug: + errormsg = '\n' + ''.join(get_traceback(sys.exc_info()[2]))\ + + str(sys.exc_info()[1]) + else: + errormsg = sys.exc_info()[1] + print 'There was a problem creating the new database:', errormsg + return 1 + old_cursor = old_connection.cursor() + new_cursor = new_connection.cursor() + try: + create_database() + except: + if debug: + errormsg = '\n' + ''.join(get_traceback(sys.exc_info()[2]))\ + + str(sys.exc_info()[1]) + else: + errormsg = sys.exc_info()[1] + print 'There was a problem creating the database:', errormsg + return 1 + try: + import_bible() + new_connection.commit() + except: + new_connection.rollback() + if debug: + errormsg = '\n' + ''.join(get_traceback(sys.exc_info()[2]))\ + + str(sys.exc_info()[1]) + else: + errormsg = sys.exc_info()[1] + print 'There was a problem importing songs:', errormsg + return 1 + print 'Import complete.' + +if __name__ == u'__main__': + option_parser = OptionParser(usage='Usage: %prog [options] OLDDATABASE NEWDATABASE') + option_parser.add_option('-o', '--overwrite', dest='overwrite', default=False, + action=u'store_true', help='Overwrite database file if it already exists.') + option_parser.add_option('-v', '--verbose', dest='verbose', default=False, + action=u'store_true', help='Outputs additional progress data.') + option_parser.add_option('-d', '--debug', dest='debug', default=False, + action=u'store_true', help='Outputs raw SQL statements (overrides verbose).') + options, arguments = option_parser.parse_args() + if len(arguments) < 2: + if len(arguments) == 0: + option_parser.error('Please specify an old database and a new database.') + else: + option_parser.error('Please specify a new database.') + old_db = os.path.abspath(arguments[0]) + new_db = os.path.abspath(arguments[1]) + if not os.path.isfile(old_db): + option_parser.error('Old database file ("%s") is not a file.' % old_db) + if not os.path.exists(old_db): + option_parser.error('Old database file ("%s") does not exist.' % old_db) + if os.path.exists(new_db): + if not options.overwrite: + option_parser.error('New database file ("%s") exists. If you want to overwrite it, specify the --overwrite option.' % new_db) + else: + if not os.path.isfile(new_db): + option_parser.error('New database file ("%s") is not a file.' % new_db) + os.unlink(new_db) + verbose = options.verbose + debug = options.debug + main(old_db, new_db) From af5bfe30661de83e9bd915d558c6a35ae334043d Mon Sep 17 00:00:00 2001 From: Tim Bentley <tim.bentley@gmail.com> Date: Thu, 28 Jan 2010 07:15:23 +0000 Subject: [PATCH 09/33] Clean up SongUsage so it now works again --- openlp/core/ui/maindisplay.py | 5 +- openlp/core/ui/thememanager.py | 53 ++++++++++--------- .../songusage/forms/songusagedeleteform.py | 8 +-- .../songusage/forms/songusagedetailform.py | 19 ++++--- openlp/plugins/songusage/songusageplugin.py | 4 +- 5 files changed, 45 insertions(+), 44 deletions(-) diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 62d5b2f21..83e245322 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -241,11 +241,8 @@ class MainDisplay(DisplayWidget): self.display_text.setPixmap(QtGui.QPixmap.fromImage(self.blankFrame)) else: self.displayBlank = False - if self.display_text_frame: + if self.display_frame: self.frameView(self.display_frame) -# if blanked != self.parent.LiveController.blankButton.isChecked(): -# self.parent.LiveController.blankButton.setChecked(self.displayBlank) -# self.parent.generalConfig.set_config(u'screen blank', self.displayBlank) def displayAlert(self, text=u''): """ diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index b2288f75a..0bf005891 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -249,32 +249,33 @@ class ThemeManager(QtGui.QWidget): log.debug(u'Load themes from dir') self.themelist = [] self.ThemeListWidget.clear() - for root, dirs, files in os.walk(self.path): - for name in files: - if name.endswith(u'.png'): - #check to see file is in theme root directory - theme = os.path.join(self.path, name) - if os.path.exists(theme): - (path, filename) = os.path.split(unicode(file)) - textName = os.path.splitext(name)[0] - if textName == self.global_theme: - name = u'%s (%s)' % (textName, - self.trUtf8('default')) - else: - name = textName - thumb = os.path.join(self.thumbPath, u'%s.png' % textName) - item_name = QtGui.QListWidgetItem(name) - if os.path.exists(thumb): - icon = build_icon(thumb) - else: - icon = build_icon(theme) - pixmap = icon.pixmap(QtCore.QSize(88,50)) - pixmap.save(thumb, u'png') - item_name.setIcon(icon) - item_name.setData(QtCore.Qt.UserRole, - QtCore.QVariant(textName)) - self.ThemeListWidget.addItem(item_name) - self.themelist.append(textName) + #root, dirs, files = os.walk(self.path) + dirList = os.listdir(self.path) + for name in dirList: + if name.endswith(u'.png'): + #check to see file is in theme root directory + theme = os.path.join(self.path, name) + if os.path.exists(theme): + (path, filename) = os.path.split(unicode(file)) + textName = os.path.splitext(name)[0] + if textName == self.global_theme: + name = u'%s (%s)' % (textName, + self.trUtf8('default')) + else: + name = textName + thumb = os.path.join(self.thumbPath, u'%s.png' % textName) + item_name = QtGui.QListWidgetItem(name) + if os.path.exists(thumb): + icon = build_icon(thumb) + else: + icon = build_icon(theme) + pixmap = icon.pixmap(QtCore.QSize(88,50)) + pixmap.save(thumb, u'png') + item_name.setIcon(icon) + item_name.setData(QtCore.Qt.UserRole, + QtCore.QVariant(textName)) + self.ThemeListWidget.addItem(item_name) + self.themelist.append(textName) self.pushThemes() def pushThemes(self): diff --git a/openlp/plugins/songusage/forms/songusagedeleteform.py b/openlp/plugins/songusage/forms/songusagedeleteform.py index b20f13c6b..98faf26ad 100644 --- a/openlp/plugins/songusage/forms/songusagedeleteform.py +++ b/openlp/plugins/songusage/forms/songusagedeleteform.py @@ -33,11 +33,11 @@ class SongUsageDeleteForm(QtGui.QDialog, Ui_SongUsageDeleteDialog): """ Class documentation goes here. """ - def __init__(self, auditmanager, parent=None): + def __init__(self, songusagemanager, parent=None): """ Constructor """ - self.auditmanager = auditmanager + self.songusagemanager = songusagemanager QtGui.QDialog.__init__(self, parent) self.setupUi(self) @@ -52,5 +52,5 @@ class SongUsageDeleteForm(QtGui.QDialog, Ui_SongUsageDeleteDialog): if ret == QtGui.QMessageBox.Ok: qDeleteDate = self.DeleteCalendar.selectedDate() deleteDate = date(qDeleteDate.year(), qDeleteDate.month(), qDeleteDate.day()) - self.auditmanager.delete_to_date(deleteDate) - self.close() \ No newline at end of file + self.songusagemanager.delete_to_date(deleteDate) + self.close() diff --git a/openlp/plugins/songusage/forms/songusagedetailform.py b/openlp/plugins/songusage/forms/songusagedetailform.py index 93b6d2e98..ead6b5166 100644 --- a/openlp/plugins/songusage/forms/songusagedetailform.py +++ b/openlp/plugins/songusage/forms/songusagedetailform.py @@ -25,10 +25,14 @@ import os from PyQt4 import QtCore, QtGui +import logging from songusagedetaildialog import Ui_SongUsageDetailDialog class SongUsageDetailForm(QtGui.QDialog, Ui_SongUsageDetailDialog): + global log + log = logging.getLogger(u'SongUsageDetailForm') + log.info(u'SongUsage Detail Form loaded') """ Class documentation goes here. """ @@ -106,19 +110,19 @@ class SongUsageDetailForm(QtGui.QDialog, Ui_SongUsageDetailDialog): self.close() def detailedReport(self): - print "detailed" - filename = u'audit_det_%s_%s.txt' % \ + log.debug(u'Detailed report generated') + filename = u'usage_detail_%s_%s.txt' % \ (self.FromDateEdit.date().toString(u'ddMMyyyy'), self.ToDateEdit.date().toString(u'ddMMyyyy')) - audits = self.parent.auditmanager.get_all_audits() + usage = self.parent.songusagemanager.get_all_songusage() outname = os.path.join(unicode(self.FileLineEdit.text()), filename) file = None try: file = open(outname, u'w') - for audit in audits: + for instance in usage: record = u'\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"\n' % \ - (audit.auditdate,audit.audittime, audit.title, - audit.copyright, audit.ccl_number , audit.authors) + (instance.usagedate,instance.usagetime, instance.title, + instance.copyright, instance.ccl_number , instance.authors) file.write(record) except: log.exception(u'Failed to write out audit records') @@ -127,8 +131,7 @@ class SongUsageDetailForm(QtGui.QDialog, Ui_SongUsageDetailDialog): file.close() def summaryReport(self): - print "summary" + log.debug(u'Summary report generated') filename = u'audit_sum_%s_%s.txt' % \ (self.FromDateEdit.date().toString(u'ddMMyyyy'), self.ToDateEdit.date().toString(u'ddMMyyyy')) - print filename \ No newline at end of file diff --git a/openlp/plugins/songusage/songusageplugin.py b/openlp/plugins/songusage/songusageplugin.py index effc06657..802f73d3d 100644 --- a/openlp/plugins/songusage/songusageplugin.py +++ b/openlp/plugins/songusage/songusageplugin.py @@ -141,7 +141,7 @@ class SongUsagePlugin(Plugin): SongUsageitem.authors = u'' for author in SongUsageData[1]: SongUsageitem.authors += author + u' ' - self.songusagemanager.insert_SongUsage(SongUsageitem) + self.songusagemanager.insert_songusage(SongUsageitem) def onSongUsageDelete(self): self.SongUsagedeleteform.exec_() @@ -154,4 +154,4 @@ class SongUsagePlugin(Plugin): about_text = self.trUtf8('<b>SongUsage Plugin</b><br>This plugin ' 'records the use of songs and when they have been used during ' 'a live service') - return about_text \ No newline at end of file + return about_text From 3baf2f2f7baed56c890aae19b96b4ac7e4250aae Mon Sep 17 00:00:00 2001 From: Tim Bentley <tim.bentley@gmail.com> Date: Thu, 28 Jan 2010 07:39:34 +0000 Subject: [PATCH 10/33] Import the startup showing the update screen --- openlp.pyw | 2 +- openlp/core/ui/mainwindow.py | 3 ++- version.txt | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/openlp.pyw b/openlp.pyw index 3b97a33d9..f1a710f59 100755 --- a/openlp.pyw +++ b/openlp.pyw @@ -131,7 +131,7 @@ class OpenLP(QtGui.QApplication): if show_splash: # now kill the splashscreen self.splash.finish(self.mainWindow) - self.mainWindow.versionCheck() + #self.mainWindow.versionCheck() return self.exec_() def main(): diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 8e93fbf12..b41b6f1b4 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -50,7 +50,6 @@ media_manager_style = """ border-color: palette(light); } """ - class Ui_MainWindow(object): def setupUi(self, MainWindow): """ @@ -582,6 +581,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): self.trUtf8('The Main Display has been blanked out'), QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok), QtGui.QMessageBox.Ok) + self.repaint() + self.versionCheck() def onHelpAboutItemClicked(self): """ diff --git a/version.txt b/version.txt index a41b1ed7a..fcd5e288e 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.9.0-697 +1.9.0-696 From dc7148b76ed587002eaef391eef3abc43a85f2e7 Mon Sep 17 00:00:00 2001 From: Tim Bentley <tim.bentley@gmail.com> Date: Thu, 28 Jan 2010 11:46:25 +0000 Subject: [PATCH 11/33] Fix screen display setup when returning from presentations --- openlp.pyw | 3 ++- openlp/core/ui/maindisplay.py | 8 ++++++++ openlp/core/ui/mainwindow.py | 2 -- version.txt | 2 +- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/openlp.pyw b/openlp.pyw index f1a710f59..03496e70a 100755 --- a/openlp.pyw +++ b/openlp.pyw @@ -131,7 +131,8 @@ class OpenLP(QtGui.QApplication): if show_splash: # now kill the splashscreen self.splash.finish(self.mainWindow) - #self.mainWindow.versionCheck() + self.mainWindow.repaint() + self.mainWindow.versionCheck() return self.exec_() def main(): diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 83e245322..7728fc4c4 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -183,10 +183,13 @@ class MainDisplay(DisplayWidget): else: self.setVisible(False) self.primary = True + self.repaint() def resetDisplay(self): if self.primary: self.setVisible(False) + else: + self.showFullScreen() def hideDisplay(self): self.setVisible(False) @@ -194,6 +197,7 @@ class MainDisplay(DisplayWidget): def showDisplay(self): if not self.primary: self.setVisible(True) + self.showFullScreen() def addImageWithText(self, frame): frame = resize_image(frame, @@ -252,8 +256,11 @@ class MainDisplay(DisplayWidget): display text """ log.debug(u'display alert called %s' % text) + self.parent.StatusBar.showMessage(self.trUtf8(u'')) self.alertList.append(text) if self.timer_id != 0 or self.mediaLoaded: + self.parent.StatusBar.showMessage(\ + self.trUtf8(u'Alert message created and delayed')) return self.generateAlert() @@ -343,4 +350,5 @@ class MainDisplay(DisplayWidget): self.mediaLoaded = False self.video.setVisible(False) self.display_text.show() + self.display_image.show() self.blankDisplay(False) diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index b41b6f1b4..226c629e8 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -581,8 +581,6 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): self.trUtf8('The Main Display has been blanked out'), QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok), QtGui.QMessageBox.Ok) - self.repaint() - self.versionCheck() def onHelpAboutItemClicked(self): """ diff --git a/version.txt b/version.txt index fcd5e288e..a41b1ed7a 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.9.0-696 +1.9.0-697 From dc6be31d1f1c5ed3bdc84dd1246e8708329ee330 Mon Sep 17 00:00:00 2001 From: Tim Bentley <tim.bentley@gmail.com> Date: Thu, 28 Jan 2010 17:36:13 +0000 Subject: [PATCH 12/33] Move changes to get displays working correctly and sort out Impress --- openlp.pyw | 4 +++ openlp/core/ui/maindisplay.py | 27 ++++++++++--------- .../presentations/lib/impresscontroller.py | 2 +- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/openlp.pyw b/openlp.pyw index 03496e70a..58925fdb9 100755 --- a/openlp.pyw +++ b/openlp.pyw @@ -68,6 +68,10 @@ class OpenLP(QtGui.QApplication): global log log.info(u'OpenLP Application Loaded') + def notify(self, obj, evt): + #TODO needed for presentation exceptions + return QtGui.QApplication.notify(self, obj, evt) + def run(self): """ Run the OpenLP application. diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 7728fc4c4..cda5774d6 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -100,8 +100,8 @@ class MainDisplay(DisplayWidget): self.display_image.setScaledContents(True) self.display_text = QtGui.QLabel(self) self.display_text.setScaledContents(True) - self.alertDisplay = QtGui.QLabel(self) - self.alertDisplay.setScaledContents(True) + self.display_alert = QtGui.QLabel(self) + self.display_alert.setScaledContents(True) self.primary = True self.displayBlank = False self.blankFrame = None @@ -141,7 +141,7 @@ class MainDisplay(DisplayWidget): self.setGeometry(self.screen[u'size']) self.alertScreenPosition = self.screen[u'size'].height() * 0.9 self.alertHeight = self.screen[u'size'].height() - self.alertScreenPosition - self.alertDisplay.setGeometry( + self.display_alert.setGeometry( QtCore.QRect(0, self.alertScreenPosition, self.screen[u'size'].width(),self.alertHeight)) self.video.setGeometry(self.screen[u'size']) @@ -163,6 +163,7 @@ class MainDisplay(DisplayWidget): (self.screen[u'size'].height() - splash_image.height()) / 2, splash_image) self.display_image.setPixmap(QtGui.QPixmap.fromImage(self.InitialFrame)) + self.repaint() #Build a Black screen painter = QtGui.QPainter() self.blankFrame = QtGui.QImage( @@ -170,11 +171,13 @@ class MainDisplay(DisplayWidget): self.screen[u'size'].height(), QtGui.QImage.Format_ARGB32_Premultiplied) painter.begin(self.blankFrame) + #TODO make black when testing finished painter.fillRect(self.blankFrame.rect(), QtCore.Qt.red) #build a blank transparent image self.transparent = QtGui.QPixmap(self.screen[u'size'].width(), self.screen[u'size'].height()) self.transparent.fill(QtCore.Qt.transparent) + self.display_alert.setPixmap(self.transparent) self.frameView(self.transparent) # To display or not to display? if not self.screen[u'primary']: @@ -183,7 +186,6 @@ class MainDisplay(DisplayWidget): else: self.setVisible(False) self.primary = True - self.repaint() def resetDisplay(self): if self.primary: @@ -248,6 +250,7 @@ class MainDisplay(DisplayWidget): if self.display_frame: self.frameView(self.display_frame) + def displayAlert(self, text=u''): """ Called from the Alert Tab to display an alert @@ -292,22 +295,24 @@ class MainDisplay(DisplayWidget): painter.drawText( x, y + metrics.height() - metrics.descent() - 1, text) painter.end() - self.alertDisplay.setPixmap(alertframe) - self.alertDisplay.setVisible(True) + self.display_alert.setPixmap(alertframe) + self.display_alert.setVisible(True) # check to see if we have a timer running if self.timer_id == 0: self.timer_id = self.startTimer(int(alertTab.timeout) * 1000) def timerEvent(self, event): if event.timerId() == self.timer_id: - self.alertDisplay.setPixmap(self.transparent) + self.display_alert.setPixmap(self.transparent) self.killTimer(self.timer_id) self.timer_id = 0 self.generateAlert() def onMediaQueue(self, message): log.debug(u'Queue new media message %s' % message) + self.display_image.close() self.display_text.close() + self.display_alert.close() file = os.path.join(message[1], message[2]) if self.firstTime: self.mediaObject.setCurrentSource(Phonon.MediaSource(file)) @@ -325,12 +330,12 @@ class MainDisplay(DisplayWidget): self.mediaLoaded = True self.display_image.hide() self.display_text.hide() - self.alertDisplay.hide() + self.display_alert.hide() self.video.setFullScreen(True) self.video.setVisible(True) self.mediaObject.play() - if self.primary: - self.setVisible(True) + self.setVisible(True) + self.hide() def onMediaPause(self): log.debug(u'Media paused by user') @@ -343,8 +348,6 @@ class MainDisplay(DisplayWidget): def onMediaFinish(self): log.debug(u'Reached end of media playlist') - if self.primary: - self.setVisible(False) self.mediaObject.stop() self.mediaObject.clearQueue() self.mediaLoaded = False diff --git a/openlp/plugins/presentations/lib/impresscontroller.py b/openlp/plugins/presentations/lib/impresscontroller.py index dc0a3bf82..d2a31e202 100644 --- a/openlp/plugins/presentations/lib/impresscontroller.py +++ b/openlp/plugins/presentations/lib/impresscontroller.py @@ -256,7 +256,7 @@ class ImpressController(PresentationController): return False if self.controller is None: return False - return self.controller.isRunning() and self.controller.isActive() + return True def unblank_screen(self): return self.controller.resume() From 04d7a9227ef4bf060f3274fe108349fada7b6358 Mon Sep 17 00:00:00 2001 From: Tim Bentley <tim.bentley@gmail.com> Date: Fri, 29 Jan 2010 11:59:13 +0000 Subject: [PATCH 13/33] Automate Presentation filters --- openlp/plugins/presentations/lib/impresscontroller.py | 1 + openlp/plugins/presentations/lib/mediaitem.py | 10 ++++++++-- .../plugins/presentations/lib/powerpointcontroller.py | 3 ++- openlp/plugins/presentations/lib/pptviewcontroller.py | 1 + .../presentations/lib/presentationcontroller.py | 3 ++- 5 files changed, 14 insertions(+), 4 deletions(-) diff --git a/openlp/plugins/presentations/lib/impresscontroller.py b/openlp/plugins/presentations/lib/impresscontroller.py index d2a31e202..ee15d27be 100644 --- a/openlp/plugins/presentations/lib/impresscontroller.py +++ b/openlp/plugins/presentations/lib/impresscontroller.py @@ -62,6 +62,7 @@ class ImpressController(PresentationController): """ log.debug(u'Initialising') PresentationController.__init__(self, plugin, u'Impress') + self.supports= [u'.odp', u'.ppt', u'.pps'] self.process = None self.document = None self.presentation = None diff --git a/openlp/plugins/presentations/lib/mediaitem.py b/openlp/plugins/presentations/lib/mediaitem.py index c1394c547..0b14f797d 100644 --- a/openlp/plugins/presentations/lib/mediaitem.py +++ b/openlp/plugins/presentations/lib/mediaitem.py @@ -63,7 +63,13 @@ class PresentationMediaItem(MediaManagerItem): def retranslateUi(self): self.OnNewPrompt = self.trUtf8('Select Presentation(s)') - self.OnNewFileMasks = self.trUtf8('Presentations (*.ppt *.pps *.odp)') + fileType = u'' + for controller in self.controllers: + if self.controllers[controller].enabled: + for type in self.controllers[controller].supports: + if fileType.find(type) == -1: + fileType += type + u' ' + self.OnNewFileMasks = self.trUtf8('Presentations (%s)' % fileType) def requiredIcons(self): MediaManagerItem.requiredIcons(self) @@ -151,4 +157,4 @@ class PresentationMediaItem(MediaManagerItem): service_item.add_from_command(path, name, img) i = i + 1 img = controller.get_slide_preview_file(i) - return True \ No newline at end of file + return True diff --git a/openlp/plugins/presentations/lib/powerpointcontroller.py b/openlp/plugins/presentations/lib/powerpointcontroller.py index d64314c76..18b644112 100644 --- a/openlp/plugins/presentations/lib/powerpointcontroller.py +++ b/openlp/plugins/presentations/lib/powerpointcontroller.py @@ -52,6 +52,7 @@ class PowerpointController(PresentationController): """ log.debug(u'Initialising') PresentationController.__init__(self, plugin, u'Powerpoint') + self.supports= [u'.ppt', u'.pps'] self.process = None self.presentation = None @@ -255,4 +256,4 @@ class PowerpointController(PresentationController): if os.path.isfile(path): return path else: - return None \ No newline at end of file + return None diff --git a/openlp/plugins/presentations/lib/pptviewcontroller.py b/openlp/plugins/presentations/lib/pptviewcontroller.py index 02b280540..0cf2405f1 100644 --- a/openlp/plugins/presentations/lib/pptviewcontroller.py +++ b/openlp/plugins/presentations/lib/pptviewcontroller.py @@ -49,6 +49,7 @@ class PptviewController(PresentationController): log.debug(u'Initialising') self.process = None PresentationController.__init__(self, plugin, u'Powerpoint Viewer') + self.supports= [u'.ppt', u'.pps'] self.pptid = None def check_available(self): diff --git a/openlp/plugins/presentations/lib/presentationcontroller.py b/openlp/plugins/presentations/lib/presentationcontroller.py index 82c014b64..ac9581d28 100644 --- a/openlp/plugins/presentations/lib/presentationcontroller.py +++ b/openlp/plugins/presentations/lib/presentationcontroller.py @@ -136,6 +136,7 @@ class PresentationController(object): ``name`` Name of the application, to appear in the application """ + self.supports = [] self.plugin = plugin self.name = name self.available = self.check_available() @@ -313,4 +314,4 @@ class PresentationController(object): else: prefix = u'preview' Receiver.send_message(u'%s_slidecontroller_change' % prefix, - self.slidenumber - 1) \ No newline at end of file + self.slidenumber - 1) From 1fd98217abcb51edae32a585afe1e6b8c13fba84 Mon Sep 17 00:00:00 2001 From: Tim Bentley <tim.bentley@gmail.com> Date: Fri, 29 Jan 2010 13:06:47 +0000 Subject: [PATCH 14/33] Pass active presentation types to other controllers --- openlp/core/lib/eventreceiver.py | 5 ++++- openlp/core/ui/servicemanager.py | 7 ++++++- openlp/plugins/presentations/presentationplugin.py | 10 ++++++++-- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/openlp/core/lib/eventreceiver.py b/openlp/core/lib/eventreceiver.py index f3b43d2b7..e72314652 100644 --- a/openlp/core/lib/eventreceiver.py +++ b/openlp/core/lib/eventreceiver.py @@ -104,6 +104,9 @@ class EventReceiver(QtCore.QObject): ``remote_edit_clear`` Informs all components that remote edit has been aborted. + ``presentation types`` + Informs all components of the presentation types supported. + """ global log log = logging.getLogger(u'EventReceiver') @@ -161,4 +164,4 @@ class Receiver(): """ Get the global ``eventreceiver`` instance. """ - return Receiver.eventreceiver \ No newline at end of file + return Receiver.eventreceiver diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index 44170e616..6bb09a92e 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -225,12 +225,17 @@ class ServiceManager(QtGui.QWidget): QtCore.SIGNAL(u'update_themes'), self.updateThemeList) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'remote_edit_clear'), self.onRemoteEditClear) + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'presentation types'), self.onPresentationTypes) # Last little bits of setting up self.config = PluginConfig(u'ServiceManager') self.servicePath = self.config.get_data_path() self.service_theme = unicode( self.config.get_config(u'service theme', u'')) + def onPresentationTypes(self, presentation_types): + self.presentation_types = presentation_types + def onMoveSelectionUp(self): """ Moves the selection up the window @@ -617,7 +622,7 @@ class ServiceManager(QtGui.QWidget): else: pos = parentitem.data(0, QtCore.Qt.UserRole).toInt()[0] count = item.data(0, QtCore.Qt.UserRole).toInt()[0] - #adjuest for zero based arrays + #adjust for zero based arrays pos = pos - 1 return pos, count diff --git a/openlp/plugins/presentations/presentationplugin.py b/openlp/plugins/presentations/presentationplugin.py index a380e9bb0..502557508 100644 --- a/openlp/plugins/presentations/presentationplugin.py +++ b/openlp/plugins/presentations/presentationplugin.py @@ -26,7 +26,7 @@ import os import logging -from openlp.core.lib import Plugin, build_icon +from openlp.core.lib import Plugin, build_icon, Receiver from openlp.plugins.presentations.lib import * class PresentationPlugin(Plugin): @@ -51,6 +51,12 @@ class PresentationPlugin(Plugin): log.info(u'Presentations Initialising') Plugin.initialise(self) self.insert_toolbox_item() + presentation_types = [] + for controller in self.controllers: + if self.controllers[controller].enabled: + presentation_types.append({u'%s' % controller : self.controllers[controller].supports}) + Receiver.send_message( + u'presentation types', presentation_types) def finalise(self): log.info(u'Plugin Finalise') @@ -106,4 +112,4 @@ class PresentationPlugin(Plugin): 'the ability to show presentations using a number of different ' 'programs. The choice of available presentation programs is ' 'available to the user in a drop down box.') - return about_text \ No newline at end of file + return about_text From 3610b232bda1e1269ce862c19c872f3fd85c6019 Mon Sep 17 00:00:00 2001 From: Tim Bentley <tim.bentley@gmail.com> Date: Fri, 29 Jan 2010 16:38:28 +0000 Subject: [PATCH 15/33] Fix up saving and loading service items --- openlp.pyw | 2 +- openlp/core/ui/servicemanager.py | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/openlp.pyw b/openlp.pyw index 58925fdb9..4741059d2 100755 --- a/openlp.pyw +++ b/openlp.pyw @@ -159,7 +159,7 @@ def main(): help="Set the Qt4 style (passed directly to Qt4).") # Set up logging filename = u'openlp.log' - logfile = FileHandler(filename) + logfile = FileHandler(filename, u'w') logfile.setFormatter(logging.Formatter( u'%(asctime)s %(name)-15s %(levelname)-8s %(message)s')) log.addHandler(logfile) diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index 6bb09a92e..5f384a955 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -438,10 +438,10 @@ class ServiceManager(QtGui.QWidget): for item in self.serviceItems: service.append({u'serviceitem':item[u'service_item'].get_service_repr()}) if item[u'service_item'].uses_file(): - for frame in item[u'service_item'].get_frames: + for frame in item[u'service_item'].get_frames(): path_from = unicode(os.path.join( item[u'service_item'].service_item_path, - frame.get_frame_title())) + frame[u'title'])) zip.write(path_from) file = open(servicefile, u'wb') cPickle.dump(service, file) @@ -504,7 +504,8 @@ class ServiceManager(QtGui.QWidget): serviceitem = ServiceItem() serviceitem.RenderManager = self.parent.RenderManager serviceitem.set_from_service(item, self.servicePath) - self.addServiceItem(serviceitem) + if self.validateItem(serviceitem): + self.addServiceItem(serviceitem) try: if os.path.isfile(p_file): os.remove(p_file) @@ -521,6 +522,14 @@ class ServiceManager(QtGui.QWidget): self.serviceName = name[len(name) - 1] self.parent.serviceChanged(True, self.serviceName) + def validateItem(self, serviceItem): + print "---" + print serviceItem.name + print serviceItem.title + print serviceItem.service_item_path + print serviceItem.service_item_type + return True + def cleanUp(self): """ Empties the servicePath of temporary files From 0e29d0b4afd0863cb41e3bd4f7e53e2a2ae5f7ac Mon Sep 17 00:00:00 2001 From: Raoul Snyman <raoul.snyman@saturnlaboratories.co.za> Date: Fri, 29 Jan 2010 22:20:30 +0200 Subject: [PATCH 16/33] Show a small progress bar rather than a "downloading" message. --- openlp/core/lib/baselistwithdnd.py | 4 +++- openlp/core/lib/eventreceiver.py | 3 ++- openlp/core/lib/mediamanageritem.py | 4 ++-- openlp/plugins/bibles/lib/http.py | 2 +- openlp/plugins/bibles/lib/manager.py | 4 ++-- openlp/plugins/bibles/lib/mediaitem.py | 30 ++++++++++++++++++++++++++ 6 files changed, 40 insertions(+), 7 deletions(-) diff --git a/openlp/core/lib/baselistwithdnd.py b/openlp/core/lib/baselistwithdnd.py index d2537e0e4..f7095550a 100644 --- a/openlp/core/lib/baselistwithdnd.py +++ b/openlp/core/lib/baselistwithdnd.py @@ -32,6 +32,7 @@ class BaseListWithDnD(QtGui.QListWidget): def __init__(self, parent=None): QtGui.QListWidget.__init__(self, parent) + self.parent = parent # this must be set by the class which is inheriting assert(self.PluginName) @@ -47,4 +48,5 @@ class BaseListWithDnD(QtGui.QListWidget): mimeData = QtCore.QMimeData() drag.setMimeData(mimeData) mimeData.setText(self.PluginName) - dropAction = drag.start(QtCore.Qt.CopyAction) \ No newline at end of file + dropAction = drag.start(QtCore.Qt.CopyAction) + diff --git a/openlp/core/lib/eventreceiver.py b/openlp/core/lib/eventreceiver.py index f3b43d2b7..41a18287e 100644 --- a/openlp/core/lib/eventreceiver.py +++ b/openlp/core/lib/eventreceiver.py @@ -161,4 +161,5 @@ class Receiver(): """ Get the global ``eventreceiver`` instance. """ - return Receiver.eventreceiver \ No newline at end of file + return Receiver.eventreceiver + diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py index 6f6f82818..5f490eed1 100644 --- a/openlp/core/lib/mediamanageritem.py +++ b/openlp/core/lib/mediamanageritem.py @@ -253,7 +253,7 @@ class MediaManagerItem(QtGui.QWidget): def addListViewToToolBar(self): #Add the List widget - self.ListView = self.ListViewWithDnD_class() + self.ListView = self.ListViewWithDnD_class(self) self.ListView.uniformItemSizes = True self.ListView.setGeometry(QtCore.QRect(10, 100, 256, 591)) self.ListView.setSpacing(1) @@ -400,4 +400,4 @@ class MediaManagerItem(QtGui.QWidget): if self.generateSlideData(service_item): return service_item else: - return None \ No newline at end of file + return None diff --git a/openlp/plugins/bibles/lib/http.py b/openlp/plugins/bibles/lib/http.py index ff3045107..bd8833105 100644 --- a/openlp/plugins/bibles/lib/http.py +++ b/openlp/plugins/bibles/lib/http.py @@ -247,7 +247,7 @@ class HTTPBible(BibleDB): return None def get_books(self): - return [Book.populate(name=book[u'name']) for book in self.books] + return [Book.populate(name=self.books[book]['name']) for book in self.books] def get_chapter_count(self, book): return self.books[book][u'chap'] diff --git a/openlp/plugins/bibles/lib/manager.py b/openlp/plugins/bibles/lib/manager.py index f6e7fc4ea..88982a8bf 100644 --- a/openlp/plugins/bibles/lib/manager.py +++ b/openlp/plugins/bibles/lib/manager.py @@ -202,8 +202,8 @@ class BibleManager(object): log.debug(u'get_bibles') bible_list = [] for bible_name, bible_object in self.db_cache.iteritems(): - if getattr(bible_object, 'download_source', None): - bible_name = u'%s (%s)' % (bible_name, self.web) + #if getattr(bible_object, 'download_source', None): + # bible_name = u'%s (%s)' % (bible_name, self.web) bible_list.append(bible_name) return bible_list diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index cc2cb90e8..49cede58a 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -42,6 +42,9 @@ class BibleListView(BaseListWithDnD): self.PluginName = u'Bibles' BaseListWithDnD.__init__(self, parent) + def resizeEvent(self, event): + self.parent.onListViewResize(event.size().width(), event.size().width()) + class BibleMediaItem(MediaManagerItem): """ @@ -242,6 +245,20 @@ class BibleMediaItem(MediaManagerItem): QtCore.SIGNAL(u'pressed()'), self.onQuickSearchButton) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'config_updated'), self.configUpdated) + # Other stuff + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'')) + + 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( @@ -319,6 +336,19 @@ class BibleMediaItem(MediaManagerItem): # 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, value): + self.SearchProgress.setVisible(True) + self.SearchProgress.setValue(value) + + def onSearchProgressHide(self, value): + self.SearchProgress.setVisible(True) + self.SearchProgress.setValue(value) + def onAdvancedVersionComboBox(self): self.initialiseBible( unicode(self.AdvancedVersionComboBox.currentText())) From 0cbb079aa3d73df174df61474b7406bd7142222d Mon Sep 17 00:00:00 2001 From: Raoul Snyman <raoul.snyman@saturnlaboratories.co.za> Date: Fri, 29 Jan 2010 23:26:24 +0200 Subject: [PATCH 17/33] Added the little progress bar back in. --- openlp/plugins/bibles/lib/http.py | 10 ++++++++-- openlp/plugins/bibles/lib/mediaitem.py | 10 ++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/openlp/plugins/bibles/lib/http.py b/openlp/plugins/bibles/lib/http.py index 5c9610bf6..a4caeb0f3 100644 --- a/openlp/plugins/bibles/lib/http.py +++ b/openlp/plugins/bibles/lib/http.py @@ -28,6 +28,7 @@ import urllib2 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 @@ -208,12 +209,17 @@ class HTTPBible(BibleDB): [(u'Genesis', 1, 1, 1), (u'Genesis', 2, 2, 3)] """ Receiver.send_message(u'bible_showprogress') + Receiver.send_message(u'process_events') 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_hideprogress') + Receiver.send_message(u'bible_nobook') + return [] db_book = self.create_book(book_details[u'name'], book_details[u'abbr'], book_details[u'test']) book = db_book.name @@ -266,7 +272,7 @@ class HTTPBible(BibleDB): return self.books[book] else: for details in self.books: - if details[u'abbr'] == book: - return details + if self.books[details][u'abbr'] == book: + return self.books[details] return None diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index 9f9840fef..9390cf642 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -250,6 +250,8 @@ class BibleMediaItem(MediaManagerItem): 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) @@ -351,6 +353,14 @@ class BibleMediaItem(MediaManagerItem): 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())) From baabcba2905ac7f034c5a57f8e0beefbe81fce10 Mon Sep 17 00:00:00 2001 From: Raoul Snyman <raoul.snyman@saturnlaboratories.co.za> Date: Fri, 29 Jan 2010 23:35:02 +0200 Subject: [PATCH 18/33] Changed the value of the progress bar to look a little more "active" --- openlp/plugins/bibles/lib/http.py | 2 ++ openlp/plugins/bibles/lib/mediaitem.py | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/openlp/plugins/bibles/lib/http.py b/openlp/plugins/bibles/lib/http.py index a4caeb0f3..a1041d98f 100644 --- a/openlp/plugins/bibles/lib/http.py +++ b/openlp/plugins/bibles/lib/http.py @@ -128,6 +128,7 @@ class CWExtract(BibleCommon): 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: @@ -235,6 +236,7 @@ class HTTPBible(BibleDB): db_book = self.get_book(bookname) self.create_chapter(db_book.id, search_results.get_chapter(), search_results.get_verselist()) + Receiver.send_message(u'process_events') Receiver.send_message(u'bible_hideprogress') return BibleDB.get_verses(self, reference_list) diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index 9390cf642..341d36c6f 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -348,7 +348,8 @@ class BibleMediaItem(MediaManagerItem): def onSearchProgressShow(self): self.SearchProgress.setVisible(True) self.SearchProgress.setMinimum(0) - self.SearchProgress.setMaximum(0) + self.SearchProgress.setMaximum(2) + self.SearchProgress.setValue(1) def onSearchProgressHide(self): self.SearchProgress.setVisible(False) From d45a9733af5dcac5f1882339d8ab142b5de96d63 Mon Sep 17 00:00:00 2001 From: Raoul Snyman <raoul.snyman@saturnlaboratories.co.za> Date: Sat, 30 Jan 2010 00:26:30 +0200 Subject: [PATCH 19/33] Fixed a bug in Windows and other versions of PyQt4 where "setProperty" was not available. Changed it to "setValue" which is what it's meant to be anyways. --- openlp/plugins/bibles/forms/bibleimportwizard.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openlp/plugins/bibles/forms/bibleimportwizard.py b/openlp/plugins/bibles/forms/bibleimportwizard.py index 1f655a52d..ec190182a 100644 --- a/openlp/plugins/bibles/forms/bibleimportwizard.py +++ b/openlp/plugins/bibles/forms/bibleimportwizard.py @@ -302,8 +302,7 @@ class Ui_BibleImportWizard(object): self.ImportProgressLabel.setObjectName(u'ImportProgressLabel') self.ImportLayout.addWidget(self.ImportProgressLabel) self.ImportProgressBar = QtGui.QProgressBar(self.ImportPage) - self.ImportProgressBar.setProperty(u'value', 0) - self.ImportProgressBar.setInvertedAppearance(False) + self.ImportProgressBar.setValue(0) self.ImportProgressBar.setObjectName(u'ImportProgressBar') self.ImportLayout.addWidget(self.ImportProgressBar) BibleImportWizard.addPage(self.ImportPage) From ab7125c98ec6b2d19b661a831eb44d080e61efc5 Mon Sep 17 00:00:00 2001 From: Raoul Snyman <raoul.snyman@saturnlaboratories.co.za> Date: Sat, 30 Jan 2010 10:42:03 +0200 Subject: [PATCH 20/33] Make the progress bar only pop up when we *actually* fetch a verse from the Internet --- openlp/plugins/bibles/lib/http.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/openlp/plugins/bibles/lib/http.py b/openlp/plugins/bibles/lib/http.py index a1041d98f..5b75407be 100644 --- a/openlp/plugins/bibles/lib/http.py +++ b/openlp/plugins/bibles/lib/http.py @@ -209,8 +209,6 @@ class HTTPBible(BibleDB): [(u'Genesis', 1, 1, 1), (u'Genesis', 2, 2, 3)] """ - Receiver.send_message(u'bible_showprogress') - Receiver.send_message(u'process_events') for reference in reference_list: log.debug('Reference: %s', reference) book = reference[0] @@ -218,13 +216,14 @@ class HTTPBible(BibleDB): if not db_book: book_details = self.lookup_book(book) if not book_details: - Receiver.send_message(u'bible_hideprogress') Receiver.send_message(u'bible_nobook') return [] db_book = self.create_book(book_details[u'name'], book_details[u'abbr'], book_details[u'test']) book = db_book.name if self.get_verse_count(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 @@ -236,8 +235,8 @@ class HTTPBible(BibleDB): 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') - Receiver.send_message(u'bible_hideprogress') return BibleDB.get_verses(self, reference_list) def get_chapter(self, version, book, chapter): From 2b5ddb13a430779d7a093ba5164d4b4d6d9eaf91 Mon Sep 17 00:00:00 2001 From: Raoul Snyman <raoul.snyman@saturnlaboratories.co.za> Date: Sun, 31 Jan 2010 21:49:01 +0200 Subject: [PATCH 21/33] An attempt to fix the problems some folks are having. --- openlp/plugins/bibles/bibleplugin.py | 4 +- .../plugins/bibles/forms/bibleimportwizard.py | 13 +----- .../plugins/bibles/forms/importwizardform.py | 44 ++++++++----------- openlp/plugins/bibles/lib/csvbible.py | 4 +- openlp/plugins/bibles/lib/db.py | 3 +- openlp/plugins/bibles/lib/http.py | 19 ++++---- openlp/plugins/bibles/lib/manager.py | 28 +++++++----- openlp/plugins/bibles/lib/mediaitem.py | 2 +- openlp/plugins/bibles/lib/opensong.py | 33 ++++++-------- openlp/plugins/bibles/lib/osis.py | 4 +- openlp/plugins/custom/forms/editcustomform.py | 10 ++--- openlp/plugins/songs/lib/mediaitem.py | 11 +++-- 12 files changed, 80 insertions(+), 95 deletions(-) diff --git a/openlp/plugins/bibles/bibleplugin.py b/openlp/plugins/bibles/bibleplugin.py index 912a02212..5fafac65b 100644 --- a/openlp/plugins/bibles/bibleplugin.py +++ b/openlp/plugins/bibles/bibleplugin.py @@ -45,7 +45,7 @@ class BiblePlugin(Plugin): def initialise(self): log.info(u'bibles Initialising') if self.biblemanager is None: - self.biblemanager = BibleManager(self.config) + self.biblemanager = BibleManager(self, self.config) Plugin.initialise(self) self.insert_toolbox_item() self.ImportBibleItem.setVisible(True) @@ -90,4 +90,4 @@ class BiblePlugin(Plugin): about_text = self.trUtf8('<strong>Bible Plugin</strong><br />This ' 'plugin allows bible verses from different sources to be ' 'displayed on the screen during the service.') - return about_text \ No newline at end of file + return about_text diff --git a/openlp/plugins/bibles/forms/bibleimportwizard.py b/openlp/plugins/bibles/forms/bibleimportwizard.py index ec190182a..59e38e39a 100644 --- a/openlp/plugins/bibles/forms/bibleimportwizard.py +++ b/openlp/plugins/bibles/forms/bibleimportwizard.py @@ -91,15 +91,6 @@ class Ui_BibleImportWizard(object): self.OsisLayout.setMargin(0) self.OsisLayout.setSpacing(8) self.OsisLayout.setObjectName(u'OsisLayout') - self.OsisBibleNameLabel = QtGui.QLabel(self.OsisPage) - self.OsisBibleNameLabel.setIndent(0) - self.OsisBibleNameLabel.setObjectName(u'OsisBibleNameLabel') - self.OsisLayout.setWidget(0, QtGui.QFormLayout.LabelRole, - self.OsisBibleNameLabel) - self.OsisBibleNameEdit = QtGui.QLineEdit(self.OsisPage) - self.OsisBibleNameEdit.setObjectName(u'OsisBibleNameEdit') - self.OsisLayout.setWidget(0, QtGui.QFormLayout.FieldRole, - self.OsisBibleNameEdit) self.OsisLocationLabel = QtGui.QLabel(self.OsisPage) self.OsisLocationLabel.setObjectName(u'OsisLocationLabel') self.OsisLayout.setWidget(1, QtGui.QFormLayout.LabelRole, @@ -307,7 +298,6 @@ class Ui_BibleImportWizard(object): self.ImportLayout.addWidget(self.ImportProgressBar) BibleImportWizard.addPage(self.ImportPage) - self.retranslateUi(BibleImportWizard) self.FormatWidget.setCurrentIndex(0) self.WebDownloadTabWidget.setCurrentIndex(0) @@ -333,7 +323,6 @@ class Ui_BibleImportWizard(object): self.FormatComboBox.setItemText(1, self.trUtf8('CSV')) self.FormatComboBox.setItemText(2, self.trUtf8('OpenSong')) self.FormatComboBox.setItemText(3, self.trUtf8('Web Download')) - self.OsisBibleNameLabel.setText(self.trUtf8('Bible Name:')) self.OsisLocationLabel.setText(self.trUtf8('File Location:')) self.BooksLocationLabel.setText(self.trUtf8('Books Location:')) self.VerseLocationLabel.setText(self.trUtf8('Verse Location:')) @@ -361,4 +350,4 @@ class Ui_BibleImportWizard(object): self.ImportPage.setSubTitle( self.trUtf8('Please wait while your Bible is imported.')) self.ImportProgressLabel.setText(self.trUtf8('Ready.')) - #self.ImportProgressBar.setFormat(u'%p') + self.ImportProgressBar.setFormat(u'%p%') diff --git a/openlp/plugins/bibles/forms/importwizardform.py b/openlp/plugins/bibles/forms/importwizardform.py index 4fcb18ad4..8be453db0 100644 --- a/openlp/plugins/bibles/forms/importwizardform.py +++ b/openlp/plugins/bibles/forms/importwizardform.py @@ -27,6 +27,7 @@ import logging import os import os.path from time import sleep +import csv from PyQt4 import QtCore, QtGui @@ -107,14 +108,6 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): elif self.currentId() == 1: # Select page if self.field(u'source_format').toInt()[0] == BibleFormat.OSIS: - if self.field(u'osis_biblename').toString() == u'': - QtGui.QMessageBox.critical(self, - self.trUtf8('Invalid Bible Name'), - self.trUtf8('You need to specify a name for your ' - 'Bible!'), - QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok)) - self.OsisBibleNameEdit.setFocus() - return False if self.field(u'osis_location').toString() == u'': QtGui.QMessageBox.critical(self, self.trUtf8('Invalid Bible Location'), @@ -218,8 +211,6 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): def registerFields(self): self.SelectPage.registerField( u'source_format', self.FormatComboBox) - self.SelectPage.registerField( - u'osis_biblename', self.OsisBibleNameEdit) self.SelectPage.registerField( u'osis_location', self.OSISLocationEdit) self.SelectPage.registerField( @@ -247,7 +238,6 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): def setDefaults(self): self.setField(u'source_format', 0) - self.setField(u'osis_biblename', u'') self.setField(u'osis_location', u'') self.setField(u'csv_booksfile', u'') self.setField(u'csv_versefile', u'') @@ -276,29 +266,33 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): fbibles = None try: self.web_bible_list[DownloadLocation.Crosswalk] = {} - fbibles = open(os.path.join(filepath, u'crosswalkbooks.csv'), 'r') - for line in fbibles: - parts = line.split(u',') - self.web_bible_list[DownloadLocation.Crosswalk][parts[0]] = \ - parts[1].rstrip() + books_file = open(os.path.join(filepath, u'crosswalkbooks.csv'), 'r') + dialect = csv.Sniffer().sniff(books_file.read(1024)) + books_file.seek(0) + books_reader = csv.reader(books_file, dialect) + for line in books_reader: + self.web_bible_list[DownloadLocation.Crosswalk][line[0]] = \ + unicode(line[1], u'utf-8').strip() except: log.exception(u'Crosswalk resources missing') finally: - if fbibles: - fbibles.close() + if books_file: + books_file.close() #Load and store BibleGateway Bibles try: self.web_bible_list[DownloadLocation.BibleGateway] = {} - fbibles = open(os.path.join(filepath, u'biblegateway.csv'), 'r') - for line in fbibles: - parts = line.split(u',') - self.web_bible_list[DownloadLocation.BibleGateway][parts[0]] = \ - parts[1].rstrip() + books_file = open(os.path.join(filepath, u'biblegateway.csv'), 'r') + dialect = csv.Sniffer().sniff(books_file.read(1024)) + books_file.seek(0) + books_reader = csv.reader(books_file, dialect) + for line in books_reader: + self.web_bible_list[DownloadLocation.BibleGateway][line[0]] = \ + unicode(line[1], u'utf-8').strip() except: log.exception(u'Biblegateway resources missing') finally: - if fbibles: - fbibles.close() + if books_file: + books_file.close() def getFileName(self, title, editbox): filename = QtGui.QFileDialog.getOpenFileName(self, title, diff --git a/openlp/plugins/bibles/lib/csvbible.py b/openlp/plugins/bibles/lib/csvbible.py index f98ef0c86..d0db5159d 100644 --- a/openlp/plugins/bibles/lib/csvbible.py +++ b/openlp/plugins/bibles/lib/csvbible.py @@ -37,13 +37,13 @@ class CSVBible(BibleDB): This class provides a specialisation for importing of CSV Bibles. """ - def __init__(self, **kwargs): + 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. """ - BibleDB.__init__(self, **kwargs) + 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.') diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py index 2131737fd..5c7229f4a 100644 --- a/openlp/plugins/bibles/lib/db.py +++ b/openlp/plugins/bibles/lib/db.py @@ -42,7 +42,7 @@ class BibleDB(QtCore.QObject): rather than depending on yet another object. """ - def __init__(self, **kwargs): + def __init__(self, parent, **kwargs): """ The constructor loads up the database and creates and initialises the tables if the database doesn't exist. @@ -60,6 +60,7 @@ class BibleDB(QtCore.QObject): 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: diff --git a/openlp/plugins/bibles/lib/http.py b/openlp/plugins/bibles/lib/http.py index 5b75407be..4472000d5 100644 --- a/openlp/plugins/bibles/lib/http.py +++ b/openlp/plugins/bibles/lib/http.py @@ -142,7 +142,7 @@ class CWExtract(BibleCommon): class HTTPBible(BibleDB): log.info(u'%s loaded', __name__) - def __init__(self, **kwargs): + def __init__(self, parent, **kwargs): """ Finds all the bibles defined for the system Creates an Interface Object for each bible containing connection @@ -152,7 +152,7 @@ class HTTPBible(BibleDB): Init confirms the bible exists and stores the database path. """ - BibleDB.__init__(self, **kwargs) + 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: @@ -267,13 +267,10 @@ class HTTPBible(BibleDB): def set_books(self, books): self.books = books - def lookup_book(self, book): - log.debug('Looking up "%s" in %s', (book, self.books)) - if book in self.books: - return self.books[book] - else: - for details in self.books: - if self.books[details][u'abbr'] == book: - return self.books[details] - return None + def lookup_book(self, name): + log.debug('Looking up "%s" in %s', (name, self.books)) + for book in self.books: + if book[u'name'] == name or book[u'abbr'] == name: + return book + return None diff --git a/openlp/plugins/bibles/lib/manager.py b/openlp/plugins/bibles/lib/manager.py index 88982a8bf..3ca76bbab 100644 --- a/openlp/plugins/bibles/lib/manager.py +++ b/openlp/plugins/bibles/lib/manager.py @@ -90,7 +90,7 @@ class BibleManager(object): log = logging.getLogger(u'BibleManager') log.info(u'Bible manager loaded') - def __init__(self, config): + def __init__(self, parent, config): """ Finds all the bibles defined for the system and creates an interface object for each bible containing connection information. Throws @@ -101,8 +101,9 @@ class BibleManager(object): ``config`` The plugin's configuration object. """ - self.config = config log.debug(u'Bible Initialising') + self.config = config + self.parent = parent self.web = u'Web' self.db_cache = None self.http_cache = None @@ -120,18 +121,19 @@ class BibleManager(object): filepath, u'..', u'resources', u'httpbooks.csv')) books_file = None try: - self.http_books = {} + self.http_books = [] books_file = open(filepath, u'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.http_books[line[0]] = { - u'name': line[0], - u'abbr': line[1], + self.http_books.append({ + u'name': unicode(line[0]), + u'abbr': unicode(line[1]), u'test': line[2], - u'chap': line[3] - } + u'chap': line[3], + u'ordr': order + }) except: log.exception(u'Failed to load http books.') finally: @@ -148,13 +150,13 @@ class BibleManager(object): self.web_bibles_present = False for filename in files: name, extension = os.path.splitext(filename) - self.db_cache[name] = BibleDB(path=self.path, name=name, config=self.config) + 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. source = self.db_cache[name].get_meta(u'download source') if source: self.web_bibles_present = True download_name = self.db_cache[name].get_meta(u'download name').value - web_bible = HTTPBible(path=self.path, name=name, + web_bible = HTTPBible(self.parent, path=self.path, name=name, config=self.config, download_source=source.value, download_name=download_name) meta_proxy = self.db_cache[name].get_meta(u'proxy url') @@ -187,7 +189,7 @@ class BibleManager(object): class_ = BibleFormat.get_class(type) kwargs['path'] = self.path kwargs['config'] = self.config - importer = class_(**kwargs) + importer = class_(self.parent, **kwargs) name = importer.register(self.import_wizard) self.db_cache[name] = importer return importer.do_import() @@ -381,8 +383,12 @@ class BibleManager(object): """ Check cache to see if new bible """ + if not isinstance(name, unicode): + name = unicode(name, u'utf8') 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, u'utf8') if bible == name: return True return False diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index 341d36c6f..213c79c54 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -357,7 +357,7 @@ class BibleMediaItem(MediaManagerItem): def onNoBookFound(self): QtGui.QMessageBox.critical(self, self.trUtf8('No Book Found'), - self.trUtf8('No matching Book could be found in this Bible.'), + self.trUtf8('No matching book could be found in this Bible.'), QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok), QtGui.QMessageBox.Ok ) diff --git a/openlp/plugins/bibles/lib/opensong.py b/openlp/plugins/bibles/lib/opensong.py index 64eeeb0f9..9e0c77b13 100644 --- a/openlp/plugins/bibles/lib/opensong.py +++ b/openlp/plugins/bibles/lib/opensong.py @@ -42,18 +42,18 @@ class OpenSongBible(BibleDB): OpenSong Bible format importer class. """ - def __init__(self, **kwargs): + 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, **kwargs) + 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) + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'openlpstopimport'), self.stop_import) def stop_import(self): """ @@ -69,27 +69,20 @@ class OpenSongBible(BibleDB): 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...') - detect_file = None - try: - detect_file = open(self.filename, u'r') - details = chardet.detect(detect_file.read()) - except: - log.exception(u'Failed to detect OpenSong file encoding') - return False - finally: - if detect_file: - detect_file.close() file = None success = True try: - file = codecs.open(self.filename, u'r', details['encoding']) + # 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 self.stop_import: break - db_book = self.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 self.stop_import: break @@ -100,12 +93,12 @@ class OpenSongBible(BibleDB): db_book.id, int(chapter.attrib[u'n']), int(verse.attrib[u'n']), - verse.text + unicode(verse.text) ) Receiver.send_message(u'process_events') self.wizard.incrementProgressBar( - QtCore.QString('Importing %s %s' % \ - (db_book.name, chapter.attrib[u'n']))) + 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') diff --git a/openlp/plugins/bibles/lib/osis.py b/openlp/plugins/bibles/lib/osis.py index a7e4ba374..b68bd5ff5 100644 --- a/openlp/plugins/bibles/lib/osis.py +++ b/openlp/plugins/bibles/lib/osis.py @@ -43,13 +43,13 @@ class OSISBible(BibleDB): log = logging.getLogger(u'BibleOSISImpl') log.info(u'BibleOSISImpl loaded') - def __init__(self, **kwargs): + 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, **kwargs) + 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'] diff --git a/openlp/plugins/custom/forms/editcustomform.py b/openlp/plugins/custom/forms/editcustomform.py index 98eb5598a..e701c0938 100644 --- a/openlp/plugins/custom/forms/editcustomform.py +++ b/openlp/plugins/custom/forms/editcustomform.py @@ -153,10 +153,10 @@ class EditCustomForm(QtGui.QDialog, Ui_customEditDialog): sxml.add_verse_to_lyrics(u'custom', unicode(count), unicode(self.VerseListView.item(i).text())) count += 1 - self.customSlide.title = unicode(self.TitleEdit.displayText()) - self.customSlide.text = unicode(sxml.extract_xml()) - self.customSlide.credits = unicode(self.CreditEdit.displayText()) - self.customSlide.theme_name = unicode(self.ThemeComboBox.currentText()) + self.customSlide.title = unicode(self.TitleEdit.displayText(), u'utf-8') + self.customSlide.text = unicode(sxml.extract_xml(), u'utf-8') + self.customSlide.credits = unicode(self.CreditEdit.displayText(), u'utf-8') + self.customSlide.theme_name = unicode(self.ThemeComboBox.currentText(), u'utf-8') self.custommanager.save_slide(self.customSlide) return True @@ -257,4 +257,4 @@ class EditCustomForm(QtGui.QDialog, Ui_customEditDialog): if len(self.VerseTextEdit.toPlainText()) > 0: self.VerseTextEdit.setFocus() return False, self.trUtf8('You have unsaved data') - return True, u'' \ No newline at end of file + return True, u'' diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index 9aef321e5..f5fe0686b 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -185,8 +185,13 @@ class SongMediaItem(MediaManagerItem): if author_list != u'': author_list = author_list + u', ' author_list = author_list + author.display_name - song_detail = unicode(self.trUtf8('%s (%s)' % \ - (unicode(song.title), unicode(author_list)))) + if not isinstance(author_list, unicode): + author_list = unicode(author_list, u'utf8') + if isinstance(song.title, unicode): + song_title = song.title + else: + song_title = unicode(song.title, u'utf8') + song_detail = u'%s (%s)' % (song_title, author_list) song_name = QtGui.QListWidgetItem(song_detail) song_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(song.id)) self.ListView.addItem(song_name) @@ -339,4 +344,4 @@ class SongMediaItem(MediaManagerItem): service_item.audit = [ song.title, author_audit, song.copyright, song.ccli_number ] - return True \ No newline at end of file + return True From db534dc2e84a61234a5f51b30c2a8e3d91bd74ef Mon Sep 17 00:00:00 2001 From: Raoul Snyman <raoul.snyman@saturnlaboratories.co.za> Date: Sun, 31 Jan 2010 21:51:23 +0200 Subject: [PATCH 22/33] Removed signals while they're still not working. --- openlp/plugins/bibles/lib/csvbible.py | 4 ++-- openlp/plugins/bibles/lib/opensong.py | 4 ++-- openlp/plugins/bibles/lib/osis.py | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/openlp/plugins/bibles/lib/csvbible.py b/openlp/plugins/bibles/lib/csvbible.py index d0db5159d..94ebf3ce7 100644 --- a/openlp/plugins/bibles/lib/csvbible.py +++ b/openlp/plugins/bibles/lib/csvbible.py @@ -51,8 +51,8 @@ class CSVBible(BibleDB): 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) + #QtCore.QObject.connect(Receiver.get_receiver(), + # QtCore.SIGNAL(u'openlpstopimport'), self.stop_import) def stop_import(self): """ diff --git a/openlp/plugins/bibles/lib/opensong.py b/openlp/plugins/bibles/lib/opensong.py index 9e0c77b13..f9f445973 100644 --- a/openlp/plugins/bibles/lib/opensong.py +++ b/openlp/plugins/bibles/lib/opensong.py @@ -52,8 +52,8 @@ class OpenSongBible(BibleDB): 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) + #QtCore.QObject.connect(Receiver.get_receiver(), + # QtCore.SIGNAL(u'openlpstopimport'), self.stop_import) def stop_import(self): """ diff --git a/openlp/plugins/bibles/lib/osis.py b/openlp/plugins/bibles/lib/osis.py index b68bd5ff5..dbcb1d57f 100644 --- a/openlp/plugins/bibles/lib/osis.py +++ b/openlp/plugins/bibles/lib/osis.py @@ -81,8 +81,8 @@ class OSISBible(BibleDB): 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): """ From 01ec0f407fc6bffd4c836e7183e5a0fed00cbe49 Mon Sep 17 00:00:00 2001 From: Raoul Snyman <raoul.snyman@saturnlaboratories.co.za> Date: Sun, 31 Jan 2010 22:36:54 +0200 Subject: [PATCH 23/33] Fixed up some of the Bible loading --- .../plugins/bibles/forms/importwizardform.py | 22 +++++++++---------- openlp/plugins/bibles/lib/db.py | 16 +++++++------- openlp/plugins/bibles/lib/http.py | 8 +++---- openlp/plugins/bibles/lib/manager.py | 3 +-- 4 files changed, 24 insertions(+), 25 deletions(-) diff --git a/openlp/plugins/bibles/forms/importwizardform.py b/openlp/plugins/bibles/forms/importwizardform.py index 8be453db0..c490e960e 100644 --- a/openlp/plugins/bibles/forms/importwizardform.py +++ b/openlp/plugins/bibles/forms/importwizardform.py @@ -97,9 +97,9 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): QtCore.SIGNAL(u'currentIdChanged(int)'), self.onCurrentIdChanged) - def show(self): + def exec_(self): self.setDefaults() - return QtGui.QWizard.show() + return QtGui.QWizard.exec_(self) def validateCurrentPage(self): if self.currentId() == 0: @@ -238,22 +238,22 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): def setDefaults(self): self.setField(u'source_format', 0) - 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): """ diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py index 5c7229f4a..bd29001e2 100644 --- a/openlp/plugins/bibles/lib/db.py +++ b/openlp/plugins/bibles/lib/db.py @@ -109,7 +109,7 @@ class BibleDB(QtCore.QObject): self.create_testament(u'Apocrypha') def create_testament(self, testament): - log.debug(u'%s: %s', __name__, testament) + log.debug(u'BibleDB.create_testament("%s")', testament) self.session.add(Testament.populate(name=testament)) self.commit() @@ -153,11 +153,11 @@ class BibleDB(QtCore.QObject): self.commit() def get_books(self): - log.debug(__name__) + log.debug(u'BibleDB.get_books()') return self.session.query(Book).order_by(Book.id).all() def get_book(self, book): - log.debug(u'%s: %s', __name__, book) + log.debug(u'BibleDb.get_book("%s")', __name__, book) db_book = self.session.query(Book)\ .filter(Book.name.like(book + u'%'))\ .first() @@ -168,7 +168,7 @@ class BibleDB(QtCore.QObject): return db_book def get_chapter(self, id, chapter): - log.debug(u'%s: %s, %s', __name__, 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)\ @@ -192,7 +192,7 @@ class BibleDB(QtCore.QObject): [(u'Genesis', 1, 1, 1), (u'Genesis', 2, 2, 3)] """ - log.debug(u'%s: %s', __name__, reference_list) + 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) @@ -221,7 +221,7 @@ class BibleDB(QtCore.QObject): contains spaces, it will split apart and AND'd on the list of values. """ - log.debug(u'%s: %s', __name__, text) + log.debug(u'BibleDB.verse_search("%s")', text) verses = self.session.query(Verse) if text.find(u',') > -1: or_clause = [] @@ -237,7 +237,7 @@ class BibleDB(QtCore.QObject): return verses def get_chapter_count(self, book): - log.debug(u'%s: %s', __name__, book) + log.debug(u'BibleDB.get_chapter_count("%s")', book) count = self.session.query(Verse.chapter).join(Book)\ .filter(Book.name==book)\ .distinct().count() @@ -249,7 +249,7 @@ class BibleDB(QtCore.QObject): return count def get_verse_count(self, book, chapter): - log.debug(u'%s: %s, %s', __name__, 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)\ diff --git a/openlp/plugins/bibles/lib/http.py b/openlp/plugins/bibles/lib/http.py index 4472000d5..607c94f0d 100644 --- a/openlp/plugins/bibles/lib/http.py +++ b/openlp/plugins/bibles/lib/http.py @@ -42,7 +42,7 @@ class BGExtract(BibleCommon): log.debug(u'init %s', proxyurl) self.proxyurl = proxyurl - def get_chapter(self, version, bookname, chapter) : + def get_bible_chapter(self, version, bookname, chapter) : """ Access and decode bibles via the BibleGateway website @@ -256,10 +256,10 @@ class HTTPBible(BibleDB): return None def get_books(self): - return [Book.populate(name=self.books[book]['name']) for book in self.books] + return [Book.populate(name=book['name']) for book in self.books] def get_chapter_count(self, book): - return self.books[book][u'chap'] + return self.lookup_book(book)[u'chap'] def set_proxy_server(self, server): self.proxy_server = server @@ -268,7 +268,7 @@ class HTTPBible(BibleDB): self.books = books def lookup_book(self, name): - log.debug('Looking up "%s" in %s', (name, self.books)) + log.debug('Looking up "%s" in %s', name, self.books) for book in self.books: if book[u'name'] == name or book[u'abbr'] == name: return book diff --git a/openlp/plugins/bibles/lib/manager.py b/openlp/plugins/bibles/lib/manager.py index 3ca76bbab..4c67dc289 100644 --- a/openlp/plugins/bibles/lib/manager.py +++ b/openlp/plugins/bibles/lib/manager.py @@ -131,8 +131,7 @@ class BibleManager(object): u'name': unicode(line[0]), u'abbr': unicode(line[1]), u'test': line[2], - u'chap': line[3], - u'ordr': order + u'chap': line[3] }) except: log.exception(u'Failed to load http books.') From 17a08e384747d3355f05cc00706794947e470d3b Mon Sep 17 00:00:00 2001 From: Tim Bentley <tim.bentley@gmail.com> Date: Mon, 1 Feb 2010 19:42:52 +0000 Subject: [PATCH 24/33] latest hacking --- .../presentations/lib/impresscontroller.py | 36 ++- .../presentations/lib/messagelistener.py | 291 +++++++----------- .../lib/presentationcontroller.py | 2 +- 3 files changed, 146 insertions(+), 183 deletions(-) diff --git a/openlp/plugins/presentations/lib/impresscontroller.py b/openlp/plugins/presentations/lib/impresscontroller.py index ee15d27be..b160b3b4b 100644 --- a/openlp/plugins/presentations/lib/impresscontroller.py +++ b/openlp/plugins/presentations/lib/impresscontroller.py @@ -62,11 +62,12 @@ class ImpressController(PresentationController): """ log.debug(u'Initialising') PresentationController.__init__(self, plugin, u'Impress') - self.supports= [u'.odp', u'.ppt', u'.pps'] + self.supports= [u'.odp', u'.ppt', u'.pps', u'.pptx', u'.ppsx'] self.process = None self.document = None self.presentation = None self.controller = None + self.desktop = None def check_available(self): """ @@ -86,7 +87,7 @@ class ImpressController(PresentationController): It is not displayed to the user but is available to the UNO interface when required. """ - log.debug(u'start Openoffice') + log.debug(u'start process Openoffice') if os.name == u'nt': self.manager = self.get_com_servicemanager() self.manager._FlagAsMethod(u'Bridge_GetStruct') @@ -102,7 +103,7 @@ class ImpressController(PresentationController): """ Called at system exit to clean up any running presentations """ - log.debug(u'Kill') + log.debug(u'Kill OpenOffice') self.close_presentation() if os.name != u'nt': desktop = self.get_uno_desktop() @@ -122,8 +123,9 @@ class ImpressController(PresentationController): ``presentation`` The file name of the presentatios to the run. """ - log.debug(u'LoadPresentation') + log.debug(u'Load Presentation OpenOffice') self.store_filename(presentation) + print "s.dsk1 ", self.desktop if os.name == u'nt': desktop = self.get_com_desktop() if desktop is None: @@ -136,6 +138,7 @@ class ImpressController(PresentationController): if desktop is None: return self.desktop = desktop + print "s.dsk2 ", self.desktop properties = [] properties.append(self.create_property(u'Minimized', True)) properties = tuple(properties) @@ -154,9 +157,9 @@ class ImpressController(PresentationController): """ Create thumbnail images for presentation """ + log.debug(u'create thumbnails OpenOffice') if self.check_thumbnails(): return - if os.name == u'nt': thumbdir = u'file:///' + self.thumbnailpath.replace( u'\\', u'/').replace(u':', u'|').replace(u' ', u'%20') @@ -171,13 +174,14 @@ class ImpressController(PresentationController): page = pages.getByIndex(idx) doc.getCurrentController().setCurrentPage(page) path = u'%s/%s%s.png'% (thumbdir, self.thumbnailprefix, - unicode(idx+1)) + unicode(idx + 1)) try: doc.storeToURL(path , props) except: log.exception(u'%s\nUnable to store preview' % path) def create_property(self, name, value): + log.debug(u'create property OpenOffice') if os.name == u'nt': prop = self.manager.Bridge_GetStruct(u'com.sun.star.beans.PropertyValue') else: @@ -187,7 +191,7 @@ class ImpressController(PresentationController): return prop def get_uno_desktop(self): - log.debug(u'getUNODesktop') + log.debug(u'get UNO Desktop Openoffice') ctx = None loop = 0 context = uno.getComponentContext() @@ -197,6 +201,7 @@ class ImpressController(PresentationController): try: ctx = resolver.resolve(u'uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext') except: + log.exception(u'Unable to fine running instance ') self.start_process() loop += 1 try: @@ -209,7 +214,7 @@ class ImpressController(PresentationController): return None def get_com_desktop(self): - log.debug(u'getCOMDesktop') + log.debug(u'get COM Desktop OpenOffice') try: desktop = self.manager.createInstance(u'com.sun.star.frame.Desktop') return desktop @@ -218,7 +223,7 @@ class ImpressController(PresentationController): return None def get_com_servicemanager(self): - log.debug(u'get_com_servicemanager') + log.debug(u'get_com_servicemanager openoffice') try: return Dispatch(u'com.sun.star.ServiceManager') except: @@ -231,6 +236,7 @@ class ImpressController(PresentationController): Triggerent by new object being added to SlideController orOpenLP being shut down """ + log.debug(u'close Presentation OpenOffice') if self.document: if self.presentation: try: @@ -243,32 +249,44 @@ class ImpressController(PresentationController): self.document = None def is_loaded(self): + log.debug(u'is loaded OpenOffice') + print "is_loaded " if self.presentation is None or self.document is None: + print "no present or document" return False try: if self.document.getPresentation() is None: + print "no getPresentation" return False except: return False return True def is_active(self): + log.debug(u'is active OpenOffice') + print "is_active " if not self.is_loaded(): + print "False " return False + print "self.con ", self.controller if self.controller is None: return False return True def unblank_screen(self): + log.debug(u'unblank screen OpenOffice') return self.controller.resume() def blank_screen(self): + log.debug(u'blank screen OpenOffice') self.controller.blankScreen(0) def stop_presentation(self): + log.debug(u'stop presentation OpenOffice') self.controller.deactivate() def start_presentation(self): + log.debug(u'start presentation OpenOffice') if self.controller is None or not self.controller.isRunning(): self.presentation.start() # start() returns before the getCurrentComponent is ready. Try for 5 seconds diff --git a/openlp/plugins/presentations/lib/messagelistener.py b/openlp/plugins/presentations/lib/messagelistener.py index 0b2fd6003..fafaa2d95 100644 --- a/openlp/plugins/presentations/lib/messagelistener.py +++ b/openlp/plugins/presentations/lib/messagelistener.py @@ -4,8 +4,8 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # +# Copyright (c) 2008-2009 Raoul Snyman # +# Portions copyright (c) 2008-2009 Tim Bentley, Jonathan Corwin, Michael # # Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # # Carsten Tinggaard # # --------------------------------------------------------------------------- # @@ -30,118 +30,6 @@ from PyQt4 import QtCore from openlp.core.lib import Receiver -class Controller(object): - """ - This is the Presentation listener who acts on events from the slide - controller and passes the messages on the the correct presentation handlers - """ - global log - log = logging.getLogger(u'Controller') - log.info(u'Controller loaded') - - def __init__(self, live): - self.isLive = live - log.info(u'%s controller loaded' % live) - - def addHandler(self, controller, file): - log.debug(u'Live = %s, addHandler %s' % (self.isLive, file)) - self.controller = controller - if self.controller.is_loaded(): - self.shutdown() - self.controller.load_presentation(file) - if self.isLive: - self.controller.start_presentation() - Receiver.send_message(u'live_slide_hide') - self.controller.slidenumber = 0 - - def activate(self): - log.debug(u'Live = %s, activate' % self.isLive) - if self.controller.is_active(): - return - if not self.controller.is_loaded(): - self.controller.load_presentation(self.controller.filepath) - if self.isLive: - self.controller.start_presentation() - if self.controller.slidenumber > 1: - self.controller.goto_slide(self.controller.slidenumber) - - def slide(self, slide, live): - log.debug(u'Live = %s, slide' % live) -# if not isLive: -# return - self.activate() - self.controller.goto_slide(int(slide) + 1) - self.controller.poll_slidenumber(live) - - def first(self): - """ - Based on the handler passed at startup triggers the first slide - """ - log.debug(u'Live = %s, first' % self.isLive) - if not self.isLive: - return - self.activate() - self.controller.start_presentation() - self.controller.poll_slidenumber(self.isLive) - - def last(self): - """ - Based on the handler passed at startup triggers the first slide - """ - log.debug(u'Live = %s, last' % self.isLive) - if not self.isLive: - return - self.activate() - self.controller.goto_slide(self.controller.get_slide_count()) - self.controller.poll_slidenumber(self.isLive) - - def next(self): - """ - Based on the handler passed at startup triggers the next slide event - """ - log.debug(u'Live = %s, next' % self.isLive) - if not self.isLive: - return - self.activate() - self.controller.next_step() - self.controller.poll_slidenumber(self.isLive) - - def previous(self): - """ - Based on the handler passed at startup triggers the previous slide event - """ - log.debug(u'Live = %s, previous' % self.isLive) - if not self.isLive: - return - self.activate() - self.controller.previous_step() - self.controller.poll_slidenumber(self.isLive) - - def shutdown(self): - """ - Based on the handler passed at startup triggers slide show to shut down - """ - log.debug(u'Live = %s, shutdown' % self.isLive) - self.controller.close_presentation() - self.controller.slidenumber = 0 - #self.timer.stop() - - def blank(self): - if not self.isLive: - return - if not self.controller.is_loaded(): - return - if not self.controller.is_active(): - return - self.controller.blank_screen() - - def unblank(self): - if not self.is_live: - return - self.activate() - self.controller.unblank_screen() - - class MessageListener(object): """ This is the Presentation listener who acts on events from the slide @@ -153,8 +41,8 @@ class MessageListener(object): def __init__(self, controllers): self.controllers = controllers - self.previewHandler = Controller(False) - self.liveHandler = Controller(True) + self.handler = None + self.is_live = None # messages are sent from core.ui.slidecontroller QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'presentations_start'), self.startup) @@ -183,62 +71,133 @@ class MessageListener(object): Start of new presentation Save the handler as any new presentations start here """ - log.debug(u'Startup called with message %s' % message) - self.handler, file, isLive = self.decodeMessage(message) - if isLive: - self.liveHandler.addHandler(self.controllers[self.handler], file) - else: - self.previewHandler.addHandler(self.controllers[self.handler], file) + log.debug(u'startup %s ' % message) + self.handler, file, self.is_live = self.decodeMessage(message) + self.controller = self.controllers[self.handler] + if self.controller.is_loaded(): + self.shutdown(None) + print "aaa ", self.is_live + self.controller.load_presentation(file) + if self.is_live: + self.controller.start_presentation() + Receiver.send_message(u'live_slide_hide') + self.controller.slidenumber = 0 + self.timer.start() + + def activate(self): + log.debug(u'activate') + if self.controller.is_active(): + return + if not self.controller.is_loaded(): + self.controller.load_presentation(self.controller.filepath) + log.debug(u'activate 2') + print "activate 2" + self.controller.start_presentation() + log.debug(u'activate 3') + print "activate 3" + if self.controller.slidenumber > 1: + self.controller.goto_slide(self.controller.slidenumber) def slide(self, message): + log.debug(u'slide %s ' % message) + #Not wanted for preview frame + if not self.is_live: + return slide, live = self.splitMessage(message) - if live: - self.liveHandler.slide(slide, live) - else: - self.previewHandler.slide(slide, live) + self.activate() + print ">>> ", message + if message: + print message[0], self.is_live + self.controller.goto_slide(int(slide) + 1) + self.controller.poll_slidenumber(self.is_live) - def first(self, isLive): - if isLive: - self.liveHandler.first() - else: - self.previewHandler.first() + def first(self, message): + """ + Based on the handler passed at startup triggers the first slide + """ + log.debug(u'first %s ' % message) + #Not wanted for preview frame + if not self.is_live: + return + self.activate() + self.controller.start_presentation() + self.controller.poll_slidenumber(self.is_live) - def last(self, isLive): - if isLive: - self.liveHandler.last() - else: - self.previewHandler.last() + def last(self, message): + """ + Based on the handler passed at startup triggers the first slide + """ + log.debug(u'last %s ' % message) + #Not wanted for preview frame + if not self.is_live: + return + self.activate() + self.controller.goto_slide(self.controller.get_slide_count()) + self.controller.poll_slidenumber(self.is_live) - def next(self, isLive): - if isLive: - self.liveHandler.next() - else: - self.previewHandler.next() + def next(self, message): + """ + Based on the handler passed at startup triggers the next slide event + """ + log.debug(u'next ', message) + #Not wanted for preview frame + if not self.is_live: + return + self.activate() + self.controller.next_step() + self.controller.poll_slidenumber(self.is_live) - def previous(self, isLive): - if isLive: - self.liveHandler.previous() - else: - self.previewHandler.previous() + def previous(self, message): + """ + Based on the handler passed at startup triggers the previous slide event + """ + log.debug(u'previous %s' % message) + if not self.is_live: + return + self.activate() + self.controller.previous_step() + self.controller.poll_slidenumber(self.is_live) - def shutdown(self, isLive): - if isLive: - self.liveHandler.shutdown() + def shutdown(self, message): + """ + Based on the handler passed at startup triggers slide show to shut down + """ + log.debug(u'shutdown %s ' % message) + if self.is_live: Receiver.send_message(u'live_slide_show') - else: - self.previewHandler.shutdown() + self.controller.close_presentation() + self.controller.slidenumber = 0 + self.timer.stop() def blank(self): - if self.isLive: - self.liveHandler.blank() - else: - self.previewHandler.blank() + log.debug(u'blank') + if not self.is_live: + return + if not self.controller.is_loaded(): + return + if not self.controller.is_active(): + return + self.controller.blank_screen() def unblank(self): - if self.isLive: - self.liveHandler.unblank() - else: - self.previewHandler.unblank() + log.debug(u'unblank') + if not self.is_live: + return + self.activate() + self.controller.unblank_screen() + + def decodeMessage(self, message): + """ + Splits the message from the SlideController into it's component parts + + ``message`` + Message containing Presentaion handler name and file to be presented. + """ + file = os.path.join(message[1], message[2]) + return message[0], file, message[4] + + def timeout(self): + self.controller.poll_slidenumber(self.is_live) def splitMessage(self, message): """ @@ -250,17 +209,3 @@ class MessageListener(object): """ bits = message.split(u':') return bits[0], bits[1] - - def decodeMessage(self, message): - """ - Splits the initial message from the SlideController - into it's component parts - - ``message`` - Message containing Presentaion handler name and file to be presented. - """ - file = os.path.join(message[1], message[2]) - return message[0], file, message[4] - - def timeout(self): - self.controller.poll_slidenumber(self.is_live) diff --git a/openlp/plugins/presentations/lib/presentationcontroller.py b/openlp/plugins/presentations/lib/presentationcontroller.py index ac9581d28..db42a482d 100644 --- a/openlp/plugins/presentations/lib/presentationcontroller.py +++ b/openlp/plugins/presentations/lib/presentationcontroller.py @@ -118,7 +118,7 @@ class PresentationController(object): """ global log log = logging.getLogger(u'PresentationController') - log.info(u'loaded') + log.info(u'PresentationController loaded') def __init__(self, plugin=None, name=u'PresentationController'): """ From 377f3ad6ea96d0859fa870592a31d142ba4f51fd Mon Sep 17 00:00:00 2001 From: Tim Bentley <tim.bentley@gmail.com> Date: Mon, 1 Feb 2010 20:06:50 +0000 Subject: [PATCH 25/33] Put the messagelistener back --- .../presentations/lib/messagelistener.py | 291 +++++++++++------- 1 file changed, 173 insertions(+), 118 deletions(-) diff --git a/openlp/plugins/presentations/lib/messagelistener.py b/openlp/plugins/presentations/lib/messagelistener.py index fafaa2d95..0b2fd6003 100644 --- a/openlp/plugins/presentations/lib/messagelistener.py +++ b/openlp/plugins/presentations/lib/messagelistener.py @@ -4,8 +4,8 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2009 Raoul Snyman # -# Portions copyright (c) 2008-2009 Tim Bentley, Jonathan Corwin, Michael # +# Copyright (c) 2008-2010 Raoul Snyman # +# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # # Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # # Carsten Tinggaard # # --------------------------------------------------------------------------- # @@ -30,6 +30,118 @@ from PyQt4 import QtCore from openlp.core.lib import Receiver +class Controller(object): + """ + This is the Presentation listener who acts on events from the slide + controller and passes the messages on the the correct presentation handlers + """ + global log + log = logging.getLogger(u'Controller') + log.info(u'Controller loaded') + + def __init__(self, live): + self.isLive = live + log.info(u'%s controller loaded' % live) + + def addHandler(self, controller, file): + log.debug(u'Live = %s, addHandler %s' % (self.isLive, file)) + self.controller = controller + if self.controller.is_loaded(): + self.shutdown() + self.controller.load_presentation(file) + if self.isLive: + self.controller.start_presentation() + Receiver.send_message(u'live_slide_hide') + self.controller.slidenumber = 0 + + def activate(self): + log.debug(u'Live = %s, activate' % self.isLive) + if self.controller.is_active(): + return + if not self.controller.is_loaded(): + self.controller.load_presentation(self.controller.filepath) + if self.isLive: + self.controller.start_presentation() + if self.controller.slidenumber > 1: + self.controller.goto_slide(self.controller.slidenumber) + + def slide(self, slide, live): + log.debug(u'Live = %s, slide' % live) +# if not isLive: +# return + self.activate() + self.controller.goto_slide(int(slide) + 1) + self.controller.poll_slidenumber(live) + + def first(self): + """ + Based on the handler passed at startup triggers the first slide + """ + log.debug(u'Live = %s, first' % self.isLive) + if not self.isLive: + return + self.activate() + self.controller.start_presentation() + self.controller.poll_slidenumber(self.isLive) + + def last(self): + """ + Based on the handler passed at startup triggers the first slide + """ + log.debug(u'Live = %s, last' % self.isLive) + if not self.isLive: + return + self.activate() + self.controller.goto_slide(self.controller.get_slide_count()) + self.controller.poll_slidenumber(self.isLive) + + def next(self): + """ + Based on the handler passed at startup triggers the next slide event + """ + log.debug(u'Live = %s, next' % self.isLive) + if not self.isLive: + return + self.activate() + self.controller.next_step() + self.controller.poll_slidenumber(self.isLive) + + def previous(self): + """ + Based on the handler passed at startup triggers the previous slide event + """ + log.debug(u'Live = %s, previous' % self.isLive) + if not self.isLive: + return + self.activate() + self.controller.previous_step() + self.controller.poll_slidenumber(self.isLive) + + def shutdown(self): + """ + Based on the handler passed at startup triggers slide show to shut down + """ + log.debug(u'Live = %s, shutdown' % self.isLive) + self.controller.close_presentation() + self.controller.slidenumber = 0 + #self.timer.stop() + + def blank(self): + if not self.isLive: + return + if not self.controller.is_loaded(): + return + if not self.controller.is_active(): + return + self.controller.blank_screen() + + def unblank(self): + if not self.is_live: + return + self.activate() + self.controller.unblank_screen() + + class MessageListener(object): """ This is the Presentation listener who acts on events from the slide @@ -41,8 +153,8 @@ class MessageListener(object): def __init__(self, controllers): self.controllers = controllers - self.handler = None - self.is_live = None + self.previewHandler = Controller(False) + self.liveHandler = Controller(True) # messages are sent from core.ui.slidecontroller QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'presentations_start'), self.startup) @@ -71,133 +183,62 @@ class MessageListener(object): Start of new presentation Save the handler as any new presentations start here """ - log.debug(u'startup %s ' % message) - self.handler, file, self.is_live = self.decodeMessage(message) - self.controller = self.controllers[self.handler] - if self.controller.is_loaded(): - self.shutdown(None) - print "aaa ", self.is_live - self.controller.load_presentation(file) - if self.is_live: - self.controller.start_presentation() - Receiver.send_message(u'live_slide_hide') - self.controller.slidenumber = 0 - self.timer.start() - - def activate(self): - log.debug(u'activate') - if self.controller.is_active(): - return - if not self.controller.is_loaded(): - self.controller.load_presentation(self.controller.filepath) - log.debug(u'activate 2') - print "activate 2" - self.controller.start_presentation() - log.debug(u'activate 3') - print "activate 3" - if self.controller.slidenumber > 1: - self.controller.goto_slide(self.controller.slidenumber) + log.debug(u'Startup called with message %s' % message) + self.handler, file, isLive = self.decodeMessage(message) + if isLive: + self.liveHandler.addHandler(self.controllers[self.handler], file) + else: + self.previewHandler.addHandler(self.controllers[self.handler], file) def slide(self, message): - log.debug(u'slide %s ' % message) - #Not wanted for preview frame - if not self.is_live: - return slide, live = self.splitMessage(message) - self.activate() - print ">>> ", message - if message: - print message[0], self.is_live - self.controller.goto_slide(int(slide) + 1) - self.controller.poll_slidenumber(self.is_live) + if live: + self.liveHandler.slide(slide, live) + else: + self.previewHandler.slide(slide, live) - def first(self, message): - """ - Based on the handler passed at startup triggers the first slide - """ - log.debug(u'first %s ' % message) - #Not wanted for preview frame - if not self.is_live: - return - self.activate() - self.controller.start_presentation() - self.controller.poll_slidenumber(self.is_live) + def first(self, isLive): + if isLive: + self.liveHandler.first() + else: + self.previewHandler.first() - def last(self, message): - """ - Based on the handler passed at startup triggers the first slide - """ - log.debug(u'last %s ' % message) - #Not wanted for preview frame - if not self.is_live: - return - self.activate() - self.controller.goto_slide(self.controller.get_slide_count()) - self.controller.poll_slidenumber(self.is_live) + def last(self, isLive): + if isLive: + self.liveHandler.last() + else: + self.previewHandler.last() - def next(self, message): - """ - Based on the handler passed at startup triggers the next slide event - """ - log.debug(u'next ', message) - #Not wanted for preview frame - if not self.is_live: - return - self.activate() - self.controller.next_step() - self.controller.poll_slidenumber(self.is_live) + def next(self, isLive): + if isLive: + self.liveHandler.next() + else: + self.previewHandler.next() - def previous(self, message): - """ - Based on the handler passed at startup triggers the previous slide event - """ - log.debug(u'previous %s' % message) - if not self.is_live: - return - self.activate() - self.controller.previous_step() - self.controller.poll_slidenumber(self.is_live) + def previous(self, isLive): + if isLive: + self.liveHandler.previous() + else: + self.previewHandler.previous() - def shutdown(self, message): - """ - Based on the handler passed at startup triggers slide show to shut down - """ - log.debug(u'shutdown %s ' % message) - if self.is_live: + def shutdown(self, isLive): + if isLive: + self.liveHandler.shutdown() Receiver.send_message(u'live_slide_show') - self.controller.close_presentation() - self.controller.slidenumber = 0 - self.timer.stop() + else: + self.previewHandler.shutdown() def blank(self): - log.debug(u'blank') - if not self.is_live: - return - if not self.controller.is_loaded(): - return - if not self.controller.is_active(): - return - self.controller.blank_screen() + if self.isLive: + self.liveHandler.blank() + else: + self.previewHandler.blank() def unblank(self): - log.debug(u'unblank') - if not self.is_live: - return - self.activate() - self.controller.unblank_screen() - - def decodeMessage(self, message): - """ - Splits the message from the SlideController into it's component parts - - ``message`` - Message containing Presentaion handler name and file to be presented. - """ - file = os.path.join(message[1], message[2]) - return message[0], file, message[4] - - def timeout(self): - self.controller.poll_slidenumber(self.is_live) + if self.isLive: + self.liveHandler.unblank() + else: + self.previewHandler.unblank() def splitMessage(self, message): """ @@ -209,3 +250,17 @@ class MessageListener(object): """ bits = message.split(u':') return bits[0], bits[1] + + def decodeMessage(self, message): + """ + Splits the initial message from the SlideController + into it's component parts + + ``message`` + Message containing Presentaion handler name and file to be presented. + """ + file = os.path.join(message[1], message[2]) + return message[0], file, message[4] + + def timeout(self): + self.controller.poll_slidenumber(self.is_live) From 632fae5a7662207e7bfa16847e1eb7736a95f279 Mon Sep 17 00:00:00 2001 From: Tim Bentley <tim.bentley@gmail.com> Date: Tue, 2 Feb 2010 18:16:11 +0000 Subject: [PATCH 26/33] Remove print statements --- openlp/core/ui/servicemanager.py | 10 +++++----- .../presentations/lib/impresscontroller.py | 16 ++++++++-------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index 5f384a955..1eef9a81b 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -523,11 +523,11 @@ class ServiceManager(QtGui.QWidget): self.parent.serviceChanged(True, self.serviceName) def validateItem(self, serviceItem): - print "---" - print serviceItem.name - print serviceItem.title - print serviceItem.service_item_path - print serviceItem.service_item_type +# print "---" +# print serviceItem.name +# print serviceItem.title +# print serviceItem.service_item_path +# print serviceItem.service_item_type return True def cleanUp(self): diff --git a/openlp/plugins/presentations/lib/impresscontroller.py b/openlp/plugins/presentations/lib/impresscontroller.py index b160b3b4b..b58a9affc 100644 --- a/openlp/plugins/presentations/lib/impresscontroller.py +++ b/openlp/plugins/presentations/lib/impresscontroller.py @@ -125,7 +125,7 @@ class ImpressController(PresentationController): """ log.debug(u'Load Presentation OpenOffice') self.store_filename(presentation) - print "s.dsk1 ", self.desktop + #print "s.dsk1 ", self.desktop if os.name == u'nt': desktop = self.get_com_desktop() if desktop is None: @@ -138,7 +138,7 @@ class ImpressController(PresentationController): if desktop is None: return self.desktop = desktop - print "s.dsk2 ", self.desktop + #print "s.dsk2 ", self.desktop properties = [] properties.append(self.create_property(u'Minimized', True)) properties = tuple(properties) @@ -250,13 +250,13 @@ class ImpressController(PresentationController): def is_loaded(self): log.debug(u'is loaded OpenOffice') - print "is_loaded " + #print "is_loaded " if self.presentation is None or self.document is None: - print "no present or document" + #print "no present or document" return False try: if self.document.getPresentation() is None: - print "no getPresentation" + #print "no getPresentation" return False except: return False @@ -264,11 +264,11 @@ class ImpressController(PresentationController): def is_active(self): log.debug(u'is active OpenOffice') - print "is_active " + #print "is_active " if not self.is_loaded(): - print "False " + #print "False " return False - print "self.con ", self.controller + #print "self.con ", self.controller if self.controller is None: return False return True From e465264630ee51eb5d04ddf8e9d9d1908a71340e Mon Sep 17 00:00:00 2001 From: Raoul Snyman <raoul.snyman@saturnlaboratories.co.za> Date: Thu, 4 Feb 2010 19:38:21 +0200 Subject: [PATCH 27/33] Standardised manager name to "manager" --- openlp/plugins/bibles/bibleplugin.py | 7 ++-- .../plugins/bibles/forms/importwizardform.py | 22 +++++----- openlp/plugins/bibles/lib/manager.py | 4 +- openlp/plugins/bibles/lib/mediaitem.py | 42 +++++++++---------- 4 files changed, 38 insertions(+), 37 deletions(-) diff --git a/openlp/plugins/bibles/bibleplugin.py b/openlp/plugins/bibles/bibleplugin.py index 5fafac65b..d560b0bce 100644 --- a/openlp/plugins/bibles/bibleplugin.py +++ b/openlp/plugins/bibles/bibleplugin.py @@ -40,12 +40,12 @@ class BiblePlugin(Plugin): self.weight = -9 self.icon = build_icon(u':/media/media_bible.png') #Register the bible Manager - self.biblemanager = None + self.manager = None def initialise(self): log.info(u'bibles Initialising') - if self.biblemanager is None: - self.biblemanager = BibleManager(self, self.config) + if self.manager is None: + self.manager = BibleManager(self, self.config) Plugin.initialise(self) self.insert_toolbox_item() self.ImportBibleItem.setVisible(True) @@ -91,3 +91,4 @@ class BiblePlugin(Plugin): 'plugin allows bible verses from different sources to be ' 'displayed on the screen during the service.') return about_text + diff --git a/openlp/plugins/bibles/forms/importwizardform.py b/openlp/plugins/bibles/forms/importwizardform.py index c490e960e..a684c01a3 100644 --- a/openlp/plugins/bibles/forms/importwizardform.py +++ b/openlp/plugins/bibles/forms/importwizardform.py @@ -60,7 +60,7 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): log = logging.getLogger(u'BibleImportForm') log.info(u'BibleImportForm loaded') - def __init__(self, parent, config, biblemanager, bibleplugin): + def __init__(self, parent, config, manager, bibleplugin): ''' Constructor ''' @@ -69,10 +69,10 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): self.registerFields() self.finishButton = self.button(QtGui.QWizard.FinishButton) self.cancelButton = self.button(QtGui.QWizard.CancelButton) - self.biblemanager = biblemanager + self.manager = manager self.config = config self.bibleplugin = bibleplugin - self.biblemanager.set_process_dialog(self) + self.manager.set_process_dialog(self) self.web_bible_list = {} self.loadWebBibles() QtCore.QObject.connect(self.LocationComboBox, @@ -162,7 +162,7 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok)) self.CopyrightEdit.setFocus() return False - elif self.biblemanager.exists( + elif self.manager.exists( self.field(u'license_version').toString()): QtGui.QMessageBox.critical(self, self.trUtf8('Bible Exists'), @@ -320,20 +320,20 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): success = False if bible_type == BibleFormat.OSIS: # Import an OSIS bible - success = self.biblemanager.import_bible(BibleFormat.OSIS, + 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.import_bible(BibleFormat.CSV, + 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.import_bible(BibleFormat.OpenSong, + success = self.manager.import_bible(BibleFormat.OpenSong, name=unicode(self.field(u'license_version').toString()), filename=self.field(u'opensong_file').toString() ) @@ -347,7 +347,7 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): elif download_location == DownloadLocation.BibleGateway: bible = self.web_bible_list[DownloadLocation.BibleGateway][ unicode(self.BibleComboBox.currentText())] - success = self.biblemanager.import_bible(BibleFormat.WebDownload, + 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), @@ -356,13 +356,13 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): 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.biblemanager.reload_bibles() + self.manager.reload_bibles() self.ImportProgressLabel.setText(self.trUtf8('Finished import.')) else: self.ImportProgressLabel.setText( @@ -372,4 +372,4 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): self.ImportProgressBar.setValue(self.ImportProgressBar.maximum()) self.finishButton.setVisible(True) self.cancelButton.setVisible(False) - Receiver.send_message(u'process_events') + Receiver.send_message(u'process_events') \ No newline at end of file diff --git a/openlp/plugins/bibles/lib/manager.py b/openlp/plugins/bibles/lib/manager.py index 4c67dc289..7ac99530c 100644 --- a/openlp/plugins/bibles/lib/manager.py +++ b/openlp/plugins/bibles/lib/manager.py @@ -383,11 +383,11 @@ class BibleManager(object): Check cache to see if new bible """ if not isinstance(name, unicode): - name = unicode(name, u'utf8') + 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, u'utf8') + bible = unicode(bible) if bible == name: return True return False diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index 213c79c54..fb6b2eafa 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -303,7 +303,7 @@ class BibleMediaItem(MediaManagerItem): def initialise(self): log.debug(u'bible manager initialise') - self.parent.biblemanager.media = self + self.parent.manager.media = self self.loadBibles() self.configUpdated() log.debug(u'bible manager initialise complete') @@ -323,13 +323,13 @@ class BibleMediaItem(MediaManagerItem): self.AdvancedSecondBibleComboBox.clear() self.QuickSecondBibleComboBox.addItem(u'') self.AdvancedSecondBibleComboBox.addItem(u'') - bibles = self.parent.biblemanager.get_bibles(BibleMode.Full) + bibles = self.parent.manager.get_bibles(BibleMode.Full) # load bibles into the combo boxes for bible in bibles: self.QuickVersionComboBox.addItem(bible) self.QuickSecondBibleComboBox.addItem(bible) # Without HTTP - #bibles = self.parent.biblemanager.get_bibles(BibleMode.Partial) + #bibles = self.parent.manager.get_bibles(BibleMode.Partial) first = True # load bibles into the combo boxes for bible in bibles: @@ -375,10 +375,10 @@ class BibleMediaItem(MediaManagerItem): def onNewClick(self): #self.bibleimportform = BibleImportForm( - # self.parent.config, self.parent.biblemanager, self) + # self.parent.config, self.parent.manager, 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() @@ -393,7 +393,7 @@ class BibleMediaItem(MediaManagerItem): 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( + verses = self.parent.manager.get_book_verse_count( bible, book, int(text2)) self.adjustComboBox(1, verses, self.AdvancedToVerse) @@ -418,7 +418,7 @@ class BibleMediaItem(MediaManagerItem): cf = int(self.AdvancedFromChapter.currentText()) self.adjustComboBox(cf, self.chapters_from, self.AdvancedToChapter) # get the verse count for new chapter - vse = self.parent.biblemanager.get_book_verse_count(bible, book, cf) + vse = self.parent.manager.get_book_verse_count(bible, book, cf) self.adjustComboBox(1, vse, self.AdvancedFromVerse) self.adjustComboBox(1, vse, self.AdvancedToVerse) @@ -430,10 +430,10 @@ class BibleMediaItem(MediaManagerItem): self.ListView.clear() #if self.QuickSearchComboBox.currentIndex() == 1: # self.search_results = \ - # self.parent.biblemanager.get_verses(bible, text) + # self.parent.manager.get_verses(bible, text) #else: # self.searchByReference(bible, text) - self.search_results = self.parent.biblemanager.get_verses(bible, text) + self.search_results = self.parent.manager.get_verses(bible, text) if self.search_results: self.displayResults(bible) @@ -524,12 +524,12 @@ class BibleMediaItem(MediaManagerItem): 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(bible) + book_data = self.parent.manager.get_bible_books(bible) self.AdvancedBookComboBox.clear() first = True for book in book_data: @@ -545,7 +545,7 @@ class BibleMediaItem(MediaManagerItem): 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, + self.verses = self.parent.manager.get_book_verse_count(bible, book, 1) if self.verses == 0: self.AdvancedSearchButton.setEnabled(False) @@ -578,12 +578,12 @@ class BibleMediaItem(MediaManagerItem): def searchByReference(self, bible, search): log.debug(u'searchByReference %s, %s', bible, search) - self.search_results = self.parent.biblemanager.get_verses(bible, search) - self.copyright = unicode(self.parent.biblemanager.get_meta_data( + self.search_results = self.parent.manager.get_verses(bible, search) + self.copyright = unicode(self.parent.manager.get_meta_data( bible, u'Copyright').value) - self.permissions = unicode(self.parent.biblemanager.get_meta_data( + self.permissions = unicode(self.parent.manager.get_meta_data( bible, u'Permissions').value) - self.version = unicode(self.parent.biblemanager.get_meta_data( + self.version = unicode(self.parent.manager.get_meta_data( bible, u'Version').value) # def searchByReference(self, bible, search): @@ -658,15 +658,15 @@ class BibleMediaItem(MediaManagerItem): # unicode(start_verse), unicode(end_verse))) # if message is None: # self.search_results = None -# self.search_results = self.parent.biblemanager.get_verse_text( +# self.search_results = self.parent.manager.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( +# self.copyright = unicode(self.parent.manager.get_meta_data( # bible, u'Copyright').value) -# self.permissions = unicode(self.parent.biblemanager.get_meta_data( +# self.permissions = unicode(self.parent.manager.get_meta_data( # bible, u'Permissions').value) -# self.version = unicode(self.parent.biblemanager.get_meta_data( +# self.version = unicode(self.parent.manager.get_meta_data( # bible, u'Version').value) # else: # QtGui.QMessageBox.information( -# self, self.trUtf8('Information'), message) +# self, self.trUtf8('Information'), message) \ No newline at end of file From ce6738a976e7e36f72b0eeabd7b5f423f93a1a4f Mon Sep 17 00:00:00 2001 From: Raoul Snyman <raoul.snyman@saturnlaboratories.co.za> Date: Thu, 4 Feb 2010 21:34:12 +0200 Subject: [PATCH 28/33] Fixed up searching for non-latin characters in Bible book names. Removed an annoying exception to do with debug logging. --- openlp/plugins/bibles/lib/common.py | 13 ++++++++++--- openlp/plugins/bibles/lib/db.py | 10 +++++----- openlp/plugins/bibles/lib/manager.py | 10 +++++----- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/openlp/plugins/bibles/lib/common.py b/openlp/plugins/bibles/lib/common.py index 3190b5d8d..962a1271f 100644 --- a/openlp/plugins/bibles/lib/common.py +++ b/openlp/plugins/bibles/lib/common.py @@ -28,13 +28,15 @@ import chardet import logging import re -only_verses = re.compile(r'([a-zA-Z0-9 ]+)[ ]+([0-9]+)[ ]*[:|v|V][ ]*([0-9]+)' +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'([a-zA-Z0-9 ]+)[ ]+([0-9]+)[ ]*[:|v|V][ ]*' +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 @@ -47,11 +49,13 @@ def parse_reference(reference): (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.') reference_list.extend([ (match.group(1), match.group(2), match.group(3), -1), (match.group(1), match.group(4), 1, match.group(5)) @@ -59,6 +63,7 @@ def parse_reference(reference): 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) @@ -82,6 +87,8 @@ def parse_reference(reference): (book, chapter, verse, match.group(4)), (book, chapter, match.group(5), end_verse) ]) + else: + log.debug('Didn\'t find anything.') return reference_list class SearchResults: @@ -216,4 +223,4 @@ class BibleCommon(object): text = text[:start_tag] + text[end_tag + 1:] start_tag = text.find(u'<') text = text.replace(u'>', u'') - return text.rstrip().lstrip() \ No newline at end of file + return text.rstrip().lstrip() diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py index bd29001e2..413f2ca1f 100644 --- a/openlp/plugins/bibles/lib/db.py +++ b/openlp/plugins/bibles/lib/db.py @@ -157,7 +157,7 @@ class BibleDB(QtCore.QObject): return self.session.query(Book).order_by(Book.id).all() def get_book(self, book): - log.debug(u'BibleDb.get_book("%s")', __name__, book) + log.debug(u'BibleDb.get_book("%s")', book) db_book = self.session.query(Book)\ .filter(Book.name.like(book + u'%'))\ .first() @@ -200,7 +200,7 @@ class BibleDB(QtCore.QObject): end_verse = self.get_chapter_count(book) if db_book: book = db_book.name - log.debug(u'Book name corrected to "%s"' % book) + 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)\ @@ -276,11 +276,11 @@ class BibleDB(QtCore.QObject): return False 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) diff --git a/openlp/plugins/bibles/lib/manager.py b/openlp/plugins/bibles/lib/manager.py index 7ac99530c..92e6cda9a 100644 --- a/openlp/plugins/bibles/lib/manager.py +++ b/openlp/plugins/bibles/lib/manager.py @@ -250,12 +250,12 @@ class BibleManager(object): Returns all the number of verses for a given book and chapterMaxBibleBookVerses """ - log.debug(u'get_verses_from_text %s,%s', bible, versetext) + log.debug(u'get_verses_from_text %s, %s', bible, versetext) reflist = parse_reference(versetext) - web_index = bible.find('(%s)' % self.web) - if web_index >= 0: - bible = bible[:web_index - 1] - log.debug('Updated bible name: %s', bible) + #web_index = bible.find('(%s)' % self.web) + #if web_index >= 0: + # bible = bible[:web_index - 1] + # log.debug('Updated bible name: %s', bible) #web, bible = self.is_bible_web(bible) #if web: # return self.http_cache[bible].get_verses(reflist) From 78c525ab760dfe35755962ae7b68090c45be11b5 Mon Sep 17 00:00:00 2001 From: Raoul Snyman <raoul.snyman@saturnlaboratories.co.za> Date: Sat, 6 Feb 2010 12:22:20 +0200 Subject: [PATCH 29/33] Moved data for web bibles to am SQLite database. --- openlp.pyw | 2 +- openlp/plugins/bibles/lib/common.py | 36 +++- openlp/plugins/bibles/lib/db.py | 2 +- openlp/plugins/bibles/lib/http.py | 107 +++++++++-- openlp/plugins/bibles/lib/manager.py | 225 +++++------------------ openlp/plugins/bibles/lib/mediaitem.py | 237 ++++++++----------------- openlp/plugins/bibles/lib/models.py | 2 +- 7 files changed, 249 insertions(+), 362 deletions(-) diff --git a/openlp.pyw b/openlp.pyw index 58925fdb9..914dbce50 100755 --- a/openlp.pyw +++ b/openlp.pyw @@ -148,7 +148,7 @@ def main(): usage = u'Usage: %prog [options] [qt-options]' parser = OptionParser(usage=usage) parser.add_option("-l", "--log-level", dest="loglevel", - default="info", metavar="LEVEL", + default="warning", metavar="LEVEL", help="Set logging to LEVEL level. Valid values are " "\"debug\", \"info\", \"warning\".") parser.add_option("-p", "--portable", dest="portable", diff --git a/openlp/plugins/bibles/lib/common.py b/openlp/plugins/bibles/lib/common.py index 962a1271f..5152ca496 100644 --- a/openlp/plugins/bibles/lib/common.py +++ b/openlp/plugins/bibles/lib/common.py @@ -27,6 +27,7 @@ import urllib2 import chardet import logging 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))?)?', @@ -56,10 +57,33 @@ def parse_reference(reference): match = chapter_range.match(reference) if match: log.debug('Found a chapter range.') - reference_list.extend([ - (match.group(1), match.group(2), match.group(3), -1), - (match.group(1), match.group(4), 1, match.group(5)) - ]) + 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: @@ -89,9 +113,11 @@ def parse_reference(reference): ]) else: log.debug('Didn\'t find anything.') + log.debug(reference_list) return reference_list -class SearchResults: + +class SearchResults(object): """ Encapsulate a set of search results. This is Bible-type independant. """ diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py index 413f2ca1f..deedf9d21 100644 --- a/openlp/plugins/bibles/lib/db.py +++ b/openlp/plugins/bibles/lib/db.py @@ -197,7 +197,7 @@ class BibleDB(QtCore.QObject): for book, chapter, start_verse, end_verse in reference_list: db_book = self.get_book(book) if end_verse == -1: - end_verse = self.get_chapter_count(book) + end_verse = self.get_verse_count(book, chapter) if db_book: book = db_book.name log.debug(u'Book name corrected to "%s"', book) diff --git a/openlp/plugins/bibles/lib/http.py b/openlp/plugins/bibles/lib/http.py index 607c94f0d..eb140b710 100644 --- a/openlp/plugins/bibles/lib/http.py +++ b/openlp/plugins/bibles/lib/http.py @@ -25,6 +25,8 @@ import logging import urllib2 +import os +import sqlite3 from BeautifulSoup import BeautifulSoup @@ -33,6 +35,89 @@ 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)') @@ -219,7 +304,7 @@ class HTTPBible(BibleDB): Receiver.send_message(u'bible_nobook') return [] db_book = self.create_book(book_details[u'name'], - book_details[u'abbr'], book_details[u'test']) + book_details[u'abbreviation'], book_details[u'testament_id']) book = db_book.name if self.get_verse_count(book, reference[1]) == 0: Receiver.send_message(u'bible_showprogress') @@ -256,21 +341,17 @@ class HTTPBible(BibleDB): return None def get_books(self): - return [Book.populate(name=book['name']) for book in self.books] + 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 self.lookup_book(book)[u'chap'] + 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 - def set_books(self, books): - self.books = books - - def lookup_book(self, name): - log.debug('Looking up "%s" in %s', name, self.books) - for book in self.books: - if book[u'name'] == name or book[u'abbr'] == name: - return book - return None - diff --git a/openlp/plugins/bibles/lib/manager.py b/openlp/plugins/bibles/lib/manager.py index 92e6cda9a..db70ac6db 100644 --- a/openlp/plugins/bibles/lib/manager.py +++ b/openlp/plugins/bibles/lib/manager.py @@ -106,8 +106,6 @@ class BibleManager(object): self.parent = parent self.web = u'Web' self.db_cache = None - self.http_cache = None - self.http_books = {} self.path = self.config.get_data_path() self.proxy_name = self.config.get_config(u'proxy name') self.suffix = u'sqlite' @@ -115,54 +113,30 @@ class BibleManager(object): self.reload_bibles() self.media = None - def load_http_books(self): - filepath = os.path.split(os.path.abspath(__file__))[0] - filepath = os.path.abspath(os.path.join( - filepath, u'..', u'resources', u'httpbooks.csv')) - books_file = None - try: - self.http_books = [] - books_file = open(filepath, u'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.http_books.append({ - u'name': unicode(line[0]), - u'abbr': unicode(line[1]), - u'test': line[2], - u'chap': line[3] - }) - except: - log.exception(u'Failed to load http books.') - finally: - if books_file: - books_file.close() - 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.suffix) log.debug(u'Bible Files %s', files) self.db_cache = {} - self.http_cache = {} - self.load_http_books() - self.web_bibles_present = False 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. source = self.db_cache[name].get_meta(u'download source') if source: - self.web_bibles_present = True 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) - meta_proxy = self.db_cache[name].get_meta(u'proxy url') if meta_proxy: web_bible.set_proxy_server(meta_proxy.value) - web_bible.set_books(self.http_books) - del self.db_cache[name] + #del self.db_cache[name] self.db_cache[name] = web_bible log.debug(u'Bibles reloaded') @@ -180,10 +154,10 @@ class BibleManager(object): Register a bible in the bible cache, and then import the verses. ``type`` - What type of Bible, one of the BibleFormat values. + What type of Bible, one of the ``BibleFormat`` values. ``**kwargs`` - Keyword arguments to send to the actualy importer class. + Keyword arguments to send to the actual importer class. """ class_ = BibleFormat.get_class(type) kwargs['path'] = self.path @@ -193,73 +167,61 @@ class BibleManager(object): self.db_cache[name] = importer return importer.do_import() - def get_bibles(self, mode=BibleMode.Full): + def get_bibles(self): """ - Returns a list of Books of the bible. When ``mode`` is set to - ``BibleMode.Full`` this method returns all the Bibles for the Advanced - Search, and when the mode is ``BibleMode.Partial`` this method returns - all the bibles for the Quick Search. + Returns a list of the names of available Bibles. """ log.debug(u'get_bibles') - bible_list = [] - for bible_name, bible_object in self.db_cache.iteritems(): - #if getattr(bible_object, 'download_source', None): - # bible_name = u'%s (%s)' % (bible_name, self.web) - bible_list.append(bible_name) - return bible_list + return [name for name, bible in self.db_cache.iteritems()] - def is_bible_web(self, bible): - pos_end = bible.find(u' (%s)' % self.web) - if pos_end != -1: - return True, bible[:pos_end] - return False, bible - - def get_bible_books(self, bible): + def get_books(self, bible): """ - Returns a list of the books of the bible - """ - log.debug(u'get_bible_books') - return [{'name': book.name, 'total': self.db_cache[bible].get_chapter_count(book.name)} for book in self.db_cache[bible].get_books()] + Returns a list of Bible books, and the number of chapters in that book. - def get_book_chapter_count(self, book): + ``bible`` + Unicode. The Bible to get the list of books from. + """ + log.debug(u'BibleManager.get_books("%s")', bible) + return [ + { + u'name': book.name, + u'chapters': self.db_cache[bible].get_chapter_count(book.name) + } + for book in self.db_cache[bible].get_books() + ] + + def get_chapter_count(self, bible, book): """ Returns the number of Chapters for a given book """ log.debug(u'get_book_chapter_count %s', book) - return self.book_chapters[book] + return self.db_cache[bible].get_chapter_count(book) - def get_book_verse_count(self, bible, book, chapter): + def get_verse_count(self, bible, book, chapter): """ Returns all the number of verses for a given book and chapterMaxBibleBookVerses """ - log.debug(u'get_book_verse_count %s,%s,%s', bible, book, chapter) - web, bible = self.is_bible_web(bible) - if web: - count = self.db_cache[bible].get_verse_count(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.db_cache[bible].get_verse_count(book, chapter) - return count - else: - return self.db_cache[bible].get_verse_count(book, chapter) + log.debug(u'BibleManager.get_verse_count("%s", "%s", %s)', bible, book, chapter) + return self.db_cache[bible].get_verse_count(book, chapter) def get_verses(self, bible, versetext): """ - Returns all the number of verses for a given - book and chapterMaxBibleBookVerses + Parses a scripture reference, fetches the verses from the Bible + specified, and returns a list of ``Verse`` objects. + + ``bible`` + Unicode. The Bible to use. + + ``versetext`` + Unicode. The scripture reference. Valid scripture references are: + + - Genesis 1:1 + - Genesis 1:1-10 + - Genesis 1:1-2:10 """ - log.debug(u'get_verses_from_text %s, %s', bible, versetext) + log.debug(u'BibleManager.get_verses("%s", "%s")', bible, versetext) reflist = parse_reference(versetext) - #web_index = bible.find('(%s)' % self.web) - #if web_index >= 0: - # bible = bible[:web_index - 1] - # log.debug('Updated bible name: %s', bible) - #web, bible = self.is_bible_web(bible) - #if web: - # return self.http_cache[bible].get_verses(reflist) - #else: return self.db_cache[bible].get_verses(reflist) def save_meta_data(self, bible, version, copyright, permissions): @@ -277,107 +239,8 @@ class BibleManager(object): 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.db_cache[bible].get_meta(key) - def get_verse_text(self, bible, book, 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, book, 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) - web_bible = False - log.debug('Web Bibles: %s', self.http_cache) - if self.http_cache[bible]: - web_bible = True - db_book = self.db_cache[bible].get_book(book) - if db_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')) % - (book, chapter)) - search_results = \ - self.http_cache[bible].get_chapter(bible, book, chapter) - 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.db_cache[bible].get_book(bookname) - if db_book is None: - ## Then create book, chapter and text - db_book = self.db_cache[bible].create_book( - bookname, self.book_abbreviations[bookname], - self.book_testaments[bookname]) - log.debug(u'New http book %s, %s, %s', - db_book, db_book.id, db_book.name) - self.db_cache[bible].create_chapter( - db_book.id, search_results.get_chapter(), - search_results.get_verselist()) - else: - ## Book exists check chapter and texts only. - v = self.db_cache[bible].get_chapter( - db_book.id, chapter) - if v is None: - self.media.setQuickMessage( - unicode(self.media.trUtf8('%Downloading %s: %s'))\ - % (book, chapter)) - self.db_cache[bible].create_chapter( - db_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.db_cache[bible].get_chapter(db_book.id, chapter) - if v is None: - try: - self.media.setQuickMessage(\ - unicode(self.media.trUtf8('Downloading %s: %s')) - % (book, chapter)) - search_results = \ - self.http_cache[bible].get_chapter( - bible, bookn, chapter) - if search_results.has_verselist(): - self.db_cache[bible].create_chapter( - db_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.db_cache[bible].get_verses( - [(book, schapter, sverse, everse)]) - else: - verse_list = [] - for chapter in range(schapter, echapter + 1): - if chapter == schapter: - start = sverse - end = self.get_verse_count(bible, book, chapter) - elif chapter == echapter: - start = 1 - end = everse - else: - start = 1 - end = self.get_verse_count(bible, book, chapter) - verse_list.append((bible, chapter, start, end)) - text = self.db_cache[bible].get_verses(verse_list) - return text - def exists(self, name): """ Check cache to see if new bible diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index fb6b2eafa..45c417130 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -60,6 +60,7 @@ class BibleMediaItem(MediaManagerItem): self.IconPath = u'songs/song' self.ListViewWithDnD_class = BibleListView self.servicePath = None + self.lastReference = u'' MediaManagerItem.__init__(self, parent, icon, title) # place to store the search results self.search_results = {} @@ -323,21 +324,16 @@ class BibleMediaItem(MediaManagerItem): self.AdvancedSecondBibleComboBox.clear() self.QuickSecondBibleComboBox.addItem(u'') self.AdvancedSecondBibleComboBox.addItem(u'') - bibles = self.parent.manager.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.manager.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): @@ -374,9 +370,6 @@ class BibleMediaItem(MediaManagerItem): self.AdvancedBookComboBox.itemData(item).toInt()[0]) def onNewClick(self): - #self.bibleimportform = BibleImportForm( - # self.parent.config, self.parent.manager, self) - #self.bibleimportform.exec_() self.bibleimportform = ImportWizardForm(self, self.parent.config, self.parent.manager, self.parent) self.bibleimportform.exec_() @@ -387,14 +380,13 @@ class BibleMediaItem(MediaManagerItem): self.adjustComboBox(frm, self.verses, self.AdvancedToVerse) def onAdvancedToChapter(self): - text1 = unicode(self.AdvancedFromChapter.currentText()) - text2 = unicode(self.AdvancedToChapter.currentText()) - if text1 != text2: + frm = unicode(self.AdvancedFromChapter.currentText()) + to = unicode(self.AdvancedToChapter.currentText()) + if frm != to: bible = unicode(self.AdvancedVersionComboBox.currentText()) book = unicode(self.AdvancedBookComboBox.currentText()) # get the verse count for new chapter - verses = self.parent.manager.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): @@ -408,6 +400,7 @@ class BibleMediaItem(MediaManagerItem): 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) + self.lastReference = versetext if self.ClearAdvancedSearchComboBox.currentIndex() == 0: self.ListView.clear() self.displayResults(bible) @@ -418,7 +411,7 @@ class BibleMediaItem(MediaManagerItem): cf = int(self.AdvancedFromChapter.currentText()) self.adjustComboBox(cf, self.chapters_from, self.AdvancedToChapter) # get the verse count for new chapter - vse = self.parent.manager.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) @@ -428,12 +421,8 @@ class BibleMediaItem(MediaManagerItem): text = unicode(self.QuickSearchEdit.displayText()) if self.ClearQuickSearchComboBox.currentIndex() == 0: self.ListView.clear() - #if self.QuickSearchComboBox.currentIndex() == 1: - # self.search_results = \ - # self.parent.manager.get_verses(bible, text) - #else: - # self.searchByReference(bible, text) self.search_results = self.parent.manager.get_verses(bible, text) + self.lastReference = text if self.search_results: self.displayResults(bible) @@ -446,60 +435,62 @@ class BibleMediaItem(MediaManagerItem): raw_slides = [] raw_footer = [] bible_text = u'' + #If we want to use a 2nd translation / version + bible2 = u'' + if self.SearchTabWidget.currentIndex() == 0: + bible2 = unicode(self.QuickSecondBibleComboBox.currentText()) + else: + bible2 = unicode(self.AdvancedSecondBibleComboBox.currentText()) + if bible2: + self.searchByReference(bible2, self.lastReference) + bible2_verses = self.search_results + 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: @@ -513,14 +504,14 @@ class BibleMediaItem(MediaManagerItem): return True def formatVerse(self, old_chapter, chapter, verse, opening, closing): - loc = opening + verse_text = opening if old_chapter != chapter: - loc += chapter + u':' + verse_text += chapter + u':' elif not self.parent.settings_tab.show_new_chapters: - loc += chapter + u':' - loc += verse - loc += closing - return loc + verse_text += chapter + u':' + verse_text += verse + verse_text += closing + return verse_text def reloadBibles(self): log.debug(u'Reloading Bibles') @@ -529,24 +520,23 @@ class BibleMediaItem(MediaManagerItem): def initialiseBible(self, bible): log.debug(u'initialiseBible %s', bible) - book_data = self.parent.manager.get_bible_books(bible) + 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'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'name'], 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.manager.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')) @@ -565,12 +555,30 @@ class BibleMediaItem(MediaManagerItem): combo.addItem(unicode(i)) def displayResults(self, bible): + version = self.parent.manager.get_meta_data(bible, u'Version') + copyright = self.parent.manager.get_meta_data(bible, u'Copyright') + permission = self.parent.manager.get_meta_data(bible, u'Permission') + if not permission: + permission = u'' + else: + permission = permission.value for count, verse in enumerate(self.search_results): - bible_text = u' %s %d:%d (%s)' % (verse.book.name, - verse.chapter, verse.verse, bible) + bible_text = u' %s %d:%d (%s)' % \ + (verse.book.name, verse.chapter, verse.verse, bible) bible_verse = QtGui.QListWidgetItem(bible_text) - bible_verse.setData(QtCore.Qt.UserRole, - QtCore.QVariant(bible_text)) + #bible_verse.setData(QtCore.Qt.UserRole, + # QtCore.QVariant(bible_text)) + vdict = { + 'bible': QtCore.QVariant(bible), + 'version': QtCore.QVariant(version.value), + 'copyright': QtCore.QVariant(copyright.value), + 'permission': QtCore.QVariant(permission), + 'book': QtCore.QVariant(verse.book.name), + 'chapter': QtCore.QVariant(verse.chapter), + 'verse': QtCore.QVariant(verse.verse), + 'text': QtCore.QVariant(verse.text) + } + bible_verse.setData(QtCore.Qt.UserRole, QtCore.QVariant(vdict)) self.ListView.addItem(bible_verse) row = self.ListView.setCurrentRow(count) if row: @@ -579,94 +587,3 @@ class BibleMediaItem(MediaManagerItem): def searchByReference(self, bible, search): log.debug(u'searchByReference %s, %s', bible, search) self.search_results = self.parent.manager.get_verses(bible, search) - self.copyright = unicode(self.parent.manager.get_meta_data( - bible, u'Copyright').value) - self.permissions = unicode(self.parent.manager.get_meta_data( - bible, u'Permissions').value) - self.version = unicode(self.parent.manager.get_meta_data( - bible, u'Version').value) - -# 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.manager.get_verse_text( -# bible, book, int(start_chapter), int(end_chapter), -# int(start_verse), int(end_verse)) -# self.copyright = unicode(self.parent.manager.get_meta_data( -# bible, u'Copyright').value) -# self.permissions = unicode(self.parent.manager.get_meta_data( -# bible, u'Permissions').value) -# self.version = unicode(self.parent.manager.get_meta_data( -# bible, u'Version').value) -# else: -# QtGui.QMessageBox.information( -# self, self.trUtf8('Information'), message) \ No newline at end of file diff --git a/openlp/plugins/bibles/lib/models.py b/openlp/plugins/bibles/lib/models.py index d9c43d1df..2802cb27f 100644 --- a/openlp/plugins/bibles/lib/models.py +++ b/openlp/plugins/bibles/lib/models.py @@ -105,4 +105,4 @@ 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) From cf95b81a497f10e5f56f76ce911c8457a94a2c41 Mon Sep 17 00:00:00 2001 From: Raoul Snyman <raoul.snyman@saturnlaboratories.co.za> Date: Sat, 6 Feb 2010 12:42:47 +0200 Subject: [PATCH 30/33] Last few fixes --- openlp/plugins/bibles/lib/http.py | 10 +++++++--- .../plugins/bibles/resources/httpbooks.sqlite | Bin 0 -> 45056 bytes 2 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 openlp/plugins/bibles/resources/httpbooks.sqlite diff --git a/openlp/plugins/bibles/lib/http.py b/openlp/plugins/bibles/lib/http.py index eb140b710..1cf92e4d2 100644 --- a/openlp/plugins/bibles/lib/http.py +++ b/openlp/plugins/bibles/lib/http.py @@ -207,8 +207,12 @@ class CWExtract(BibleCommon): log.debug(u'get_bible_chapter %s,%s,%s', version, bookname, chapter) bookname = bookname.replace(u' ', u'') - page = urllib2.urlopen(u'http://www.biblestudytools.com/%s/%s/%s.html' % \ - (version, bookname.lower(), chapter)) + 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 = {} @@ -306,7 +310,7 @@ class HTTPBible(BibleDB): db_book = self.create_book(book_details[u'name'], book_details[u'abbreviation'], book_details[u'testament_id']) book = db_book.name - if self.get_verse_count(book, reference[1]) == 0: + 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]) diff --git a/openlp/plugins/bibles/resources/httpbooks.sqlite b/openlp/plugins/bibles/resources/httpbooks.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..ea0c405309e361c3366188aec8604b97db846861 GIT binary patch literal 45056 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 literal 0 HcmV?d00001 From 92ef1f0d57f87238d738401051403bbf82a7008b Mon Sep 17 00:00:00 2001 From: Raoul Snyman <raoul.snyman@saturnlaboratories.co.za> Date: Sat, 6 Feb 2010 15:05:45 +0200 Subject: [PATCH 31/33] Fixed multi-verse dual bible. --- openlp/plugins/bibles/lib/mediaitem.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index 45c417130..bcd9adbb3 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -60,7 +60,7 @@ class BibleMediaItem(MediaManagerItem): self.IconPath = u'songs/song' self.ListViewWithDnD_class = BibleListView self.servicePath = None - self.lastReference = u'' + self.lastReference = [] MediaManagerItem.__init__(self, parent, icon, title) # place to store the search results self.search_results = {} @@ -400,9 +400,10 @@ class BibleMediaItem(MediaManagerItem): 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) - self.lastReference = versetext if self.ClearAdvancedSearchComboBox.currentIndex() == 0: self.ListView.clear() + self.lastReference = [] + self.lastReference.append(versetext) self.displayResults(bible) def onAdvancedFromChapter(self): @@ -421,8 +422,9 @@ class BibleMediaItem(MediaManagerItem): text = unicode(self.QuickSearchEdit.displayText()) if self.ClearQuickSearchComboBox.currentIndex() == 0: self.ListView.clear() + self.lastReference = [] + self.lastReference.append(versetext) self.search_results = self.parent.manager.get_verses(bible, text) - self.lastReference = text if self.search_results: self.displayResults(bible) @@ -442,8 +444,9 @@ class BibleMediaItem(MediaManagerItem): else: bible2 = unicode(self.AdvancedSecondBibleComboBox.currentText()) if bible2: - self.searchByReference(bible2, self.lastReference) - bible2_verses = self.search_results + 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') @@ -477,7 +480,7 @@ class BibleMediaItem(MediaManagerItem): #If not found throws and error so add.s if footer not in raw_footer: raw_footer.append(footer) - bible_text = u'%s %s \n\n %s %s)' % \ + 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'' From f81968e62b2c615b88dada7417c6e9b1264f42cc Mon Sep 17 00:00:00 2001 From: Raoul Snyman <raoul.snyman@saturnlaboratories.co.za> Date: Sat, 6 Feb 2010 15:22:26 +0200 Subject: [PATCH 32/33] Mis-named variable in QuickSearch click. --- openlp/plugins/bibles/lib/mediaitem.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index bcd9adbb3..648694f45 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -423,7 +423,7 @@ class BibleMediaItem(MediaManagerItem): if self.ClearQuickSearchComboBox.currentIndex() == 0: self.ListView.clear() self.lastReference = [] - self.lastReference.append(versetext) + self.lastReference.append(text) self.search_results = self.parent.manager.get_verses(bible, text) if self.search_results: self.displayResults(bible) From bd4d2daa74ed58b1e3f1a9e6b26089081e4934af Mon Sep 17 00:00:00 2001 From: Raoul Snyman <raoul.snyman@saturnlaboratories.co.za> Date: Sat, 6 Feb 2010 15:23:38 +0200 Subject: [PATCH 33/33] Removed now unnecessary file. --- openlp/plugins/bibles/resources/httpbooks.csv | 66 ------------------- 1 file changed, 66 deletions(-) delete mode 100644 openlp/plugins/bibles/resources/httpbooks.csv diff --git a/openlp/plugins/bibles/resources/httpbooks.csv b/openlp/plugins/bibles/resources/httpbooks.csv deleted file mode 100644 index 2d8afa20e..000000000 --- a/openlp/plugins/bibles/resources/httpbooks.csv +++ /dev/null @@ -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