More improvements and functional additions

bzr-revno: 250
This commit is contained in:
Tim Bentley 2008-12-20 16:59:56 +00:00
parent 76723fbc92
commit abb9a6e4c0
3 changed files with 484 additions and 5 deletions

View File

@ -0,0 +1,203 @@
"""
OpenLP - Open Source Lyrics Projection
Copyright (c) 2008 Raoul Snyman
Portions copyright (c) 2008 Martin Thompson, Tim Bentley
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
"""
import os, os.path
import sys
import time
import datetime
import logging
import string
from sqlalchemy import *
from sqlalchemy.sql import select
from sqlalchemy.orm import sessionmaker, mapper
from openlp.plugins.bibles.lib.biblecommon import BibleCommon
from openlp.core.utils import ConfigHelper
import logging
class BibleDBException(Exception):
pass
class BibleInvalidDatabaseError(Exception):
pass
metadata = MetaData()
#authors = Table('authors', metadata, autoload=True)
class SongDBImpl(BibleCommon):
global log
log=logging.getLogger("SongDBImpl")
log.info("SongDBImpl loaded")
def __init__(self, songpath , suffix, btype = 'sqlite'):
# Connect to database
self.songfile = os.path.join(songpath, "songs."+suffix)
log.debug( "Load Song on path %s", self.songfile)
if btype == 'sqlite':
self.db = create_engine("sqlite:///"+self.songfile)
elif btype == 'mysql':
self.db = create_engine("mysql://tim:@192.168.0.100:3306/openlp_rsv_bible")
else:
raise BibleInvalidDatabaseError("Database not mysql or sqlite")
self.db.echo = True
#self.metadata = metaData()
metadata.bind = self.db
metadata.bind.echo = False
self.Session = sessionmaker()
self.Session.configure(bind=self.db)
authors = Table('authors', metadata, autoload=True)
settings = Table('settings', metadata, autoload=True)
songauthors = Table('songauthors', metadata, autoload=True)
songs = Table('songs', metadata, autoload=True)
def create_tables(self):
log.debug( "createTables")
if os.path.exists(self.biblefile): # delete bible file and set it up again
os.remove(self.biblefile)
meta_table.create()
testament_table.create()
book_table.create()
verse_table.create()
self.save_meta("dbversion", "2")
self._loadTestaments()
def add_verse(self, bookid, chap, verse, text):
log.debug( "add_verse %s,%s,%s,%s", bookid, chap, verse, text)
metadata.bind.echo = False
session = self.Session()
versemeta = Verse(book_id=int(bookid), chapter=int(chap), verse=int(verse), text=(text))
session.add(versemeta)
session.commit()
def create_chapter(self, bookid, chap, textlist):
log.debug( "create_chapter %s,%s,%s", bookid, chap, textlist)
metadata.bind.echo = False
session = self.Session()
#s = text (""" select id FROM book where book.name == :b """)
#data = self.db.execute(s, b=bookname).fetchone()
#id = data[0] # id is first record in list.
#log.debug( "id = " , id
for v , t in textlist.iteritems():
versemeta = Verse(book_id=bookid, chapter=int(chap), verse=int(v), text=(t))
session.add(versemeta)
session.commit()
def create_book(self, bookid, bookname, bookabbrev):
log.debug( "create_book %s,%s,%s", bookid, bookname, bookabbrev)
metadata.bind.echo = False
session = self.Session()
bookmeta = Book(int(5), bookname, bookabbrev)
session.add(bookmeta)
session.commit()
def save_meta(self, key, value):
metadata.bind.echo = False
session = self.Session()
bmeta= BibleMeta(key, value)
session.add(bmeta)
session.commit()
def get_meta(self, key):
s = text (""" select value FROM metadata where key == :k """)
return self.db.execute(s, k=key).fetchone()
def delete_meta(self, key):
metadata.bind.echo = False
s = text (""" delete FROM meta where key == :k """)
self.db.execute(s, k=key)
def _load_testaments(self):
log.debug("load_testaments")
metadata.bind.echo = False
session = self.Session()
testmeta = ONTestament(name="Old Testament")
session.add(testmeta)
testmeta = ONTestament(name="New Testament")
session.add(testmeta)
testmeta = ONTestament(name="Apocrypha")
session.add(testmeta)
session.commit()
def get_bible_books(self):
log.debug( "get_bible_book ")
metadata.bind.echo = False
s = text (""" select name FROM book order by id """)
return self.db.execute(s).fetchall()
def get_max_bible_book_verses(self, bookname, chapter):
log.debug( "get_max_bible_book_verses %s,%s ", bookname , chapter)
metadata.bind.echo = False
s = text (""" select max(verse.verse) from verse,book where chapter = :c and book_id = book.id and book.name = :b """)
return self.db.execute(s, c=chapter, b=bookname).fetchone()
def get_max_bible_book_chapter(self, bookname):
log.debug( "get_max_bible_book_chapter %s ", bookname )
metadata.bind.echo = False
s = text (""" select max(verse.chapter) from verse,book where book_id = book.id and book.name = :b """)
return self.db.execute(s, b=bookname).fetchone()
def get_bible_book(self, bookname):
log.debug( "get_bible_book %s", bookname)
metadata.bind.echo = False
s = text (""" select name FROM book where book.name == :b """)
return self.db.execute(s, b=bookname).fetchone()
def get_bible_book_Id(self, bookname):
log.debug( "get_bible_book_id %s", bookname)
metadata.bind.echo = False
s = text (""" select id FROM book where book.name == :b """)
return self.db.execute(s, b=bookname).fetchone()
def get_bible_chapter(self, bookname, chapter):
log.debug( "get_bible_chapter %s,%s", bookname, chapter )
metadata.bind.echo = False
s = text (""" select book.name FROM verse,book where verse.book_id == book.id AND verse.chapter == :c and book.name == :b """)
return self.db.execute(s, c=chapter, b=bookname).fetchone()
def get_bible_text(self, bookname, chapter, sverse, everse):
log.debug( "get_bible_text %s,%s,%s,%s ", bookname, chapter, sverse, everse)
metadata.bind.echo = False
s = text (""" select name,chapter,verse.verse, verse.text FROM verse , book where verse.book_id == book.id AND verse.chapter == :c AND (verse.verse between :v1 and :v2) and book.name == :b """)
return self.db.execute(s, c=chapter, v1=sverse , v2=everse, b=bookname).fetchall()
def get_song_from_lyrics(self,searchtext):
log.debug( "get_song_from_lyrics %s",searchtext)
metadata.bind.echo = False
searchtext = "%"+searchtext+"%"
s = text (""" SELECT s.songid AS songid, s.songtitle AS songtitle, a.authorname AS authorname FROM songs s OUTER JOIN songauthors sa ON s.songid = sa.songid OUTER JOIN authors a ON sa.authorid = a.authorid WHERE s.lyrics LIKE :t ORDER BY s.songtitle ASC """)
return self.db.execute(s, t=searchtext).fetchall()
def get_song_from_title(self,searchtext):
log.debug( "get_song_from_title %s",searchtext)
metadata.bind.echo = False
searchtext = "%"+searchtext+"%"
s = text (""" SELECT s.songid AS songid, s.songtitle AS songtitle, a.authorname AS authorname FROM songs s OUTER JOIN songauthors sa ON s.songid = sa.songid OUTER JOIN authors a ON sa.authorid = a.authorid WHERE s.songtitle LIKE :t ORDER BY s.songtitle ASC """)
return self.db.execute(s, t=searchtext).fetchall()
def get_song_from_author(self,searchtext):
log.debug( "get_song_from_author %s",searchtext)
metadata.bind.echo = False
searchtext = "%"+searchtext+"%"
s = text (""" SELECT s.songid AS songid, s.songtitle AS songtitle, a.authorname AS authorname FROM songs s OUTER JOIN songauthors sa ON s.songid = sa.songid OUTER JOIN authors a ON sa.authorid = a.authorid WHERE a.authorname LIKE :t ORDER BY s.songtitle ASC """)
return self.db.execute(s, t=searchtext).fetchall()
def dump_songs(self):
log.debug( ".........Dumping Songs Database")
log.debug( "...............................Books ")
s = text (""" select * FROM authors """)
log.debug( self.db.execute(s).fetchall())

View File

@ -0,0 +1,262 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
"""
OpenLP - Open Source Lyrics Projection
Copyright (c) 2008 Raoul Snyman
Portions copyright (c) 2008 Martin Thompson, Tim Bentley
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
"""
import os, os.path
import sys
from songDBimpl import SongDBImpl
import logging
class SongManager():
global log
log=logging.getLogger("SongManager")
log.info("Song manager loaded")
def __init__(self, config):
"""
Finds all the bibles defined for the system
Creates an Interface Object for each bible containing connection information
Throws Exception if no Bibles are found.
Init confirms the bible exists and stores the database path.
"""
self.config = config
log.debug( "Song Initialising")
self.bibleDBCache = None
#self.bibleHTTPCache = {} # dict of bible http readers
self.songPath = self.config.get_data_path()
self.songSuffix = self.config.get_config("suffix name", u'olp3')
log.debug("Song Path %s and suffix %s", self.songPath, self.songSuffix )
self.dialogobject = None
files = self.config.get_files()
if len(files) > 0:
log.debug("Song File %s", files )
self.songDBCache = SongDBImpl(self.songPath, self.songSuffix)
log.debug( "Song Initialised")
def process_dialog(self, dialogobject):
self.dialogobject = dialogobject
def register_HTTP_bible(self, biblename, biblesource, mode="lazy", 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
"""
log.debug( "register_HTTP_bible %s,%s,%s,%s,%s", biblename, biblesource, proxyurl, proxyid, proxypass, mode)
if self._is_new_bible(biblename):
nbible = BibleDBImpl(self.biblePath, biblename, self.bibleSuffix) # Create new Bible
nbible.createTables() # Create Database
self.bibleDBCache[biblename] = nbible
nhttp = BibleHTTPImpl()
nhttp.setBibleSource(biblesource)
self.bibleHTTPCache[biblename] = nhttp
nbible.save_meta("WEB", biblesource) # register a lazy loading interest
if proxyurl != None:
nbible.save_meta("proxy", proxyurl) # store the proxy URL
nhttp.setProxy(proxyurl)
if proxyid != None:
nbible.save_meta("proxyid", proxyid) # store the proxy userid
if proxypass != None:
nbible.save_meta("proxypass", proxypass) # store the proxy password
def register_CVS_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.
"""
if self._is_new_bible(biblename):
nbible = BibleDBImpl(self.biblePath, biblename, self.bibleSuffix) # Create new Bible
nbible.createTables() # Create Database
self.bibleDBCache[biblename] = nbible # cache the database for use later
bcsv = BibleCSVImpl(nbible) # create the loader and pass in the database
bcsv.load_data(booksfile, versefile)
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( "register_OSIS_file_bible %s , %s", biblename, osisfile)
if self._is_new_bible(biblename):
nbible = BibleDBImpl(self.biblePath, biblename, self.bibleSuffix) # Create new Bible
nbible.createTables() # Create Database
self.bibleDBCache[biblename] = nbible # cache the database for use later
bcsv = BibleOSISImpl(self.biblePath, nbible) # create the loader and pass in the database
bcsv.loadData(osisfile, self.dialogobject)
# def loadBible(self,biblename):
# """
# Downloads all the books of the bible
# and loads it into the database
# """
# log.debug( "loadBible %s", biblename)
# bookabbrev = ""
# for bookname in self.listOfBooks:
# cptrs = self.booksChapters[ self.booksOfBible[bookname]]
# log.debug( "book and chapter %s %s", bookname , self.booksChapters[ self.booksOfBible[bookname]] )
# for chptr in range(1 , int(cptrs)): # loop through all the chapters in book
# c = self.bibleDBCache[biblename].getBibleChapter(bookname, chptr) # check to see if book/chapter exists
# log.debug( "got chapter %s", c)
# if not c:
# bookid = self.booksOfBible[bookname] # convert to id ie Genesis --> 1 Revelation --> 73
# log.debug( "missing %s,%s", bookname, chptr)
# self._loadBook(biblename,bookid, bookname, bookabbrev)
# self._loadChapter(biblename,bookid, bookname, chptr)
def get_bibles(self, mode="full"):
"""
Returns a list of Books of the bible
"""
r=[]
for b , o in self.bibleDBCache.iteritems():
if mode != "full":
print self.bibleHTTPCache[b]
r.append(b)
return r
def get_bible_books(self,bible):
"""
Returns a list of the books of the bible from the database
"""
log.debug("get_bible_books %s", bible)
return self.bibleDBCache[bible].get_bible_books()
def get_book_chapter_count(self, bible, book):
"""
Returns the number of Chapters for a given book
"""
log.debug( "get_book_chapter_count %s,%s", bible, book)
return self.bibleDBCache[bible].get_max_bible_book_chapter(book)
def get_book_verse_count(self, bible, book, chapter):
"""
Returns all the number of verses for a given
book and chapterMaxBibleBookVerses
"""
log.debug( "get_book_verse_count %s,%s,%s", bible, book, chapter)
return self.bibleDBCache[bible].get_max_bible_book_verses(book, chapter)
def get_verse_from_text(self, bible, versetext):
"""
Returns all the number of verses for a given
book and chapterMaxBibleBookVerses
"""
log.debug( "get_verses_from_text %s,%s", bible, versetext)
return self.bibleDBCache[bible].get_verses_from_text(versetext)
def save_meta_data(self, bible, version, copyright, permissions):
"""
Saves the bibles meta data
"""
log.debug( "save_meta %s,%s, %s,%s", bible, version, copyright, permissions)
self.bibleDBCache[bible].save_meta("Version", version)
self.bibleDBCache[bible].save_meta("Copyright", copyright)
self.bibleDBCache[bible].save_meta("Permissins", permissions)
def get_meta_data(self, bible, key):
"""
Returns the meta data for a given key
"""
log.debug( "get_meta %s,%s", bible, key)
self.bibleDBCache[bible].get_meta(key)
def get_verse_text(self, bible, bookname, schapter, echapter, sverse, everse = 0 ):
"""
Returns a list of verses for a given Book, Chapter and ranges of verses.
If the end verse(everse) is less then the start verse(sverse)
then only one verse is returned
bible - Which bible to use.
Rest can be guessed at !
"""
text = []
#log.debug( self.bibleDBCache)
#log.debug( self.bibleHTTPCache)
log.debug( "get_verse_text %s,%s,%s,%s,%s,%s", bible,bookname, schapter,echapter, sverse, everse)
# bookid = self.booksOfBible[bookname] # convert to id ie Genesis --> 1 Revelation --> 73
# # SORT OUT BOOKNAME BOOK ID.
# # NAME COMES IN TO ID AND BACK TO NAME ?
# c = self.bibleDBCache[bible].getBibleChapter(bookname, chapter) # check to see if book/chapter exists
# bookabbrev = ""
# log.debug( "Bible Chapter %s", c )
# if not c:
# self._loadBook(bible,bookid, bookname, bookabbrev)
# self._loadChapter(bible, bookid,bookname, chapter)
if schapter == echapter:
text = self.bibleDBCache[bible].get_bible_text(bookname, schapter, sverse, everse)
else:
for i in range (schapter, echapter + 1):
if i == schapter:
start = sverse
end = self.get_book_verse_count(bible, bookname,i )[0]
elif i == echapter:
start = 1
end = everse
else:
start = 1
end = self.get_book_verse_count(bible, bookname,i )[0]
txt = self.bibleDBCache[bible].get_bible_text(bookname, i, start, end)
text.extend(txt)
return text
def _load_book(self, bible, bookid, bookname, bookabbrev):
log.debug( "load_book %s,%s,%s,%s", bible, bookid, bookname, bookabbrev)
cl = self.bibleDBCache[bible].get_bible_book(bookname)
log.debug( "get bible book %s" , cl)
if not cl :
self.bibleDBCache[bible].create_book(bookid, bookname, bookabbrev)
def _loadChapter(self, bible, bookid, bookname, chapter):
log.debug( "load_chapter %s,%s,%s,%s", bible, bookid,bookname, chapter)
try :
chaptlist = self.bibleHTTPCache[bible].get_bible_chapter(bible, bookid,bookname, chapter)
self.bibleDBCache[bible].create_chapter(bookname, chapter, chaptlist)
except :
log.error("Errow thrown %s", sys.exc_info()[1])
def _is_new_bible(self, name):
"""
Check cache to see if new bible
"""
for b , o in self.bibleDBCache.iteritems():
log.debug( b )
if b == name :
return False
return True
def get_song_from_title(self,searchtext):
return self.songDBCache.get_song_from_title(searchtext)
def get_song_from_lyrics(self,searchtext):
return self.songDBCache.get_song_from_lyrics(searchtext)
def get_song_from_author(self,searchtext):
return self.songDBCache.get_song_from_author(searchtext)
def dump_songs(self):
self.songDBCache.dump_songs()

View File

@ -107,6 +107,7 @@ class SongsPlugin(Plugin):
self.MediaManagerItem.PageLayout.addWidget(self.SongWidget) self.MediaManagerItem.PageLayout.addWidget(self.SongWidget)
self.SongListView = QtGui.QTableWidget() self.SongListView = QtGui.QTableWidget()
self.SongListView.setColumnCount(2) self.SongListView.setColumnCount(2)
self.SongListView.setHorizontalHeaderLabels(QtCore.QStringList(["Song Name","Author"]))
self.SongListView.setGeometry(QtCore.QRect(10, 100, 256, 591)) self.SongListView.setGeometry(QtCore.QRect(10, 100, 256, 591))
self.SongListView.setObjectName("listView") self.SongListView.setObjectName("listView")
self.MediaManagerItem.PageLayout.addWidget(self.SongListView) self.MediaManagerItem.PageLayout.addWidget(self.SongListView)
@ -182,10 +183,19 @@ class SongsPlugin(Plugin):
def onSearchTextButton(self): def onSearchTextButton(self):
searchtext = str(self.SearchTextEdit.displayText() ) searchtext = str(self.SearchTextEdit.displayText() )
if str(self.SearchTypeComboBox.currentText=="Titles"): ct = self.SearchTypeComboBox.currentText()
print ct , str(ct)
if self.SearchTypeComboBox.currentText()=="Titles":
print "Titles"
self.searchresults = self.songmanager.get_song_from_title(searchtext) self.searchresults = self.songmanager.get_song_from_title(searchtext)
elif str(self.SearchTypeComboBox.currentText=="Lyrics"): elif self.SearchTypeComboBox.currentText()=="Lyrics":
print "Lyrics"
self.searchresults = self.songmanager.get_song_from_lyrics(searchtext) self.searchresults = self.songmanager.get_song_from_lyrics(searchtext)
elif self.SearchTypeComboBox.currentText()=="Authors":
print "Authors"
self.searchresults = self.songmanager.get_song_from_author(searchtext)
else:
print "missed ", ct
self._display_results() self._display_results()
def onSongNewClick(self): def onSongNewClick(self):
@ -220,9 +230,13 @@ class SongsPlugin(Plugin):
def _display_results(self): def _display_results(self):
self.SongListView.clear() # clear the results self.SongListView.clear() # clear the results
self.SongListView.setHorizontalHeaderLabels(QtCore.QStringList(["Song Name","Author"]))
self.SongListView.setRowCount(0) self.SongListView.setRowCount(0)
for id, txt in self.searchresults: for id, txt, name in self.searchresults:
c = self.SongListView.rowCount() c = self.SongListView.rowCount()
self.SongListView.setRowCount(c+1) self.SongListView.setRowCount(c+1)
twi = QtGui.QTableWidgetItem(str(txt)) twi = QtGui.QTableWidgetItem(str(txt))
self.SongListView.setItem(c , 0, twi) self.SongListView.setItem(c , 0, twi)
twi = QtGui.QTableWidgetItem(str(name))
self.SongListView.setItem(c , 1, twi)