From 55f6197212478480665e3310e744ef536a53aeb1 Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Sat, 12 Jun 2010 02:52:04 +0100 Subject: [PATCH 01/11] RFC: Refactor database setup code A possible way to refactor database code to remove code duplication and, I hope, provide a simpler, more intuitive model to be copied by others --- openlp/core/lib/__init__.py | 1 - openlp/core/lib/{basemodel.py => db.py} | 26 ++- openlp/migration/migratebibles.py | 3 +- openlp/migration/migratesongs.py | 3 +- openlp/plugins/alerts/forms/alertform.py | 2 +- .../plugins/alerts/lib/{classes.py => db.py} | 28 +++- openlp/plugins/alerts/lib/manager.py | 7 +- openlp/plugins/alerts/lib/meta.py | 38 ----- openlp/plugins/alerts/lib/models.py | 39 ----- openlp/plugins/alerts/lib/tables.py | 33 ---- openlp/plugins/bibles/lib/models.py | 2 +- openlp/plugins/custom/lib/classes.py | 2 +- openlp/plugins/songs/forms/authorsdialog.py | 1 + openlp/plugins/songs/forms/authorsform.py | 1 - openlp/plugins/songs/forms/editsongdialog.py | 3 +- openlp/plugins/songs/forms/editsongform.py | 2 +- openlp/plugins/songs/forms/songbookdialog.py | 1 + openlp/plugins/songs/forms/songbookform.py | 1 - .../songs/forms/songmaintenanceform.py | 4 +- openlp/plugins/songs/forms/topicsdialog.py | 1 + openlp/plugins/songs/forms/topicsform.py | 1 - openlp/plugins/songs/lib/classes.py | 52 ------ openlp/plugins/songs/lib/db.py | 150 ++++++++++++++++++ openlp/plugins/songs/lib/manager.py | 7 +- openlp/plugins/songs/lib/meta.py | 38 ----- openlp/plugins/songs/lib/models.py | 48 ------ openlp/plugins/songs/lib/songimport.py | 2 +- openlp/plugins/songs/lib/tables.py | 99 ------------ openlp/plugins/songs/songsplugin.py | 1 - openlp/plugins/songusage/lib/classes.py | 2 +- 30 files changed, 223 insertions(+), 375 deletions(-) rename openlp/core/lib/{basemodel.py => db.py} (74%) rename openlp/plugins/alerts/lib/{classes.py => db.py} (72%) delete mode 100644 openlp/plugins/alerts/lib/meta.py delete mode 100644 openlp/plugins/alerts/lib/models.py delete mode 100644 openlp/plugins/alerts/lib/tables.py delete mode 100644 openlp/plugins/songs/lib/classes.py create mode 100644 openlp/plugins/songs/lib/db.py delete mode 100644 openlp/plugins/songs/lib/meta.py delete mode 100644 openlp/plugins/songs/lib/models.py delete mode 100644 openlp/plugins/songs/lib/tables.py diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py index d5b46e6cb..e09b6f1b4 100644 --- a/openlp/core/lib/__init__.py +++ b/openlp/core/lib/__init__.py @@ -184,5 +184,4 @@ from themexmlhandler import ThemeXML from renderer import Renderer from rendermanager import RenderManager from mediamanageritem import MediaManagerItem -from basemodel import BaseModel from baselistwithdnd import BaseListWithDnD diff --git a/openlp/core/lib/basemodel.py b/openlp/core/lib/db.py similarity index 74% rename from openlp/core/lib/basemodel.py rename to openlp/core/lib/db.py index f56336c7b..4762da157 100644 --- a/openlp/core/lib/basemodel.py +++ b/openlp/core/lib/db.py @@ -22,6 +22,31 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### +""" +The :mod:`db` module provides the core database functionality for OpenLP +""" + +from sqlalchemy import create_engine, MetaData +from sqlalchemy.orm import scoped_session, sessionmaker + +def init_db(url, auto_flush=True, auto_commit=False): + """ + Initialise and return the session and metadata for a database + + ``url`` + The database to initialise connection with + + ``auto_flush`` + Sets the flushing behaviour of the session + + ``auto_commit`` + Sets the commit behaviour of the session + """ + engine = create_engine(url) + metadata = MetaData(bind=engine) + session = scoped_session(sessionmaker(autoflush=auto_flush, + autocommit=auto_commit, bind=engine)) + return session, metadata class BaseModel(object): """ @@ -37,4 +62,3 @@ class BaseModel(object): for key in kwargs: me.__setattr__(key, kwargs[key]) return me - diff --git a/openlp/migration/migratebibles.py b/openlp/migration/migratebibles.py index 89bb5ffdf..b024343a4 100644 --- a/openlp/migration/migratebibles.py +++ b/openlp/migration/migratebibles.py @@ -30,7 +30,8 @@ import sqlite3 from sqlalchemy.exceptions import InvalidRequestError from sqlalchemy.orm import mapper -from openlp.core.lib import BaseModel, SettingsManager +from openlp.core.lib import SettingsManager +from openlp.core.lib.db import BaseModel from openlp.core.utils import AppLocation from openlp.plugins.bibles.lib.models import * diff --git a/openlp/migration/migratesongs.py b/openlp/migration/migratesongs.py index 87d5de40b..c4cab00bc 100644 --- a/openlp/migration/migratesongs.py +++ b/openlp/migration/migratesongs.py @@ -31,7 +31,8 @@ from sqlalchemy import create_engine from sqlalchemy.exceptions import InvalidRequestError from sqlalchemy.orm import scoped_session, sessionmaker, mapper, relation -from openlp.core.lib import BaseModel, SettingsManager +from openlp.core.lib import SettingsManager +from openlp.core.lib.db import BaseModel from openlp.core.utils import AppLocation from openlp.plugins.songs.lib.models import metadata, songs_table, Song, \ Author, Topic, Book diff --git a/openlp/plugins/alerts/forms/alertform.py b/openlp/plugins/alerts/forms/alertform.py index 04028fc1b..e8fc0d2fe 100644 --- a/openlp/plugins/alerts/forms/alertform.py +++ b/openlp/plugins/alerts/forms/alertform.py @@ -25,8 +25,8 @@ from PyQt4 import QtGui, QtCore -from openlp.plugins.alerts.lib.models import AlertItem from openlp.core.lib import translate +from openlp.plugins.alerts.lib.db import AlertItem from alertdialog import Ui_AlertDialog diff --git a/openlp/plugins/alerts/lib/classes.py b/openlp/plugins/alerts/lib/db.py similarity index 72% rename from openlp/plugins/alerts/lib/classes.py rename to openlp/plugins/alerts/lib/db.py index e58f80829..3656d41b8 100644 --- a/openlp/plugins/alerts/lib/classes.py +++ b/openlp/plugins/alerts/lib/db.py @@ -22,11 +22,35 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### +""" +The :mod:`db` module provides the database and schema that is the backend for +the Alerts plugin +""" -from openlp.core.lib import BaseModel +from sqlalchemy import Column, Table, types +from sqlalchemy.orm import mapper + +from openlp.core.lib.db import BaseModel, init_db class AlertItem(BaseModel): """ - Custom Slide model + AlertItem model """ pass + +def init_schema(url): + """ + Setup the alerts database connection and initialise the database schema + + ``url`` + The database to setup + """ + session, metadata = init_db(url) + + alerts_table = Table(u'alerts', metadata, + Column(u'id', types.Integer(), primary_key=True), + Column(u'text', types.UnicodeText, nullable=False)) + + mapper(AlertItem, alerts_table) + + return session, metadata diff --git a/openlp/plugins/alerts/lib/manager.py b/openlp/plugins/alerts/lib/manager.py index 088f0cbae..814e3dca6 100644 --- a/openlp/plugins/alerts/lib/manager.py +++ b/openlp/plugins/alerts/lib/manager.py @@ -29,7 +29,7 @@ from PyQt4 import QtCore from sqlalchemy.exceptions import InvalidRequestError from openlp.core.utils import AppLocation -from openlp.plugins.alerts.lib.models import init_models, metadata, AlertItem +from openlp.plugins.alerts.lib.db import init_schema, AlertItem log = logging.getLogger(__name__) @@ -61,8 +61,8 @@ class DBManager(object): unicode(settings.value(u'db hostname').toString()), unicode(settings.value(u'db database').toString())) settings.endGroup() - self.session = init_models(self.db_url) - metadata.create_all(checkfirst=True) + self.session, self.metadata = init_schema(self.db_url) + self.metadata.create_all(checkfirst=True) log.debug(u'Alerts Initialised') def get_all_alerts(self): @@ -111,4 +111,3 @@ class DBManager(object): return False else: return True - diff --git a/openlp/plugins/alerts/lib/meta.py b/openlp/plugins/alerts/lib/meta.py deleted file mode 100644 index affa31969..000000000 --- a/openlp/plugins/alerts/lib/meta.py +++ /dev/null @@ -1,38 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, 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 # -############################################################################### - -from sqlalchemy import MetaData - -__all__ = ['session', 'metadata', 'engine'] - -# SQLAlchemy database engine. Updated by model.init_model() -engine = None - -# SQLAlchemy session manager. Updated by model.init_model() -session = None - -# Global metadata. If you have multiple databases with overlapping table -# names, you'll need a metadata for each database -metadata = MetaData() diff --git a/openlp/plugins/alerts/lib/models.py b/openlp/plugins/alerts/lib/models.py deleted file mode 100644 index f222345f1..000000000 --- a/openlp/plugins/alerts/lib/models.py +++ /dev/null @@ -1,39 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, 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 # -############################################################################### - -from sqlalchemy import create_engine -from sqlalchemy.orm import scoped_session, sessionmaker, mapper - -from openlp.plugins.alerts.lib.meta import metadata -from openlp.plugins.alerts.lib.tables import * -from openlp.plugins.alerts.lib.classes import * - -def init_models(url): - engine = create_engine(url) - metadata.bind = engine - session = scoped_session(sessionmaker(autoflush=True, autocommit=False, - bind=engine)) - mapper(AlertItem, alerts_table) - return session diff --git a/openlp/plugins/alerts/lib/tables.py b/openlp/plugins/alerts/lib/tables.py deleted file mode 100644 index 0e707570d..000000000 --- a/openlp/plugins/alerts/lib/tables.py +++ /dev/null @@ -1,33 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, 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 # -############################################################################### - -from sqlalchemy import Column, Table, types - -from openlp.plugins.alerts.lib.meta import metadata - -# Definition of the "alerts" table -alerts_table = Table(u'alerts', metadata, - Column(u'id', types.Integer(), primary_key=True), - Column(u'text', types.UnicodeText, nullable=False)) diff --git a/openlp/plugins/bibles/lib/models.py b/openlp/plugins/bibles/lib/models.py index d970bce08..2cd52fb0b 100644 --- a/openlp/plugins/bibles/lib/models.py +++ b/openlp/plugins/bibles/lib/models.py @@ -27,7 +27,7 @@ from sqlalchemy import Column, Table, MetaData, ForeignKey, types, \ create_engine from sqlalchemy.orm import mapper, relation, sessionmaker, scoped_session -from openlp.core.lib import BaseModel +from openlp.core.lib.db import BaseModel class BibleMeta(BaseModel): diff --git a/openlp/plugins/custom/lib/classes.py b/openlp/plugins/custom/lib/classes.py index dc6c5c1b8..6d8c623d1 100644 --- a/openlp/plugins/custom/lib/classes.py +++ b/openlp/plugins/custom/lib/classes.py @@ -23,7 +23,7 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from openlp.core.lib import BaseModel +from openlp.core.lib.db import BaseModel class CustomSlide(BaseModel): """ diff --git a/openlp/plugins/songs/forms/authorsdialog.py b/openlp/plugins/songs/forms/authorsdialog.py index 082b1133d..1a7a4ccb5 100644 --- a/openlp/plugins/songs/forms/authorsdialog.py +++ b/openlp/plugins/songs/forms/authorsdialog.py @@ -24,6 +24,7 @@ ############################################################################### from PyQt4 import QtCore, QtGui + from openlp.core.lib import translate class Ui_AuthorsDialog(object): diff --git a/openlp/plugins/songs/forms/authorsform.py b/openlp/plugins/songs/forms/authorsform.py index 4d7fcd4b6..c5d0b2fa4 100644 --- a/openlp/plugins/songs/forms/authorsform.py +++ b/openlp/plugins/songs/forms/authorsform.py @@ -28,7 +28,6 @@ from PyQt4 import QtGui, QtCore from openlp.core.lib import translate from openlp.plugins.songs.forms.authorsdialog import Ui_AuthorsDialog - class AuthorsForm(QtGui.QDialog, Ui_AuthorsDialog): """ Class to control the Maintenance of Authors Dialog diff --git a/openlp/plugins/songs/forms/editsongdialog.py b/openlp/plugins/songs/forms/editsongdialog.py index d613715dd..9c088ea30 100644 --- a/openlp/plugins/songs/forms/editsongdialog.py +++ b/openlp/plugins/songs/forms/editsongdialog.py @@ -24,9 +24,8 @@ ############################################################################### from PyQt4 import QtCore, QtGui -from openlp.core.lib import translate -from openlp.core.lib import build_icon +from openlp.core.lib import build_icon, translate class Ui_EditSongDialog(object): def setupUi(self, EditSongDialog): diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py index d23bcd298..1ae8796f5 100644 --- a/openlp/plugins/songs/forms/editsongform.py +++ b/openlp/plugins/songs/forms/editsongform.py @@ -30,7 +30,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import SongXMLBuilder, SongXMLParser, Receiver, translate from openlp.plugins.songs.forms import EditVerseForm -from openlp.plugins.songs.lib.models import Song +from openlp.plugins.songs.lib.db import Song from editsongdialog import Ui_EditSongDialog log = logging.getLogger(__name__) diff --git a/openlp/plugins/songs/forms/songbookdialog.py b/openlp/plugins/songs/forms/songbookdialog.py index 06e27d04e..578be03fc 100644 --- a/openlp/plugins/songs/forms/songbookdialog.py +++ b/openlp/plugins/songs/forms/songbookdialog.py @@ -24,6 +24,7 @@ ############################################################################### from PyQt4 import QtCore, QtGui + from openlp.core.lib import translate class Ui_SongBookDialog(object): diff --git a/openlp/plugins/songs/forms/songbookform.py b/openlp/plugins/songs/forms/songbookform.py index ad85990f0..172b74892 100644 --- a/openlp/plugins/songs/forms/songbookform.py +++ b/openlp/plugins/songs/forms/songbookform.py @@ -28,7 +28,6 @@ from PyQt4 import QtGui from openlp.core.lib import translate from openlp.plugins.songs.forms.songbookdialog import Ui_SongBookDialog - class SongBookForm(QtGui.QDialog, Ui_SongBookDialog): """ Class documentation goes here. diff --git a/openlp/plugins/songs/forms/songmaintenanceform.py b/openlp/plugins/songs/forms/songmaintenanceform.py index 34388dd62..d6ac7bf04 100644 --- a/openlp/plugins/songs/forms/songmaintenanceform.py +++ b/openlp/plugins/songs/forms/songmaintenanceform.py @@ -25,12 +25,12 @@ from PyQt4 import QtGui, QtCore -from openlp.plugins.songs.lib.classes import Author, Book, Topic +from openlp.core.lib import translate +from openlp.plugins.songs.lib.db import Author, Book, Topic from songmaintenancedialog import Ui_SongMaintenanceDialog from authorsform import AuthorsForm from topicsform import TopicsForm from songbookform import SongBookForm -from openlp.core.lib import translate class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): """ diff --git a/openlp/plugins/songs/forms/topicsdialog.py b/openlp/plugins/songs/forms/topicsdialog.py index 3ed9da3c3..9200285f7 100644 --- a/openlp/plugins/songs/forms/topicsdialog.py +++ b/openlp/plugins/songs/forms/topicsdialog.py @@ -24,6 +24,7 @@ ############################################################################### from PyQt4 import QtCore, QtGui + from openlp.core.lib import translate class Ui_TopicsDialog(object): diff --git a/openlp/plugins/songs/forms/topicsform.py b/openlp/plugins/songs/forms/topicsform.py index fc5efe38d..a78c88c5a 100644 --- a/openlp/plugins/songs/forms/topicsform.py +++ b/openlp/plugins/songs/forms/topicsform.py @@ -28,7 +28,6 @@ from PyQt4 import QtGui from openlp.core.lib import translate from openlp.plugins.songs.forms.topicsdialog import Ui_TopicsDialog - class TopicsForm(QtGui.QDialog, Ui_TopicsDialog): """ Class documentation goes here. diff --git a/openlp/plugins/songs/lib/classes.py b/openlp/plugins/songs/lib/classes.py deleted file mode 100644 index c465588a4..000000000 --- a/openlp/plugins/songs/lib/classes.py +++ /dev/null @@ -1,52 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, 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 # -############################################################################### - -from openlp.core.lib import BaseModel - -class Author(BaseModel): - """ - Author model - """ - pass - -class Book(BaseModel): - """ - Book model - """ - def __repr__(self): - return u'' % ( - str(self.id), self.name, self.publisher) - -class Song(BaseModel): - """ - Song model - """ - pass - -class Topic(BaseModel): - """ - Topic model - """ - pass diff --git a/openlp/plugins/songs/lib/db.py b/openlp/plugins/songs/lib/db.py new file mode 100644 index 000000000..3c1aae7cb --- /dev/null +++ b/openlp/plugins/songs/lib/db.py @@ -0,0 +1,150 @@ +# -*- 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, Christian Richter, 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 # +############################################################################### +""" +The :mod:`db` module provides the database and schema that is the backend for +the Songs plugin +""" + +from sqlalchemy import Column, ForeignKey, Index, Table, types +from sqlalchemy.orm import mapper, relation + +from openlp.core.lib.db import BaseModel, init_db + +class Author(BaseModel): + """ + Author model + """ + pass + +class Book(BaseModel): + """ + Book model + """ + def __repr__(self): + return u'' % ( + str(self.id), self.name, self.publisher) + +class Song(BaseModel): + """ + Song model + """ + pass + +class Topic(BaseModel): + """ + Topic model + """ + pass + +def init_schema(url): + """ + Setup the songs database connection and initialise the database schema + + ``url`` + The database to setup + """ + session, metadata = init_db(url, auto_flush=False) + + # Definition of the "authors" table + authors_table = Table(u'authors', metadata, + Column(u'id', types.Integer, primary_key=True), + Column(u'first_name', types.Unicode(128)), + Column(u'last_name', types.Unicode(128)), + Column(u'display_name', types.Unicode(255), nullable=False) + ) + + # Definition of the "song_books" table + song_books_table = Table(u'song_books', metadata, + Column(u'id', types.Integer, primary_key=True), + Column(u'name', types.Unicode(128), nullable=False), + Column(u'publisher', types.Unicode(128)) + ) + + # Definition of the "songs" table + songs_table = Table(u'songs', metadata, + Column(u'id', types.Integer, primary_key=True), + Column(u'song_book_id', types.Integer, + ForeignKey(u'song_books.id'), default=0), + Column(u'title', types.Unicode(255), nullable=False), + Column(u'lyrics', types.UnicodeText, nullable=False), + Column(u'verse_order', types.Unicode(128)), + Column(u'copyright', types.Unicode(255)), + Column(u'comments', types.UnicodeText), + Column(u'ccli_number', types.Unicode(64)), + Column(u'song_number', types.Unicode(64)), + Column(u'theme_name', types.Unicode(128)), + Column(u'search_title', types.Unicode(255), index=True, nullable=False), + Column(u'search_lyrics', types.UnicodeText, index=True, nullable=False) + ) + + # Definition of the "topics" table + topics_table = Table(u'topics', metadata, + Column(u'id', types.Integer, primary_key=True), + Column(u'name', types.Unicode(128), nullable=False) + ) + + # Definition of the "authors_songs" table + authors_songs_table = Table(u'authors_songs', metadata, + Column(u'author_id', types.Integer, + ForeignKey(u'authors.id'), primary_key=True), + Column(u'song_id', types.Integer, + ForeignKey(u'songs.id'), primary_key=True) + ) + + # Definition of the "songs_topics" table + songs_topics_table = Table(u'songs_topics', metadata, + Column(u'song_id', types.Integer, + ForeignKey(u'songs.id'), primary_key=True), + Column(u'topic_id', types.Integer, + ForeignKey(u'topics.id'), primary_key=True) + ) + + # Define table indexes + Index(u'authors_id', authors_table.c.id) + Index(u'authors_display_name_id', authors_table.c.display_name, + authors_table.c.id) + Index(u'song_books_id', song_books_table.c.id) + Index(u'songs_id', songs_table.c.id) + Index(u'topics_id', topics_table.c.id) + Index(u'authors_songs_author', authors_songs_table.c.author_id, + authors_songs_table.c.song_id) + Index(u'authors_songs_song', authors_songs_table.c.song_id, + authors_songs_table.c.author_id) + Index(u'topics_song_topic', songs_topics_table.c.topic_id, + songs_topics_table.c.song_id) + Index(u'topics_song_song', songs_topics_table.c.song_id, + songs_topics_table.c.topic_id) + + mapper(Author, authors_table) + mapper(Book, song_books_table) + mapper(Song, songs_table, + properties={'authors': relation(Author, backref='songs', + secondary=authors_songs_table), + 'book': relation(Book, backref='songs'), + 'topics': relation(Topic, backref='songs', + secondary=songs_topics_table)}) + mapper(Topic, topics_table) + + return session, metadata diff --git a/openlp/plugins/songs/lib/manager.py b/openlp/plugins/songs/lib/manager.py index 0b833fb0b..0194cea5b 100644 --- a/openlp/plugins/songs/lib/manager.py +++ b/openlp/plugins/songs/lib/manager.py @@ -29,8 +29,7 @@ from PyQt4 import QtCore from sqlalchemy.exceptions import InvalidRequestError from openlp.core.utils import AppLocation -from openlp.plugins.songs.lib.models import init_models, metadata, Song, \ - Author, Topic, Book +from openlp.plugins.songs.lib.db import init_schema, Song, Author, Topic, Book #from openlp.plugins.songs.lib import OpenLyricsSong, OpenSongSong, CCLISong, \ # CSVSong @@ -111,8 +110,8 @@ class SongManager(object): u'db hostname', QtCore.QVariant(u'')).toString()), unicode(settings.value( u'db database', QtCore.QVariant(u'')).toString())) - self.session = init_models(self.db_url) - metadata.create_all(checkfirst=True) + self.session, self.metadata = init_schema(self.db_url) + self.metadata.create_all(checkfirst=True) settings.endGroup() log.debug(u'Song Initialised') diff --git a/openlp/plugins/songs/lib/meta.py b/openlp/plugins/songs/lib/meta.py deleted file mode 100644 index affa31969..000000000 --- a/openlp/plugins/songs/lib/meta.py +++ /dev/null @@ -1,38 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, 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 # -############################################################################### - -from sqlalchemy import MetaData - -__all__ = ['session', 'metadata', 'engine'] - -# SQLAlchemy database engine. Updated by model.init_model() -engine = None - -# SQLAlchemy session manager. Updated by model.init_model() -session = None - -# Global metadata. If you have multiple databases with overlapping table -# names, you'll need a metadata for each database -metadata = MetaData() diff --git a/openlp/plugins/songs/lib/models.py b/openlp/plugins/songs/lib/models.py deleted file mode 100644 index 272981d20..000000000 --- a/openlp/plugins/songs/lib/models.py +++ /dev/null @@ -1,48 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, 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 # -############################################################################### - -from sqlalchemy import create_engine -from sqlalchemy.orm import scoped_session, sessionmaker, mapper, relation - -from openlp.plugins.songs.lib.meta import metadata -from openlp.plugins.songs.lib.tables import * -from openlp.plugins.songs.lib.classes import * - -def init_models(url): - engine = create_engine(url) - metadata.bind = engine - session = scoped_session(sessionmaker(autoflush=False, autocommit=False, - bind=engine)) - mapper(Author, authors_table) - mapper(Book, song_books_table) - mapper(Song, songs_table, - properties={'authors': relation(Author, backref='songs', - secondary=authors_songs_table), - 'book': relation(Book, backref='songs'), - 'topics': relation(Topic, backref='songs', - secondary=songs_topics_table)}) - mapper(Topic, topics_table) - return session - diff --git a/openlp/plugins/songs/lib/songimport.py b/openlp/plugins/songs/lib/songimport.py index fa016729d..f2222e09b 100644 --- a/openlp/plugins/songs/lib/songimport.py +++ b/openlp/plugins/songs/lib/songimport.py @@ -28,7 +28,7 @@ import string from PyQt4 import QtGui from openlp.core.lib import SongXMLBuilder -from openlp.plugins.songs.lib.models import Song, Author, Topic, Book +from openlp.plugins.songs.lib.db import Song, Author, Topic, Book from openlp.plugins.songs.forms import VerseType class SongImport(object): diff --git a/openlp/plugins/songs/lib/tables.py b/openlp/plugins/songs/lib/tables.py deleted file mode 100644 index 24137d7b1..000000000 --- a/openlp/plugins/songs/lib/tables.py +++ /dev/null @@ -1,99 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, 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 # -############################################################################### - -from sqlalchemy import * -from sqlalchemy import Column, Table, ForeignKey, types - -from openlp.plugins.songs.lib.meta import metadata - -# Definition of the "authors" table -authors_table = Table(u'authors', metadata, - Column(u'id', types.Integer, primary_key=True), - Column(u'first_name', types.Unicode(128)), - Column(u'last_name', types.Unicode(128)), - Column(u'display_name', types.Unicode(255), nullable=False) -) - -# Definition of the "song_books" table -song_books_table = Table(u'song_books', metadata, - Column(u'id', types.Integer, primary_key=True), - Column(u'name', types.Unicode(128), nullable=False), - Column(u'publisher', types.Unicode(128)) -) - -# Definition of the "songs" table -songs_table = Table(u'songs', metadata, - Column(u'id', types.Integer, primary_key=True), - Column(u'song_book_id', types.Integer, - ForeignKey(u'song_books.id'), default=0), - Column(u'title', types.Unicode(255), nullable=False), - Column(u'lyrics', types.UnicodeText, nullable=False), - Column(u'verse_order', types.Unicode(128)), - Column(u'copyright', types.Unicode(255)), - Column(u'comments', types.UnicodeText), - Column(u'ccli_number', types.Unicode(64)), - Column(u'song_number', types.Unicode(64)), - Column(u'theme_name', types.Unicode(128)), - Column(u'search_title', types.Unicode(255), index=True, nullable=False), - Column(u'search_lyrics', types.UnicodeText, index=True, nullable=False) -) - -# Definition of the "topics" table -topics_table = Table(u'topics', metadata, - Column(u'id', types.Integer, primary_key=True), - Column(u'name', types.Unicode(128), nullable=False) -) - -# Definition of the "authors_songs" table -authors_songs_table = Table(u'authors_songs', metadata, - Column(u'author_id', types.Integer, - ForeignKey(u'authors.id'), primary_key=True), - Column(u'song_id', types.Integer, - ForeignKey(u'songs.id'), primary_key=True) -) - -# Definition of the "songs_topics" table -songs_topics_table = Table(u'songs_topics', metadata, - Column(u'song_id', types.Integer, - ForeignKey(u'songs.id'), primary_key=True), - Column(u'topic_id', types.Integer, - ForeignKey(u'topics.id'), primary_key=True) -) - -# Define table indexes -Index(u'authors_id', authors_table.c.id) -Index(u'authors_display_name_id', authors_table.c.display_name, - authors_table.c.id) -Index(u'song_books_id', song_books_table.c.id) -Index(u'songs_id', songs_table.c.id) -Index(u'topics_id', topics_table.c.id) -Index(u'authors_songs_author', authors_songs_table.c.author_id, - authors_songs_table.c.song_id) -Index(u'authors_songs_song', authors_songs_table.c.song_id, - authors_songs_table.c.author_id) -Index(u'topics_song_topic', songs_topics_table.c.topic_id, - songs_topics_table.c.song_id) -Index(u'topics_song_song', songs_topics_table.c.song_id, - songs_topics_table.c.topic_id) diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py index 993b18bb9..09485082c 100644 --- a/openlp/plugins/songs/songsplugin.py +++ b/openlp/plugins/songs/songsplugin.py @@ -34,7 +34,6 @@ from openlp.plugins.songs.lib import SongManager, SongMediaItem, SongsTab, \ log = logging.getLogger(__name__) - class SongsPlugin(Plugin): """ This is the number 1 plugin, if importance were placed on any diff --git a/openlp/plugins/songusage/lib/classes.py b/openlp/plugins/songusage/lib/classes.py index 298380f58..885d87faf 100644 --- a/openlp/plugins/songusage/lib/classes.py +++ b/openlp/plugins/songusage/lib/classes.py @@ -23,7 +23,7 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from openlp.core.lib import BaseModel +from openlp.core.lib.db import BaseModel class SongUsageItem(BaseModel): """ From 5f2042168da20d5ebe51e57da091aa5142af761c Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Sat, 12 Jun 2010 03:14:18 +0100 Subject: [PATCH 02/11] RFC: Cleanup DB metadata for RFC --- openlp/plugins/alerts/lib/db.py | 3 ++- openlp/plugins/alerts/lib/manager.py | 3 +-- openlp/plugins/songs/lib/db.py | 3 ++- openlp/plugins/songs/lib/manager.py | 3 +-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/openlp/plugins/alerts/lib/db.py b/openlp/plugins/alerts/lib/db.py index 3656d41b8..5e4b1a99a 100644 --- a/openlp/plugins/alerts/lib/db.py +++ b/openlp/plugins/alerts/lib/db.py @@ -53,4 +53,5 @@ def init_schema(url): mapper(AlertItem, alerts_table) - return session, metadata + metadata.create_all(checkfirst=True) + return session diff --git a/openlp/plugins/alerts/lib/manager.py b/openlp/plugins/alerts/lib/manager.py index 814e3dca6..7b5cf2da0 100644 --- a/openlp/plugins/alerts/lib/manager.py +++ b/openlp/plugins/alerts/lib/manager.py @@ -61,8 +61,7 @@ class DBManager(object): unicode(settings.value(u'db hostname').toString()), unicode(settings.value(u'db database').toString())) settings.endGroup() - self.session, self.metadata = init_schema(self.db_url) - self.metadata.create_all(checkfirst=True) + self.session = init_schema(self.db_url) log.debug(u'Alerts Initialised') def get_all_alerts(self): diff --git a/openlp/plugins/songs/lib/db.py b/openlp/plugins/songs/lib/db.py index 3c1aae7cb..655043144 100644 --- a/openlp/plugins/songs/lib/db.py +++ b/openlp/plugins/songs/lib/db.py @@ -147,4 +147,5 @@ def init_schema(url): secondary=songs_topics_table)}) mapper(Topic, topics_table) - return session, metadata + metadata.create_all(checkfirst=True) + return session diff --git a/openlp/plugins/songs/lib/manager.py b/openlp/plugins/songs/lib/manager.py index 0194cea5b..8e0a79ef7 100644 --- a/openlp/plugins/songs/lib/manager.py +++ b/openlp/plugins/songs/lib/manager.py @@ -110,8 +110,7 @@ class SongManager(object): u'db hostname', QtCore.QVariant(u'')).toString()), unicode(settings.value( u'db database', QtCore.QVariant(u'')).toString())) - self.session, self.metadata = init_schema(self.db_url) - self.metadata.create_all(checkfirst=True) + self.session = init_schema(self.db_url) settings.endGroup() log.debug(u'Song Initialised') From 54aa8958fee401780392f77ba1277e148533d436 Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Sun, 13 Jun 2010 00:00:14 +0100 Subject: [PATCH 03/11] RFC PT2: Refactor Manager --- openlp/core/lib/db.py | 121 ++++++++++++ openlp/plugins/alerts/alertsplugin.py | 6 +- openlp/plugins/alerts/forms/alertform.py | 11 +- openlp/plugins/alerts/lib/__init__.py | 1 - openlp/plugins/alerts/lib/manager.py | 112 ----------- openlp/plugins/songs/forms/editsongform.py | 24 +-- .../songs/forms/songmaintenanceform.py | 48 ++--- openlp/plugins/songs/lib/manager.py | 185 +----------------- openlp/plugins/songs/lib/mediaitem.py | 7 +- openlp/plugins/songs/lib/songimport.py | 8 +- openlp/plugins/songs/songsplugin.py | 4 +- 11 files changed, 176 insertions(+), 351 deletions(-) delete mode 100644 openlp/plugins/alerts/lib/manager.py diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index 4762da157..323b48e39 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -25,10 +25,17 @@ """ The :mod:`db` module provides the core database functionality for OpenLP """ +import logging +from PyQt4 import QtCore from sqlalchemy import create_engine, MetaData +from sqlalchemy.exceptions import InvalidRequestError from sqlalchemy.orm import scoped_session, sessionmaker +from openlp.core.utils import AppLocation + +log = logging.getLogger(__name__) + def init_db(url, auto_flush=True, auto_commit=False): """ Initialise and return the session and metadata for a database @@ -62,3 +69,117 @@ class BaseModel(object): for key in kwargs: me.__setattr__(key, kwargs[key]) return me + +class Manager(object): + """ + Provide generic object persistence management + """ + def __init__(self, plugin_name, init_schema): + """ + Runs the initialisation process that includes creating the connection + to the database and the tables if they don't exist. + + ``plugin_name`` + The name to setup paths and settings section names + """ + settings = QtCore.QSettings() + settings.beginGroup(plugin_name) + self.db_url = u'' + db_type = unicode( + settings.value(u'db type', QtCore.QVariant(u'sqlite')).toString()) + if db_type == u'sqlite': + self.db_url = u'sqlite:///%s/%s.sqlite' % ( + AppLocation.get_section_data_path(plugin_name), plugin_name) + else: + self.db_url = u'%s://%s:%s@%s/%s' % (db_type, + unicode(settings.value(u'db username').toString()), + unicode(settings.value(u'db password').toString()), + unicode(settings.value(u'db hostname').toString()), + unicode(settings.value(u'db database').toString())) + settings.endGroup() + self.session = init_schema(self.db_url) + + def insert_object(self, object_instance): + """ + Save an object to the database + + ``object_instance`` + The object to save + """ + try: + self.session.add(object_instance) + self.session.commit() + return True + except InvalidRequestError: + self.session.rollback() + log.exception(u'Object save failed') + return False + + def get_object(self, object_class, id=None): + """ + Return the details of an object + + ``object_class`` + The type of object to return + + ``id`` + The unique reference for the class instance to return + """ + if not id: + return object_class() + else: + return self.session.query(object_class).get(id) + + def get_all_objects(self, object_class, order_by_ref=None): + """ + Returns all the objects from the database + + ``object_class`` + The type of object to return + + ``order_by_ref`` + Any parameters to order the returned objects by. Defaults to None. + """ + if order_by_ref: + return self.session.query(object_class).order_by(order_by_ref).all() + return self.session.query(object_class).all() + + def delete_object(self, object_class, id): + """ + Delete an object from the database + + ``object_class`` + The type of object to delete + + ``id`` + The unique reference for the class instance to be deleted + """ + if id != 0: + object = self.get_object(object_class, id) + try: + self.session.delete(object) + self.session.commit() + return True + except InvalidRequestError: + self.session.rollback() + log.exception(u'Failed to delete object') + return False + else: + return True + + def delete_all_objects(self, object_class): + """ + Delete all object records + + ``object_class`` + The type of object to delete + """ + try: + self.session.query(object_class).delete(synchronize_session=False) + self.session.commit() + return True + except InvalidRequestError: + self.session.rollback() + log.exception(u'Failed to delete all %s records', + object_class.__name__) + return False diff --git a/openlp/plugins/alerts/alertsplugin.py b/openlp/plugins/alerts/alertsplugin.py index 7474a0564..3c14e23b1 100644 --- a/openlp/plugins/alerts/alertsplugin.py +++ b/openlp/plugins/alerts/alertsplugin.py @@ -28,7 +28,9 @@ import logging from PyQt4 import QtCore, QtGui from openlp.core.lib import Plugin, build_icon, PluginStatus, translate -from openlp.plugins.alerts.lib import AlertsManager, AlertsTab, DBManager +from openlp.core.lib.db import Manager +from openlp.plugins.alerts.lib import AlertsManager, AlertsTab +from openlp.plugins.alerts.lib.db import init_schema from openlp.plugins.alerts.forms import AlertForm log = logging.getLogger(__name__) @@ -41,7 +43,7 @@ class alertsPlugin(Plugin): self.weight = -3 self.icon = build_icon(u':/media/media_image.png') self.alertsmanager = AlertsManager(self) - self.manager = DBManager() + self.manager = Manager(u'alerts', init_schema) self.alertForm = AlertForm(self.manager, self) self.status = PluginStatus.Active diff --git a/openlp/plugins/alerts/forms/alertform.py b/openlp/plugins/alerts/forms/alertform.py index e8fc0d2fe..b00ba0f05 100644 --- a/openlp/plugins/alerts/forms/alertform.py +++ b/openlp/plugins/alerts/forms/alertform.py @@ -62,7 +62,7 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): def loadList(self): self.AlertListWidget.clear() - alerts = self.manager.get_all_alerts() + alerts = self.manager.get_all_objects(AlertItem, AlertItem.text) for alert in alerts: item_name = QtGui.QListWidgetItem(alert.text) item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(alert.id)) @@ -82,7 +82,7 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): item = self.AlertListWidget.currentItem() if item: item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] - self.parent.manager.delete_alert(item_id) + self.manager.delete_object(AlertItem, item_id) row = self.AlertListWidget.row(item) self.AlertListWidget.takeItem(row) self.AlertTextEdit.setText(u'') @@ -98,15 +98,15 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): else: alert = AlertItem() alert.text = unicode(self.AlertTextEdit.text()) - self.manager.save_alert(alert) + self.manager.insert_object(alert) self.AlertTextEdit.setText(u'') self.loadList() def onSaveClick(self): if self.item_id: - alert = self.manager.get_alert(self.item_id) + alert = self.manager.get_object(AlertItem, self.item_id) alert.text = unicode(self.AlertTextEdit.text()) - self.manager.save_alert(alert) + self.manager.insert_object(alert) self.item_id = None self.loadList() else: @@ -148,4 +148,3 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): self.parent.alertsmanager.displayAlert(text) return True return False - diff --git a/openlp/plugins/alerts/lib/__init__.py b/openlp/plugins/alerts/lib/__init__.py index 81a2641f6..2c22e5375 100644 --- a/openlp/plugins/alerts/lib/__init__.py +++ b/openlp/plugins/alerts/lib/__init__.py @@ -25,4 +25,3 @@ from alertsmanager import AlertsManager from alertstab import AlertsTab -from manager import DBManager diff --git a/openlp/plugins/alerts/lib/manager.py b/openlp/plugins/alerts/lib/manager.py deleted file mode 100644 index 7b5cf2da0..000000000 --- a/openlp/plugins/alerts/lib/manager.py +++ /dev/null @@ -1,112 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin # -# Thompson, Jon Tibble, Carsten Tinggaard # -# --------------------------------------------------------------------------- # -# This program is free software; you can redistribute it and/or modify it # -# under the terms of the GNU General Public License as published by the Free # -# Software Foundation; version 2 of the License. # -# # -# This program is distributed in the hope that it will be useful, but WITHOUT # -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # -# more details. # -# # -# You should have received a copy of the GNU General Public License along # -# with this program; if not, write to the Free Software Foundation, Inc., 59 # -# Temple Place, Suite 330, Boston, MA 02111-1307 USA # -############################################################################### - -import logging - -from PyQt4 import QtCore -from sqlalchemy.exceptions import InvalidRequestError - -from openlp.core.utils import AppLocation -from openlp.plugins.alerts.lib.db import init_schema, AlertItem - -log = logging.getLogger(__name__) - -class DBManager(object): - """ - The Song Manager provides a central location for all database code. This - class takes care of connecting to the database and running all the queries. - """ - log.info(u'Alerts DB loaded') - - def __init__(self): - """ - Creates the connection to the database, and creates the tables if they - don't exist. - """ - log.debug(u'Alerts Initialising') - settings = QtCore.QSettings() - settings.beginGroup(u'alerts') - self.db_url = u'' - db_type = unicode( - settings.value(u'db type', QtCore.QVariant(u'sqlite')).toString()) - if db_type == u'sqlite': - self.db_url = u'sqlite:///%s/alerts.sqlite' % \ - AppLocation.get_section_data_path(u'alerts') - else: - self.db_url = u'%s://%s:%s@%s/%s' % (db_type, - unicode(settings.value(u'db username').toString()), - unicode(settings.value(u'db password').toString()), - unicode(settings.value(u'db hostname').toString()), - unicode(settings.value(u'db database').toString())) - settings.endGroup() - self.session = init_schema(self.db_url) - log.debug(u'Alerts Initialised') - - def get_all_alerts(self): - """ - Returns the details of a Alert Show - """ - return self.session.query(AlertItem).order_by(AlertItem.text).all() - - def save_alert(self, alert_item): - """ - Saves a Alert show to the database - """ - log.debug(u'Alert added') - try: - self.session.add(alert_item) - self.session.commit() - log.debug(u'Alert saved') - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'Alert save failed') - return False - - def get_alert(self, id=None): - """ - Returns the details of a Alert - """ - if id is None: - return AlertItem() - else: - return self.session.query(AlertItem).get(id) - - def delete_alert(self, id): - """ - Delete a Alert show - """ - if id != 0: - alert_item = self.get_alert(id) - try: - self.session.delete(alert_item) - self.session.commit() - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'Alert deleton failed') - return False - else: - return True diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py index 1ae8796f5..ecee8975d 100644 --- a/openlp/plugins/songs/forms/editsongform.py +++ b/openlp/plugins/songs/forms/editsongform.py @@ -30,7 +30,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import SongXMLBuilder, SongXMLParser, Receiver, translate from openlp.plugins.songs.forms import EditVerseForm -from openlp.plugins.songs.lib.db import Song +from openlp.plugins.songs.lib.db import Book, Song, Author, Topic from editsongdialog import Ui_EditSongDialog log = logging.getLogger(__name__) @@ -125,7 +125,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.TopicRemoveButton.setEnabled(False) def loadAuthors(self): - authors = self.songmanager.get_authors() + authors = self.songmanager.get_all_objects(Author, Author.display_name) authorsCompleter = QtGui.QCompleter( [author.display_name for author in authors], self.AuthorsSelectionComboItem) @@ -139,7 +139,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): row, QtCore.QVariant(author.id)) def loadTopics(self): - topics = self.songmanager.get_topics() + topics = self.songmanager.get_all_objects(Topic, Topic.name) topicsCompleter = QtGui.QCompleter( [topic.name for topic in topics], self.SongTopicCombo) topicsCompleter.setCaseSensitivity(QtCore.Qt.CaseInsensitive) @@ -151,7 +151,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.SongTopicCombo.setItemData(row, QtCore.QVariant(topic.id)) def loadBooks(self): - books = self.songmanager.get_books() + books = self.songmanager.get_all_objects(Book, Book.name) booksCompleter = QtGui.QCompleter( [book.name for book in books], self.SongbookCombo) booksCompleter.setCaseSensitivity(QtCore.Qt.CaseInsensitive) @@ -201,11 +201,12 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.loadAuthors() self.loadTopics() self.loadBooks() - self.song = self.songmanager.get_song(id) + self.song = self.songmanager.get_object(Song, id) self.TitleEditItem.setText(self.song.title) title = self.song.search_title.split(u'@') if self.song.song_book_id != 0: - book_name = self.songmanager.get_book(self.song.song_book_id) + book_name = self.songmanager.get_object(Book, + self.song.song_book_id) id = self.SongbookCombo.findText( unicode(book_name.name), QtCore.Qt.MatchExactly) if id == -1: @@ -301,7 +302,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): item = int(self.AuthorsSelectionComboItem.currentIndex()) if item > -1: item_id = (self.AuthorsSelectionComboItem.itemData(item)).toInt()[0] - author = self.songmanager.get_author(item_id) + author = self.songmanager.get_object(Author, item_id) self.song.authors.append(author) author_item = QtGui.QListWidgetItem(unicode(author.display_name)) author_item.setData(QtCore.Qt.UserRole, QtCore.QVariant(author.id)) @@ -315,7 +316,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.AuthorRemoveButton.setEnabled(False) item = self.AuthorsListView.currentItem() author_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] - author = self.songmanager.get_author(author_id) + author = self.songmanager.get_object(Author, author_id) self.song.authors.remove(author) row = self.AuthorsListView.row(item) self.AuthorsListView.takeItem(row) @@ -324,7 +325,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): item = int(self.SongTopicCombo.currentIndex()) if item > -1: item_id = (self.SongTopicCombo.itemData(item)).toInt()[0] - topic = self.songmanager.get_topic(item_id) + topic = self.songmanager.get_object(Topic, item_id) self.song.topics.append(topic) topic_item = QtGui.QListWidgetItem(unicode(topic.name)) topic_item.setData(QtCore.Qt.UserRole, QtCore.QVariant(topic.id)) @@ -337,7 +338,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.TopicRemoveButton.setEnabled(False) item = self.TopicsListView.currentItem() topic_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] - topic = self.songmanager.get_topic(topic_id) + topic = self.songmanager.get_object(Topic, topic_id) self.song.topics.remove(topic) row = self.TopicsListView.row(item) self.TopicsListView.takeItem(row) @@ -550,7 +551,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.song.ccli_number = unicode(self.CCLNumberEdit.text()) self.processLyrics() self.processTitle() - self.songmanager.save_song(self.song) + self.songmanager.insert_object(self.song) return True def processLyrics(self): @@ -596,4 +597,3 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.song.search_title = self.song.search_title.replace(u'{', u'') self.song.search_title = self.song.search_title.replace(u'}', u'') self.song.search_title = self.song.search_title.replace(u'?', u'') - diff --git a/openlp/plugins/songs/forms/songmaintenanceform.py b/openlp/plugins/songs/forms/songmaintenanceform.py index d6ac7bf04..c0134f100 100644 --- a/openlp/plugins/songs/forms/songmaintenanceform.py +++ b/openlp/plugins/songs/forms/songmaintenanceform.py @@ -26,11 +26,9 @@ from PyQt4 import QtGui, QtCore from openlp.core.lib import translate +from openlp.plugins.songs.forms import AuthorsForm, TopicsForm, SongBookForm from openlp.plugins.songs.lib.db import Author, Book, Topic from songmaintenancedialog import Ui_SongMaintenanceDialog -from authorsform import AuthorsForm -from topicsform import TopicsForm -from songbookform import SongBookForm class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): """ @@ -81,17 +79,17 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): else: return -1 - def _deleteItem(self, list_widget, get_func, del_func, reset_func, - dlg_title, del_text, err_text, sel_text): + def _deleteItem(self, item_class, list_widget, reset_func, dlg_title, + del_text, err_text, sel_text): item_id = self._getCurrentItemId(list_widget) if item_id != -1: - item = get_func(item_id) + item = self.songmanager.get_object(item_class, item_id) if item and len(item.songs) == 0: if QtGui.QMessageBox.warning(self, dlg_title, del_text, QtGui.QMessageBox.StandardButtons( QtGui.QMessageBox.No | QtGui.QMessageBox.Yes) ) == QtGui.QMessageBox.Yes: - del_func(item.id) + self.songmanager.delete_object(item_class, item.id) reset_func() else: QtGui.QMessageBox.critical(self, dlg_title, err_text) @@ -100,7 +98,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): def resetAuthors(self): self.AuthorsListWidget.clear() - authors = self.songmanager.get_authors() + authors = self.songmanager.get_all_objects(Author, Author.display_name) for author in authors: if author.display_name: author_name = QtGui.QListWidgetItem(author.display_name) @@ -112,7 +110,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): def resetTopics(self): self.TopicsListWidget.clear() - topics = self.songmanager.get_topics() + topics = self.songmanager.get_all_objects(Topic, Topic.name) for topic in topics: topic_name = QtGui.QListWidgetItem(topic.name) topic_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(topic.id)) @@ -120,7 +118,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): def resetBooks(self): self.BooksListWidget.clear() - books = self.songmanager.get_books() + books = self.songmanager.get_all_objects(Book, Book.name) for book in books: book_name = QtGui.QListWidgetItem(book.name) book_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(book.id)) @@ -133,7 +131,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): first_name=unicode(self.authorform.FirstNameEdit.text()), last_name=unicode(self.authorform.LastNameEdit.text()), display_name=unicode(self.authorform.DisplayEdit.text())) - if self.songmanager.save_author(author): + if self.songmanager.insert_object(author): self.resetAuthors() else: QtGui.QMessageBox.critical( @@ -145,7 +143,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): def onTopicAddButtonClick(self): if self.topicform.exec_(): topic = Topic.populate(name=unicode(self.topicform.NameEdit.text())) - if self.songmanager.save_topic(topic): + if self.songmanager.insert_object(topic): self.resetTopics() else: QtGui.QMessageBox.critical( @@ -159,7 +157,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): book = Book.populate( name=unicode(self.bookform.NameEdit.text()), publisher=unicode(self.bookform.PublisherEdit.text())) - if self.songmanager.save_book(book): + if self.songmanager.insert_object(book): self.resetBooks() else: QtGui.QMessageBox.critical( @@ -171,7 +169,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): def onAuthorEditButtonClick(self): author_id = self._getCurrentItemId(self.AuthorsListWidget) if author_id != -1: - author = self.songmanager.get_author(author_id) + author = self.songmanager.get_object(Author, author_id) self.authorform.setAutoDisplayName(False) self.authorform.FirstNameEdit.setText(author.first_name) self.authorform.LastNameEdit.setText(author.last_name) @@ -182,7 +180,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): author.last_name = unicode(self.authorform.LastNameEdit.text()) author.display_name = unicode( self.authorform.DisplayEdit.text()) - if self.songmanager.save_author(author): + if self.songmanager.insert_object(author): self.resetAuthors() else: QtGui.QMessageBox.critical( @@ -194,11 +192,11 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): def onTopicEditButtonClick(self): topic_id = self._getCurrentItemId(self.TopicsListWidget) if topic_id != -1: - topic = self.songmanager.get_topic(topic_id) + topic = self.songmanager.get_object(Topic, topic_id) self.topicform.NameEdit.setText(topic.name) if self.topicform.exec_(False): topic.name = unicode(self.topicform.NameEdit.text()) - if self.songmanager.save_topic(topic): + if self.songmanager.insert_object(topic): self.resetTopics() else: QtGui.QMessageBox.critical( @@ -210,13 +208,13 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): def onBookEditButtonClick(self): book_id = self._getCurrentItemId(self.BooksListWidget) if book_id != -1: - book = self.songmanager.get_book(book_id) + book = self.songmanager.get_object(Book, book_id) self.bookform.NameEdit.setText(book.name) self.bookform.PublisherEdit.setText(book.publisher) if self.bookform.exec_(False): book.name = unicode(self.bookform.NameEdit.text()) book.publisher = unicode(self.bookform.PublisherEdit.text()) - if self.songmanager.save_book(book): + if self.songmanager.insert_object(book): self.resetBooks() else: QtGui.QMessageBox.critical( @@ -229,9 +227,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): """ Delete the author if the author is not attached to any songs """ - self._deleteItem( - self.AuthorsListWidget, self.songmanager.get_author, - self.songmanager.delete_author, self.resetAuthors, + self._deleteItem(Author, self.AuthorsListWidget, self.resetAuthors, translate(u'SongsPlugin.SongMaintenanceForm', u'Delete Author'), translate(u'SongsPlugin.SongMaintenanceForm', u'Are you sure you want to delete the selected author?'), @@ -245,9 +241,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): """ Delete the Book is the Book is not attached to any songs """ - self._deleteItem( - self.TopicsListWidget, self.songmanager.get_topic, - self.songmanager.delete_topic, self.resetTopics, + self._deleteItem(Topic, self.TopicsListWidget, self.resetTopics, translate(u'SongsPlugin.SongMaintenanceForm', u'Delete Topic'), translate(u'SongsPlugin.SongMaintenanceForm', u'Are you sure you want to delete the selected topic?'), @@ -261,9 +255,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): """ Delete the Book is the Book is not attached to any songs """ - self._deleteItem( - self.BooksListWidget, self.songmanager.get_book, - self.songmanager.delete_book, self.resetBooks, + self._deleteItem(Book, self.BooksListWidget, self.resetBooks, translate(u'SongsPlugin.SongMaintenanceForm', u'Delete Book'), translate(u'SongsPlugin.SongMaintenanceForm', u'Are you sure you want to delete the selected book?'), diff --git a/openlp/plugins/songs/lib/manager.py b/openlp/plugins/songs/lib/manager.py index 8e0a79ef7..6cd9a90ad 100644 --- a/openlp/plugins/songs/lib/manager.py +++ b/openlp/plugins/songs/lib/manager.py @@ -25,10 +25,7 @@ import logging -from PyQt4 import QtCore -from sqlalchemy.exceptions import InvalidRequestError - -from openlp.core.utils import AppLocation +from openlp.core.lib.db import Manager from openlp.plugins.songs.lib.db import init_schema, Song, Author, Topic, Book #from openlp.plugins.songs.lib import OpenLyricsSong, OpenSongSong, CCLISong, \ # CSVSong @@ -79,7 +76,7 @@ class SongFormat(object): ] -class SongManager(object): +class SongManager(Manager): """ The Song Manager provides a central location for all database code. This class takes care of connecting to the database and running all the queries. @@ -92,34 +89,9 @@ class SongManager(object): don't exist. """ log.debug(u'Song Initialising') - settings = QtCore.QSettings() - settings.beginGroup(u'songs') - self.db_url = u'' - db_type = unicode(settings.value(u'songs/db type', - QtCore.QVariant(u'sqlite')).toString()) - if db_type == u'sqlite': - self.db_url = u'sqlite:///%s/songs.sqlite' % \ - AppLocation.get_section_data_path(u'songs') - else: - self.db_url = u'%s://%s:%s@%s/%s' % (db_type, - unicode(settings.value( - u'db username', QtCore.QVariant(u'')).toString()), - unicode(settings.value( - u'db password', QtCore.QVariant(u'')).toString()), - unicode(settings.value( - u'db hostname', QtCore.QVariant(u'')).toString()), - unicode(settings.value( - u'db database', QtCore.QVariant(u'')).toString())) - self.session = init_schema(self.db_url) - settings.endGroup() + Manager.__init__(self, u'songs', init_schema) log.debug(u'Song Initialised') - def get_songs(self): - """ - Returns the details of a song - """ - return self.session.query(Song).order_by(Song.title).all() - def search_song_title(self, keywords): """ Searches the song title for keywords. @@ -143,174 +115,23 @@ class SongManager(object): return self.session.query(Author).filter(Author.display_name.like( u'%' + keywords + u'%')).order_by(Author.display_name.asc()).all() - def get_song(self, id=None): - """ - Returns the details of a song - """ - if id is None: - return Song() - else: - return self.session.query(Song).get(id) - - def save_song(self, song): - """ - Saves a song to the database - """ - try: - self.session.add(song) - self.session.commit() - return True - except InvalidRequestError: - log.exception(u'Could not save song to song database') - self.session.rollback() - return False - - def delete_song(self, songid): - song = self.get_song(songid) - try: - self.session.delete(song) - self.session.commit() - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'Could not delete song from song database') - return False - - def get_authors(self): - """ - Returns a list of all the authors - """ - return self.session.query(Author).order_by(Author.display_name).all() - - def get_author(self, id): - """ - Details of the Author - """ - return self.session.query(Author).get(id) - def get_author_by_name(self, name): """ Get author by display name """ return self.session.query(Author).filter_by(display_name=name).first() - def save_author(self, author): - """ - Save the Author and refresh the cache - """ - try: - self.session.add(author) - self.session.commit() - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'Could not save author to song database') - return False - - def delete_author(self, authorid): - """ - Delete the author - """ - author = self.get_author(authorid) - try: - self.session.delete(author) - self.session.commit() - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'Could not delete author from song database') - return False - - def get_topics(self): - """ - Returns a list of all the topics - """ - return self.session.query(Topic).order_by(Topic.name).all() - - def get_topic(self, id): - """ - Details of the Topic - """ - return self.session.query(Topic).get(id) - def get_topic_by_name(self, name): """ Get topic by name """ return self.session.query(Topic).filter_by(name=name).first() - def save_topic(self, topic): - """ - Save the Topic - """ - try: - self.session.add(topic) - self.session.commit() - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'Could not save topic to song database') - return False - - def delete_topic(self, topicid): - """ - Delete the topic - """ - topic = self.get_topic(topicid) - try: - self.session.delete(topic) - self.session.commit() - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'Could not delete topic from song database') - return False - - def get_books(self): - """ - Returns a list of all the Books - """ - return self.session.query(Book).order_by(Book.name).all() - - def get_book(self, id): - """ - Details of the Books - """ - return self.session.query(Book).get(id) - def get_book_by_name(self, name): """ Get book by name """ return self.session.query(Book).filter_by(name=name).first() - def save_book(self, book): - """ - Save the Book - """ - try: - self.session.add(book) - self.session.commit() - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'Could not save book to song database') - return False - - def delete_book(self, bookid): - """ - Delete the Book - """ - book = self.get_book(bookid) - try: - self.session.delete(book) - self.session.commit() - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'Could not delete book from song database') - return False - def get_songs_for_theme(self, theme): return self.session.query(Song).filter(Song.theme_name == theme).all() - diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index 67133f9c6..f0a4afc88 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -31,6 +31,7 @@ from openlp.core.lib import MediaManagerItem, SongXMLParser, \ BaseListWithDnD, Receiver, ItemCapabilities, translate from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \ ImportWizardForm +from openlp.plugins.songs.lib.db import Song log = logging.getLogger(__name__) @@ -267,7 +268,7 @@ class SongMediaItem(MediaManagerItem): type of display is required. """ fields = songid.split(u':') - valid = self.parent.manager.get_song(fields[1]) + valid = self.parent.manager.get_object(Song, fields[1]) if valid: self.remoteSong = fields[1] self.remoteTriggered = fields[0] @@ -301,7 +302,7 @@ class SongMediaItem(MediaManagerItem): return for item in items: item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] - self.parent.manager.delete_song(item_id) + self.parent.manager.delete_object(Song, item_id) self.onSearchTextButtonClick() def generateSlideData(self, service_item, item=None): @@ -322,7 +323,7 @@ class SongMediaItem(MediaManagerItem): service_item.add_capability(ItemCapabilities.AllowsEdit) service_item.add_capability(ItemCapabilities.AllowsPreview) service_item.add_capability(ItemCapabilities.AllowsLoop) - song = self.parent.manager.get_song(item_id) + song = self.parent.manager.get_object(Song, item_id) service_item.theme = song.theme_name service_item.editId = item_id if song.lyrics.startswith(u' Date: Tue, 15 Jun 2010 01:44:06 +0100 Subject: [PATCH 04/11] RFC PT3: Bibles --- openlp/core/lib/db.py | 42 ++++- .../plugins/bibles/forms/importwizardform.py | 12 +- openlp/plugins/bibles/lib/csvbible.py | 6 +- openlp/plugins/bibles/lib/db.py | 168 ++++++++++-------- openlp/plugins/bibles/lib/http.py | 3 +- openlp/plugins/bibles/lib/manager.py | 16 +- openlp/plugins/bibles/lib/models.py | 94 ---------- openlp/plugins/bibles/lib/opensong.py | 2 +- openlp/plugins/bibles/lib/osis.py | 4 +- openlp/plugins/songs/lib/songimport.py | 2 +- 10 files changed, 151 insertions(+), 198 deletions(-) delete mode 100644 openlp/plugins/bibles/lib/models.py diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index 323b48e39..7517998f0 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -74,13 +74,20 @@ class Manager(object): """ Provide generic object persistence management """ - def __init__(self, plugin_name, init_schema): + def __init__(self, plugin_name, init_schema, db_file_name=None): """ Runs the initialisation process that includes creating the connection to the database and the tables if they don't exist. ``plugin_name`` The name to setup paths and settings section names + + ``init_schema`` + The init_schema function for this database + + ``db_file_name`` + The file name to use for this database. Defaults to None resulting + in the plugin_name being used. """ settings = QtCore.QSettings() settings.beginGroup(plugin_name) @@ -88,8 +95,13 @@ class Manager(object): db_type = unicode( settings.value(u'db type', QtCore.QVariant(u'sqlite')).toString()) if db_type == u'sqlite': - self.db_url = u'sqlite:///%s/%s.sqlite' % ( - AppLocation.get_section_data_path(plugin_name), plugin_name) + if db_file_name: + self.db_url = u'sqlite:///%s/%s' % ( + AppLocation.get_section_data_path(plugin_name), + db_file_name) + else: + self.db_url = u'sqlite:///%s/%s.sqlite' % ( + AppLocation.get_section_data_path(plugin_name), plugin_name) else: self.db_url = u'%s://%s:%s@%s/%s' % (db_type, unicode(settings.value(u'db username').toString()), @@ -99,6 +111,30 @@ class Manager(object): settings.endGroup() self.session = init_schema(self.db_url) + def delete_database(self, plugin_name, db_file_name=None): + """ + Remove a database file from the system. + + ``plugin_name`` + The name of the plugin to remove the database for + + ``db_file_name`` + The database file name. Defaults to None resulting in the + plugin_name being used. + """ + db_file_path = None + if db_file_name: + db_file_path = os.path.join( + AppLocation.get_section_data_path(plugin_name), db_file_name) + else: + db_file_path = os.path.join( + AppLocation.get_section_data_path(plugin_name), plugin_name) + try: + os.remove(db_file_path) + return True + except OSError: + return False + def insert_object(self, object_instance): """ Save an object to the database diff --git a/openlp/plugins/bibles/forms/importwizardform.py b/openlp/plugins/bibles/forms/importwizardform.py index b1eafcd61..023391615 100644 --- a/openlp/plugins/bibles/forms/importwizardform.py +++ b/openlp/plugins/bibles/forms/importwizardform.py @@ -224,7 +224,7 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): Show the file open dialog for the OSIS file. """ self.getFileName( - translate(u'BiblesPlugin.ImportWizardForm', u'Open OSIS File'), + translate(u'BiblesPlugin.ImportWizardForm', u'Open OSIS File'), self.OSISLocationEdit) def onBooksFileButtonClicked(self): @@ -239,10 +239,8 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): """ Show the file open dialog for the verses CSV file. """ - self.getFileName( - translate(u'BiblesPlugin.ImportWizardForm', - u'Open Verses CSV File'), - self.CsvVerseLocationEdit) + self.getFileName(translate(u'BiblesPlugin.ImportWizardForm', + u'Open Verses CSV File'), self.CsvVerseLocationEdit) def onOpenSongBrowseButtonClicked(self): """ @@ -450,11 +448,11 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): self.ImportProgressLabel.setText( translate(u'BiblesPlugin.ImportWizardForm', u'Your Bible import failed.')) - importer.delete() + importer.delete_database(self.bibleplugin.settingsSection, + importer.file) def postImport(self): self.ImportProgressBar.setValue(self.ImportProgressBar.maximum()) self.finishButton.setVisible(True) self.cancelButton.setVisible(False) Receiver.send_message(u'openlp_process_events') - diff --git a/openlp/plugins/bibles/lib/csvbible.py b/openlp/plugins/bibles/lib/csvbible.py index 3cfe9dea5..9a504f48f 100644 --- a/openlp/plugins/bibles/lib/csvbible.py +++ b/openlp/plugins/bibles/lib/csvbible.py @@ -97,11 +97,11 @@ class CSVBible(BibleDB): book_ptr = book.name self.wizard.incrementProgressBar( u'Importing %s %s' % (book.name, line[1])) - self.commit() + self.session.commit() self.create_verse(book.id, line[1], line[2], unicode(line[3], details['encoding'])) Receiver.send_message(u'openlp_process_events') - self.commit() + self.session.commit() except IOError: log.exception(u'Loading verses from file failed') success = False @@ -113,5 +113,3 @@ class CSVBible(BibleDB): return False else: return success - - diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py index 97983e72c..7733261db 100644 --- a/openlp/plugins/bibles/lib/db.py +++ b/openlp/plugins/bibles/lib/db.py @@ -23,19 +23,98 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -import os import logging import chardet import re -from sqlalchemy import or_ from PyQt4 import QtCore +from sqlalchemy import Column, ForeignKey, or_, Table, types +from sqlalchemy.orm import class_mapper, mapper, relation +from sqlalchemy.orm.exc import UnmappedClassError -from openlp.plugins.bibles.lib.models import * +from openlp.core.lib.db import BaseModel, init_db, Manager log = logging.getLogger(__name__) -class BibleDB(QtCore.QObject): +class BibleMeta(BaseModel): + """ + Bible Meta Data + """ + pass + +class Testament(BaseModel): + """ + Bible Testaments + """ + pass + +class Book(BaseModel): + """ + Song model + """ + pass + +class Verse(BaseModel): + """ + Topic model + """ + pass + +def init_schema(url): + """ + Setup a bible database connection and initialise the database schema + + ``url`` + The database to setup + """ + session, metadata = init_db(url) + + meta_table = Table(u'metadata', metadata, + Column(u'key', types.Unicode(255), primary_key=True, index=True), + Column(u'value', types.Unicode(255)), + ) + testament_table = Table(u'testament', metadata, + Column(u'id', types.Integer, primary_key=True), + Column(u'name', types.Unicode(50)), + ) + book_table = Table(u'book', metadata, + Column(u'id', types.Integer, primary_key=True), + Column(u'testament_id', types.Integer, ForeignKey(u'testament.id')), + Column(u'name', types.Unicode(50), index=True), + Column(u'abbreviation', types.Unicode(5), index=True), + ) + verse_table = Table(u'verse', metadata, + Column(u'id', types.Integer, primary_key=True, index=True), + Column(u'book_id', types.Integer, ForeignKey(u'book.id'), index=True), + Column(u'chapter', types.Integer, index=True), + Column(u'verse', types.Integer, index=True), + Column(u'text', types.UnicodeText, index=True), + ) + + try: + class_mapper(BibleMeta) + except UnmappedClassError: + mapper(BibleMeta, meta_table) + try: + class_mapper(Testament) + except UnmappedClassError: + mapper(Testament, testament_table, + properties={'books': relation(Book, backref='testament')}) + try: + class_mapper(Book) + except UnmappedClassError: + mapper(Book, book_table, + properties={'verses': relation(Verse, backref='book')}) + try: + class_mapper(Verse) + except UnmappedClassError: + mapper(Verse, verse_table) + + metadata.create_all(checkfirst=True) + return session + + +class BibleDB(QtCore.QObject, Manager): """ 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 @@ -72,24 +151,7 @@ class BibleDB(QtCore.QObject): self.file = self.clean_filename(self.name) if u'file' in kwargs: self.file = kwargs[u'file'] - self.db_file = os.path.join(kwargs[u'path'], self.file) - log.debug(u'Load bible %s on path %s', self.file, self.db_file) - settings = QtCore.QSettings() - settings.beginGroup(u'bibles') - db_type = unicode( - settings.value(u'db type', QtCore.QVariant(u'sqlite')).toString()) - db_url = u'' - if db_type == u'sqlite': - db_url = u'sqlite:///' + self.db_file - else: - db_url = u'%s://%s:%s@%s/%s' % (db_type, - unicode(settings.value(u'db username').toString()), - unicode(settings.value(u'db password').toString()), - unicode(settings.value(u'db hostname').toString()), - unicode(settings.value(u'db database').toString())) - settings.endGroup() - self.session = init_models(db_url) - metadata.create_all(checkfirst=True) + Manager.__init__(self, u'bibles', init_schema, self.file) if u'file' in kwargs: self.get_name() @@ -104,7 +166,7 @@ class BibleDB(QtCore.QObject): """ Returns the version name of the Bible. """ - version_name = self.get_meta(u'Version') + version_name = self.get_object(BibleMeta, u'Version') if version_name: self.name = version_name.value else: @@ -124,16 +186,6 @@ class BibleDB(QtCore.QObject): old_filename = re.sub(r'[^\w]+', u'_', old_filename).strip(u'_') return old_filename + u'.sqlite' - def delete(self): - """ - Remove the Bible database file. Used when a Bible import fails. - """ - try: - os.remove(self.db_file) - return True - except OSError: - return False - def register(self, wizard): """ This method basically just initialialises the database. It is called @@ -148,33 +200,15 @@ class BibleDB(QtCore.QObject): self.create_tables() return self.name - def commit(self): - """ - Perform a database commit. - """ - log.debug('Committing...') - self.session.commit() - def create_tables(self): """ Create some initial metadata. """ log.debug(u'createTables') self.create_meta(u'dbversion', u'2') - self.create_testament(u'Old Testament') - self.create_testament(u'New Testament') - self.create_testament(u'Apocrypha') - - def create_testament(self, testament): - """ - Add a testament to the database. - - ``testament`` - The testament name. - """ - log.debug(u'BibleDB.create_testament("%s")', testament) - self.session.add(Testament.populate(name=testament)) - self.commit() + self.insert_object(Testament.populate(name=u'Old Testament')) + self.insert_object(Testament.populate(name=u'New Testament')) + self.insert_object(Testament.populate(name=u'Apocrypha')) def create_book(self, name, abbrev, testament=1): """ @@ -192,8 +226,7 @@ class BibleDB(QtCore.QObject): log.debug(u'create_book %s,%s', name, abbrev) book = Book.populate(name=name, abbreviation=abbrev, testament_id=testament) - self.session.add(book) - self.commit() + self.insert_object(book) return book def create_chapter(self, book_id, chapter, textlist): @@ -220,7 +253,7 @@ class BibleDB(QtCore.QObject): text = verse_text ) self.session.add(verse) - self.commit() + self.session.commit() def create_verse(self, book_id, chapter, verse, text): """ @@ -252,12 +285,7 @@ class BibleDB(QtCore.QObject): def create_meta(self, key, value): log.debug(u'save_meta %s/%s', key, value) - self.session.add(BibleMeta.populate(key=key, value=value)) - self.commit() - - def get_books(self): - log.debug(u'BibleDB.get_books()') - return self.session.query(Book).order_by(Book.id).all() + self.insert_object(BibleMeta.populate(key=key, value=value)) def get_book(self, book): log.debug(u'BibleDb.get_book("%s")', book) @@ -362,19 +390,6 @@ class BibleDB(QtCore.QObject): else: return count - def get_meta(self, key): - log.debug(u'get meta %s', key) - return self.session.query(BibleMeta).get(key) - - def delete_meta(self, metakey): - biblemeta = self.get_meta(metakey) - try: - self.session.delete(biblemeta) - self.commit() - return True - except: - return False - def dump_bible(self): log.debug(u'.........Dumping Bible Database') log.debug('...............................Books ') @@ -383,4 +398,3 @@ class BibleDB(QtCore.QObject): 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 d3d6ca5f6..0b613b4b6 100644 --- a/openlp/plugins/bibles/lib/http.py +++ b/openlp/plugins/bibles/lib/http.py @@ -35,8 +35,7 @@ from openlp.core.lib import Receiver from openlp.core.utils import AppLocation from openlp.plugins.bibles.lib.common import BibleCommon, SearchResults, \ unescape -from openlp.plugins.bibles.lib.db import BibleDB -from openlp.plugins.bibles.lib.models import Book +from openlp.plugins.bibles.lib.db import BibleDB, Book log = logging.getLogger(__name__) diff --git a/openlp/plugins/bibles/lib/manager.py b/openlp/plugins/bibles/lib/manager.py index 7ef18a604..39f3c255b 100644 --- a/openlp/plugins/bibles/lib/manager.py +++ b/openlp/plugins/bibles/lib/manager.py @@ -29,12 +29,12 @@ from PyQt4 import QtCore from openlp.core.lib import SettingsManager from openlp.core.utils import AppLocation +from openlp.plugins.bibles.lib.db import BibleDB, Book, BibleMeta from common import parse_reference from opensong import OpenSongBible from osis import OSISBible from csvbible import CSVBible -from db import BibleDB from http import HTTPBible log = logging.getLogger(__name__) @@ -137,11 +137,13 @@ class BibleManager(object): log.debug(u'Bible Name: "%s"', name) self.db_cache[name] = bible # look to see if lazy load bible exists and get create getter. - source = self.db_cache[name].get_meta(u'download source') + source = self.db_cache[name].get_object(BibleMeta, + u'download source') if source: - download_name = \ - self.db_cache[name].get_meta(u'download name').value - meta_proxy = self.db_cache[name].get_meta(u'proxy url') + download_name = self.db_cache[name].get_object(BibleMeta, + u'download name').value + meta_proxy = self.db_cache[name].get_object(BibleMeta, + u'proxy url') web_bible = HTTPBible(self.parent, path=self.path, file=filename, download_source=source.value, download_name=download_name) @@ -196,7 +198,7 @@ class BibleManager(object): u'name': book.name, u'chapters': self.db_cache[bible].get_chapter_count(book.name) } - for book in self.db_cache[bible].get_books() + for book in self.db_cache[bible].get_all_objects(Book, Book.id) ] def get_chapter_count(self, bible, book): @@ -249,7 +251,7 @@ class BibleManager(object): Returns the meta data for a given key """ log.debug(u'get_meta %s,%s', bible, key) - return self.db_cache[bible].get_meta(key) + return self.db_cache[bible].get_object(BibleMeta, key) def exists(self, name): """ diff --git a/openlp/plugins/bibles/lib/models.py b/openlp/plugins/bibles/lib/models.py deleted file mode 100644 index 2cd52fb0b..000000000 --- a/openlp/plugins/bibles/lib/models.py +++ /dev/null @@ -1,94 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, 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 # -############################################################################### - -from sqlalchemy import Column, Table, MetaData, ForeignKey, types, \ - create_engine -from sqlalchemy.orm import mapper, relation, sessionmaker, scoped_session - -from openlp.core.lib.db import BaseModel - - -class BibleMeta(BaseModel): - """ - Bible Meta Data - """ - pass - - -class Testament(BaseModel): - """ - Bible Testaments - """ - pass - - -class Book(BaseModel): - """ - Song model - """ - pass - - -class Verse(BaseModel): - """ - Topic model - """ - pass - -def init_models(db_url): - engine = create_engine(db_url) - metadata.bind = engine - session = scoped_session(sessionmaker(autoflush=True, autocommit=False, - bind=engine)) - return session - -metadata = MetaData() -meta_table = Table(u'metadata', metadata, - Column(u'key', types.Unicode(255), primary_key=True, index=True), - Column(u'value', types.Unicode(255)), -) -testament_table = Table(u'testament', metadata, - Column(u'id', types.Integer, primary_key=True), - Column(u'name', types.Unicode(50)), -) -book_table = Table(u'book', metadata, - Column(u'id', types.Integer, primary_key=True), - Column(u'testament_id', types.Integer, ForeignKey(u'testament.id')), - Column(u'name', types.Unicode(50), index=True), - Column(u'abbreviation', types.Unicode(5), index=True), -) -verse_table = Table(u'verse', metadata, - Column(u'id', types.Integer, primary_key=True, index=True), - Column(u'book_id', types.Integer, ForeignKey(u'book.id'), index=True), - Column(u'chapter', types.Integer, index=True), - Column(u'verse', types.Integer, index=True), - Column(u'text', types.UnicodeText, index=True), -) -mapper(BibleMeta, meta_table) -mapper(Testament, testament_table, - properties={'books': relation(Book, backref='testament')}) -mapper(Book, book_table, - properties={'verses': relation(Verse, backref='book')}) -mapper(Verse, verse_table) diff --git a/openlp/plugins/bibles/lib/opensong.py b/openlp/plugins/bibles/lib/opensong.py index b2df50257..dfdc542ef 100644 --- a/openlp/plugins/bibles/lib/opensong.py +++ b/openlp/plugins/bibles/lib/opensong.py @@ -90,7 +90,7 @@ class OpenSongBible(BibleDB): QtCore.QString('%s %s %s' % ( translate(u'BiblesPlugin.Opensong', u'Importing'), \ db_book.name, chapter.attrib[u'n']))) - self.commit() + self.session.commit() except IOError: log.exception(u'Loading bible from OpenSong file failed') success = False diff --git a/openlp/plugins/bibles/lib/osis.py b/openlp/plugins/bibles/lib/osis.py index b4a2a2aa1..2f30cf63c 100644 --- a/openlp/plugins/bibles/lib/osis.py +++ b/openlp/plugins/bibles/lib/osis.py @@ -136,7 +136,7 @@ class OSISBible(BibleDB): self.wizard.ImportProgressBar.setMaximum(260) if last_chapter != chapter: if last_chapter != 0: - self.commit() + self.session.commit() self.wizard.incrementProgressBar( u'Importing %s %s...' % \ (self.books[match.group(1)][0], chapter)) @@ -162,7 +162,7 @@ class OSISBible(BibleDB): verse_text = self.spaces_regex.sub(u' ', verse_text) self.create_verse(db_book.id, chapter, verse, verse_text) Receiver.send_message(u'openlp_process_events') - self.commit() + self.session.commit() self.wizard.incrementProgressBar(u'Finishing import...') if match_count == 0: success = False diff --git a/openlp/plugins/songs/lib/songimport.py b/openlp/plugins/songs/lib/songimport.py index 2d6a4cd21..36a9b9953 100644 --- a/openlp/plugins/songs/lib/songimport.py +++ b/openlp/plugins/songs/lib/songimport.py @@ -28,8 +28,8 @@ import string from PyQt4 import QtGui from openlp.core.lib import SongXMLBuilder +from openlp.plugins.songs.lib import VerseType from openlp.plugins.songs.lib.db import Song, Author, Topic, Book -from openlp.plugins.songs.forms import VerseType class SongImport(object): """ From e92b0173480852c2e3e374eafdf8c2b8de1cd525 Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Tue, 15 Jun 2010 03:08:22 +0100 Subject: [PATCH 05/11] RFC PT4: The other DB plugins --- openlp/core/lib/db.py | 14 ++- openlp/plugins/custom/customplugin.py | 9 +- openlp/plugins/custom/forms/editcustomform.py | 6 +- openlp/plugins/custom/lib/__init__.py | 1 - .../plugins/custom/lib/{classes.py => db.py} | 31 ++++- openlp/plugins/custom/lib/manager.py | 117 ------------------ openlp/plugins/custom/lib/mediaitem.py | 10 +- openlp/plugins/custom/lib/meta.py | 38 ------ openlp/plugins/custom/lib/models.py | 39 ------ openlp/plugins/custom/lib/tables.py | 37 ------ openlp/plugins/songs/lib/manager.py | 3 - openlp/plugins/songs/songsplugin.py | 4 +- .../songusage/forms/songusagedetailform.py | 17 ++- openlp/plugins/songusage/lib/classes.py | 32 ----- .../songusage/lib/{models.py => db.py} | 44 +++++-- openlp/plugins/songusage/lib/manager.py | 100 +++------------ openlp/plugins/songusage/lib/meta.py | 38 ------ openlp/plugins/songusage/lib/tables.py | 39 ------ openlp/plugins/songusage/songusageplugin.py | 6 +- 19 files changed, 120 insertions(+), 465 deletions(-) rename openlp/plugins/custom/lib/{classes.py => db.py} (68%) delete mode 100644 openlp/plugins/custom/lib/manager.py delete mode 100644 openlp/plugins/custom/lib/meta.py delete mode 100644 openlp/plugins/custom/lib/models.py delete mode 100644 openlp/plugins/custom/lib/tables.py delete mode 100644 openlp/plugins/songusage/lib/classes.py rename openlp/plugins/songusage/lib/{models.py => db.py} (63%) delete mode 100644 openlp/plugins/songusage/lib/meta.py delete mode 100644 openlp/plugins/songusage/lib/tables.py diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index 7517998f0..4c7b1ca23 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -171,7 +171,7 @@ class Manager(object): Returns all the objects from the database ``object_class`` - The type of object to return + The type of objects to return ``order_by_ref`` Any parameters to order the returned objects by. Defaults to None. @@ -180,6 +180,18 @@ class Manager(object): return self.session.query(object_class).order_by(order_by_ref).all() return self.session.query(object_class).all() + def get_all_objects_filtered(self, object_class, filter_string): + """ + Returns a selection of objects from the database + + ``object_class`` + The type of objects to return + + ``filter_string`` + The filter governing selection of objects to return + """ + return self.session.query(object_class).filter(filter_string).all() + def delete_object(self, object_class, id): """ Delete an object from the database diff --git a/openlp/plugins/custom/customplugin.py b/openlp/plugins/custom/customplugin.py index 9ae208a28..92bfdadfc 100644 --- a/openlp/plugins/custom/customplugin.py +++ b/openlp/plugins/custom/customplugin.py @@ -27,7 +27,9 @@ import logging from forms import EditCustomForm from openlp.core.lib import Plugin, build_icon, PluginStatus, translate -from openlp.plugins.custom.lib import CustomManager, CustomMediaItem, CustomTab +from openlp.core.lib.db import Manager +from openlp.plugins.custom.lib import CustomMediaItem, CustomTab +from openlp.plugins.custom.lib.db import CustomSlide, init_schema log = logging.getLogger(__name__) @@ -45,7 +47,7 @@ class CustomPlugin(Plugin): def __init__(self, plugin_helpers): Plugin.__init__(self, u'Custom', u'1.9.1', plugin_helpers) self.weight = -5 - self.custommanager = CustomManager() + self.custommanager = Manager(u'custom', init_schema) self.edit_custom_form = EditCustomForm(self.custommanager) self.icon = build_icon(u':/media/media_custom.png') self.status = PluginStatus.Active @@ -75,6 +77,7 @@ class CustomPlugin(Plugin): return about_text def can_delete_theme(self, theme): - if len(self.custommanager.get_customs_for_theme(theme)) == 0: + filter = u'theme_name=%s' % theme + if not self.custommanager.get_all_objects_filtered(CustomSlide, filter): return True return False diff --git a/openlp/plugins/custom/forms/editcustomform.py b/openlp/plugins/custom/forms/editcustomform.py index 4e8b5957a..2b8a5bc03 100644 --- a/openlp/plugins/custom/forms/editcustomform.py +++ b/openlp/plugins/custom/forms/editcustomform.py @@ -29,7 +29,7 @@ from PyQt4 import QtCore, QtGui from editcustomdialog import Ui_customEditDialog from openlp.core.lib import SongXMLBuilder, SongXMLParser, Receiver, translate -from openlp.plugins.custom.lib.models import CustomSlide +from openlp.plugins.custom.lib.db import CustomSlide log = logging.getLogger(__name__) @@ -117,7 +117,7 @@ class EditCustomForm(QtGui.QDialog, Ui_customEditDialog): self.customSlide = CustomSlide() self.initialise() if id != 0: - self.customSlide = self.custommanager.get_custom(id) + self.customSlide = self.custommanager.get_object(CustomSlide, id) self.TitleEdit.setText(self.customSlide.title) self.CreditEdit.setText(self.customSlide.credits) songXML = SongXMLParser(self.customSlide.text) @@ -167,7 +167,7 @@ class EditCustomForm(QtGui.QDialog, Ui_customEditDialog): u'utf-8') self.customSlide.theme_name = unicode(self.ThemeComboBox.currentText(), u'utf-8') - self.custommanager.save_slide(self.customSlide) + self.custommanager.insert_object(self.customSlide) return True def onUpButtonPressed(self): diff --git a/openlp/plugins/custom/lib/__init__.py b/openlp/plugins/custom/lib/__init__.py index e62669ad3..0d9de3173 100644 --- a/openlp/plugins/custom/lib/__init__.py +++ b/openlp/plugins/custom/lib/__init__.py @@ -23,6 +23,5 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from manager import CustomManager from mediaitem import CustomMediaItem from customtab import CustomTab diff --git a/openlp/plugins/custom/lib/classes.py b/openlp/plugins/custom/lib/db.py similarity index 68% rename from openlp/plugins/custom/lib/classes.py rename to openlp/plugins/custom/lib/db.py index 6d8c623d1..277f3a7e8 100644 --- a/openlp/plugins/custom/lib/classes.py +++ b/openlp/plugins/custom/lib/db.py @@ -22,11 +22,40 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### +""" +The :mod:`db` module provides the database and schema that is the backend for +the Custom plugin +""" -from openlp.core.lib.db import BaseModel +from sqlalchemy import Column, Table, types +from sqlalchemy.orm import mapper + +from openlp.core.lib.db import BaseModel, init_db class CustomSlide(BaseModel): """ Custom Slide model """ pass + +def init_schema(url): + """ + Setup the custom database connection and initialise the database schema + + ``url`` + The database to setup + """ + session, metadata = init_db(url) + + custom_slide_table = Table(u'custom_slide', metadata, + Column(u'id', types.Integer(), primary_key=True), + Column(u'title', types.Unicode(255), nullable=False), + Column(u'text', types.UnicodeText, nullable=False), + Column(u'credits', types.UnicodeText), + Column(u'theme_name', types.Unicode(128)) + ) + + mapper(CustomSlide, custom_slide_table) + + metadata.create_all(checkfirst=True) + return session diff --git a/openlp/plugins/custom/lib/manager.py b/openlp/plugins/custom/lib/manager.py deleted file mode 100644 index 793cd8699..000000000 --- a/openlp/plugins/custom/lib/manager.py +++ /dev/null @@ -1,117 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin # -# Thompson, Jon Tibble, Carsten Tinggaard # -# --------------------------------------------------------------------------- # -# This program is free software; you can redistribute it and/or modify it # -# under the terms of the GNU General Public License as published by the Free # -# Software Foundation; version 2 of the License. # -# # -# This program is distributed in the hope that it will be useful, but WITHOUT # -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # -# more details. # -# # -# You should have received a copy of the GNU General Public License along # -# with this program; if not, write to the Free Software Foundation, Inc., 59 # -# Temple Place, Suite 330, Boston, MA 02111-1307 USA # -############################################################################### - -import logging - -from PyQt4 import QtCore -from sqlalchemy.exceptions import InvalidRequestError - -from openlp.core.utils import AppLocation -from openlp.plugins.custom.lib.models import init_models, metadata, CustomSlide - -log = logging.getLogger(__name__) - -class CustomManager(object): - """ - The Song Manager provides a central location for all database code. This - class takes care of connecting to the database and running all the queries. - """ - log.info(u'Custom manager loaded') - - def __init__(self): - """ - Creates the connection to the database, and creates the tables if they - don't exist. - """ - log.debug(u'Custom Initialising') - settings = QtCore.QSettings() - settings.beginGroup(u'custom') - self.db_url = u'' - db_type = unicode( - settings.value(u'db type', QtCore.QVariant(u'sqlite')).toString()) - if db_type == u'sqlite': - self.db_url = u'sqlite:///%s/custom.sqlite' % \ - AppLocation.get_section_data_path(u'custom') - else: - self.db_url = u'%s://%s:%s@%s/%s' % (db_type, - unicode(settings.value(u'db username').toString()), - unicode(settings.value(u'db password').toString()), - unicode(settings.value(u'db hostname').toString()), - unicode(settings.value(u'db database').toString())) - self.session = init_models(self.db_url) - metadata.create_all(checkfirst=True) - settings.endGroup() - log.debug(u'Custom Initialised') - - def get_all_slides(self): - """ - Returns the details of a Custom Slide Show - """ - return self.session.query(CustomSlide).order_by(CustomSlide.title).all() - - def save_slide(self, customslide): - """ - Saves a Custom slide show to the database - """ - log.debug(u'Custom Slide added') - try: - self.session.add(customslide) - self.session.commit() - log.debug(u'Custom Slide saved') - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'Custom Slide save failed') - return False - - def get_custom(self, id=None): - """ - Returns the details of a Custom Slide - """ - if id is None: - return CustomSlide() - else: - return self.session.query(CustomSlide).get(id) - - def delete_custom(self, id): - """ - Delete a Custom slide show - """ - if id != 0: - customslide = self.get_custom(id) - try: - self.session.delete(customslide) - self.session.commit() - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'Custom Slide deleton failed') - return False - else: - return True - - def get_customs_for_theme(self, theme): - return self.session.query( - CustomSlide).filter(CustomSlide.theme_name == theme).all() diff --git a/openlp/plugins/custom/lib/mediaitem.py b/openlp/plugins/custom/lib/mediaitem.py index 581334410..18f681489 100644 --- a/openlp/plugins/custom/lib/mediaitem.py +++ b/openlp/plugins/custom/lib/mediaitem.py @@ -29,6 +29,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import MediaManagerItem, SongXMLParser, BaseListWithDnD, \ Receiver, ItemCapabilities, translate +from openlp.plugins.custom.lib.db import CustomSlide log = logging.getLogger(__name__) @@ -72,7 +73,8 @@ class CustomMediaItem(MediaManagerItem): MediaManagerItem.requiredIcons(self) def initialise(self): - self.loadCustomListView(self.parent.custommanager.get_all_slides()) + self.loadCustomListView(self.parent.custommanager.get_all_objects( + CustomSlide, CustomSlide.title)) #Called to redisplay the song list screen edith from a search #or from the exit of the Song edit dialog. If remote editing is active #Trigger it and clean up so it will not update again. @@ -106,7 +108,7 @@ class CustomMediaItem(MediaManagerItem): type of display is required. """ fields = customid.split(u':') - valid = self.parent.custommanager.get_custom(fields[1]) + valid = self.parent.custommanager.get_object(CustomSlide, fields[1]) if valid: self.remoteCustom = fields[1] self.remoteTriggered = fields[0] @@ -126,7 +128,7 @@ class CustomMediaItem(MediaManagerItem): item = self.ListView.currentItem() if item: item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] - self.parent.custommanager.delete_custom(item_id) + self.parent.custommanager.delete_object(CustomSlide, item_id) row = self.ListView.row(item) self.ListView.takeItem(row) @@ -148,7 +150,7 @@ class CustomMediaItem(MediaManagerItem): service_item.add_capability(ItemCapabilities.AllowsEdit) service_item.add_capability(ItemCapabilities.AllowsPreview) service_item.add_capability(ItemCapabilities.AllowsLoop) - customSlide = self.parent.custommanager.get_custom(item_id) + customSlide = self.parent.custommanager.get_object(CustomSlide, item_id) title = customSlide.title credit = customSlide.credits service_item.editId = item_id diff --git a/openlp/plugins/custom/lib/meta.py b/openlp/plugins/custom/lib/meta.py deleted file mode 100644 index affa31969..000000000 --- a/openlp/plugins/custom/lib/meta.py +++ /dev/null @@ -1,38 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, 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 # -############################################################################### - -from sqlalchemy import MetaData - -__all__ = ['session', 'metadata', 'engine'] - -# SQLAlchemy database engine. Updated by model.init_model() -engine = None - -# SQLAlchemy session manager. Updated by model.init_model() -session = None - -# Global metadata. If you have multiple databases with overlapping table -# names, you'll need a metadata for each database -metadata = MetaData() diff --git a/openlp/plugins/custom/lib/models.py b/openlp/plugins/custom/lib/models.py deleted file mode 100644 index 3bd2886bd..000000000 --- a/openlp/plugins/custom/lib/models.py +++ /dev/null @@ -1,39 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, 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 # -############################################################################### - -from sqlalchemy import create_engine -from sqlalchemy.orm import scoped_session, sessionmaker, mapper - -from openlp.plugins.custom.lib.meta import metadata -from openlp.plugins.custom.lib.tables import * -from openlp.plugins.custom.lib.classes import * - -def init_models(url): - engine = create_engine(url) - metadata.bind = engine - session = scoped_session(sessionmaker(autoflush=True, autocommit=False, - bind=engine)) - mapper(CustomSlide, custom_slide_table) - return session diff --git a/openlp/plugins/custom/lib/tables.py b/openlp/plugins/custom/lib/tables.py deleted file mode 100644 index bb86d9d6d..000000000 --- a/openlp/plugins/custom/lib/tables.py +++ /dev/null @@ -1,37 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, 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 # -############################################################################### - -from sqlalchemy import Column, Table, types - -from openlp.plugins.custom.lib.meta import metadata - -# Definition of the "custom slide" table -custom_slide_table = Table(u'custom_slide', metadata, - Column(u'id', types.Integer(), primary_key=True), - Column(u'title', types.Unicode(255), nullable=False), - Column(u'text', types.UnicodeText, nullable=False), - Column(u'credits', types.UnicodeText), - Column(u'theme_name', types.Unicode(128)) -) diff --git a/openlp/plugins/songs/lib/manager.py b/openlp/plugins/songs/lib/manager.py index 6cd9a90ad..f2edf6e75 100644 --- a/openlp/plugins/songs/lib/manager.py +++ b/openlp/plugins/songs/lib/manager.py @@ -132,6 +132,3 @@ class SongManager(Manager): Get book by name """ return self.session.query(Book).filter_by(name=name).first() - - def get_songs_for_theme(self, theme): - return self.session.query(Song).filter(Song.theme_name == theme).all() diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py index b7ddd473e..45ee4fe46 100644 --- a/openlp/plugins/songs/songsplugin.py +++ b/openlp/plugins/songs/songsplugin.py @@ -187,7 +187,7 @@ class SongsPlugin(Plugin): return about_text def can_delete_theme(self, theme): - if len(self.manager.get_songs_for_theme(theme)) == 0: + filter = u'theme_name=%s' % theme + if not self.manager.get_all_objects_filtered(Song, filter): return True return False - diff --git a/openlp/plugins/songusage/forms/songusagedetailform.py b/openlp/plugins/songusage/forms/songusagedetailform.py index fb1d1c73d..bb19bc2e6 100644 --- a/openlp/plugins/songusage/forms/songusagedetailform.py +++ b/openlp/plugins/songusage/forms/songusagedetailform.py @@ -71,20 +71,19 @@ class SongUsageDetailForm(QtGui.QDialog, Ui_SongUsageDetailDialog): def accept(self): log.debug(u'Detailed report generated') - filename = u'usage_detail_%s_%s.txt' % \ - (self.FromDate.selectedDate().toString(u'ddMMyyyy'), - self.ToDate.selectedDate().toString(u'ddMMyyyy')) - usage = self.parent.songusagemanager.get_all_songusage(\ - self.FromDate.selectedDate(), \ - self.ToDate.selectedDate()) + filename = u'usage_detail_%s_%s.txt' % ( + self.FromDate.selectedDate().toString(u'ddMMyyyy'), + self.ToDate.selectedDate().toString(u'ddMMyyyy')) + usage = self.parent.songusagemanager.get_songusage_for_period( + self.FromDate.selectedDate(), self.ToDate.selectedDate()) outname = os.path.join(unicode(self.FileLineEdit.text()), filename) file = None try: file = open(outname, u'w') for instance in usage: - record = u'\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"\n' % \ - (instance.usagedate,instance.usagetime, instance.title, - instance.copyright, instance.ccl_number , instance.authors) + record = u'\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"\n' % ( + instance.usagedate, instance.usagetime, instance.title, + instance.copyright, instance.ccl_number, instance.authors) file.write(record) except IOError: log.exception(u'Failed to write out song usage records') diff --git a/openlp/plugins/songusage/lib/classes.py b/openlp/plugins/songusage/lib/classes.py deleted file mode 100644 index 885d87faf..000000000 --- a/openlp/plugins/songusage/lib/classes.py +++ /dev/null @@ -1,32 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, 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 # -############################################################################### - -from openlp.core.lib.db import BaseModel - -class SongUsageItem(BaseModel): - """ - Audit model - """ - pass diff --git a/openlp/plugins/songusage/lib/models.py b/openlp/plugins/songusage/lib/db.py similarity index 63% rename from openlp/plugins/songusage/lib/models.py rename to openlp/plugins/songusage/lib/db.py index a7babbaed..ffb720a58 100644 --- a/openlp/plugins/songusage/lib/models.py +++ b/openlp/plugins/songusage/lib/db.py @@ -22,18 +22,42 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### +""" +The :mod:`db` module provides the database and schema that is the backend for +the SongUsage plugin +""" -from sqlalchemy import create_engine -from sqlalchemy.orm import scoped_session, sessionmaker, mapper +from sqlalchemy import Column, Table, types +from sqlalchemy.orm import mapper -from openlp.plugins.songusage.lib.meta import metadata -from openlp.plugins.songusage.lib.tables import * -from openlp.plugins.songusage.lib.classes import * +from openlp.core.lib.db import BaseModel, init_db + +class SongUsageItem(BaseModel): + """ + SongUsageItem model + """ + pass + +def init_schema(url): + """ + Setup the songusage database connection and initialise the database schema + + ``url`` + The database to setup + """ + session, metadata = init_db(url) + + songusage_table = Table(u'songusage_data', metadata, + Column(u'id', types.Integer(), primary_key=True), + Column(u'usagedate', types.Date, index=True, nullable=False), + Column(u'usagetime', types.Time, index=True, nullable=False), + Column(u'title', types.Unicode(255), nullable=False), + Column(u'authors', types.Unicode(255), nullable=False), + Column(u'copyright', types.Unicode(255)), + Column(u'ccl_number', types.Unicode(65)) + ) -def init_models(url): - engine = create_engine(url) - metadata.bind = engine - session = scoped_session(sessionmaker(autoflush=True, autocommit=False, - bind=engine)) mapper(SongUsageItem, songusage_table) + + metadata.create_all(checkfirst=True) return session diff --git a/openlp/plugins/songusage/lib/manager.py b/openlp/plugins/songusage/lib/manager.py index b830fdafd..363f06fb8 100644 --- a/openlp/plugins/songusage/lib/manager.py +++ b/openlp/plugins/songusage/lib/manager.py @@ -25,16 +25,14 @@ import logging -from PyQt4 import QtCore from sqlalchemy.exceptions import InvalidRequestError -from openlp.core.utils import AppLocation -from openlp.plugins.songusage.lib.models import init_models, metadata, \ - SongUsageItem +from openlp.core.lib.db import Manager +from openlp.plugins.songusage.lib.db import init_schema, SongUsageItem log = logging.getLogger(__name__) -class SongUsageManager(object): +class SongUsageManager(Manager): """ The Song Manager provides a central location for all database code. This class takes care of connecting to the database and running all the queries. @@ -47,98 +45,31 @@ class SongUsageManager(object): don't exist. """ log.debug(u'SongUsage Initialising') - settings = QtCore.QSettings() - settings.beginGroup(u'songusage') - self.db_url = u'' - db_type = unicode( - settings.value(u'db type', QtCore.QVariant(u'sqlite')).toString()) - if db_type == u'sqlite': - self.db_url = u'sqlite:///%s/songusage.sqlite' % \ - AppLocation.get_section_data_path(u'songusage') - else: - self.db_url = u'%s://%s:%s@%s/%s' % (db_type, - unicode(settings.value(u'db username', - QtCore.QVariant(u'')).toString()), - unicode(settings.value(u'db password', - QtCore.QVariant(u'')).toString()), - unicode(settings.value(u'db hostname', - QtCore.QVariant(u'')).toString()), - unicode(settings.value(u'db database', - QtCore.QVariant(u'')).toString())) - self.session = init_models(self.db_url) - metadata.create_all(checkfirst=True) - settings.endGroup() + Manager.__init__(self, u'songusage', init_schema) log.debug(u'SongUsage Initialised') - def get_all_songusage(self, start_date, end_date): + def get_songusage_for_period(self, start_date, end_date): """ - Returns the details of SongUsage + Returns the details of SongUsage for a designated time period + + ``start_date`` + The start of the period to return + + ``end_date`` + The end of the period to return """ return self.session.query(SongUsageItem) \ .filter(SongUsageItem.usagedate >= start_date.toPyDate()) \ .filter(SongUsageItem.usagedate < end_date.toPyDate()) \ - .order_by(SongUsageItem.usagedate, SongUsageItem.usagetime ).all() - - def insert_songusage(self, songusageitem): - """ - Saves an SongUsage to the database - """ - log.debug(u'SongUsage added') - try: - self.session.add(songusageitem) - self.session.commit() - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'SongUsage item failed to save') - return False - - def get_songusage(self, id=None): - """ - Returns the details of a SongUsage - """ - if id is None: - return SongUsageItem() - else: - return self.session.query(SongUsageItem).get(id) - - def delete_songusage(self, id): - """ - Delete a SongUsage record - """ - if id != 0: - songusageitem = self.get_songusage(id) - try: - self.session.delete(songusageitem) - self.session.commit() - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'SongUsage Item failed to delete') - return False - else: - return True - - def delete_all(self): - """ - Delete all Song Usage records - """ - try: - self.session.query(SongUsageItem).delete(synchronize_session=False) - self.session.commit() - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'Failed to delete all Song Usage items') - return False + .order_by(SongUsageItem.usagedate, SongUsageItem.usagetime).all() def delete_to_date(self, date): """ Delete SongUsage records before given date """ try: - self.session.query(SongUsageItem)\ - .filter(SongUsageItem.usagedate <= date)\ + self.session.query(SongUsageItem) \ + .filter(SongUsageItem.usagedate <= date) \ .delete(synchronize_session=False) self.session.commit() return True @@ -146,4 +77,3 @@ class SongUsageManager(object): self.session.rollback() log.exception(u'Failed to delete all Song Usage items to %s' % date) return False - diff --git a/openlp/plugins/songusage/lib/meta.py b/openlp/plugins/songusage/lib/meta.py deleted file mode 100644 index affa31969..000000000 --- a/openlp/plugins/songusage/lib/meta.py +++ /dev/null @@ -1,38 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, 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 # -############################################################################### - -from sqlalchemy import MetaData - -__all__ = ['session', 'metadata', 'engine'] - -# SQLAlchemy database engine. Updated by model.init_model() -engine = None - -# SQLAlchemy session manager. Updated by model.init_model() -session = None - -# Global metadata. If you have multiple databases with overlapping table -# names, you'll need a metadata for each database -metadata = MetaData() diff --git a/openlp/plugins/songusage/lib/tables.py b/openlp/plugins/songusage/lib/tables.py deleted file mode 100644 index 008c722b1..000000000 --- a/openlp/plugins/songusage/lib/tables.py +++ /dev/null @@ -1,39 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, 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 # -############################################################################### - -from sqlalchemy import Column, Table, types - -from openlp.plugins.songusage.lib.meta import metadata - -# Definition of the "songusage" table -songusage_table = Table(u'songusage_data', metadata, - Column(u'id', types.Integer(), primary_key=True), - Column(u'usagedate', types.Date, index=True, nullable=False), - Column(u'usagetime', types.Time, index=True, nullable=False), - Column(u'title', types.Unicode(255), nullable=False), - Column(u'authors', types.Unicode(255), nullable=False), - Column(u'copyright', types.Unicode(255)), - Column(u'ccl_number', types.Unicode(65)) -) diff --git a/openlp/plugins/songusage/songusageplugin.py b/openlp/plugins/songusage/songusageplugin.py index 6cbb08e1a..04292e069 100644 --- a/openlp/plugins/songusage/songusageplugin.py +++ b/openlp/plugins/songusage/songusageplugin.py @@ -23,16 +23,16 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from datetime import datetime import logging +from datetime import datetime from PyQt4 import QtCore, QtGui from openlp.core.lib import Plugin, Receiver, build_icon, translate from openlp.plugins.songusage.lib import SongUsageManager from openlp.plugins.songusage.forms import SongUsageDetailForm, \ SongUsageDeleteForm -from openlp.plugins.songusage.lib.models import SongUsageItem +from openlp.plugins.songusage.lib.db import SongUsageItem log = logging.getLogger(__name__) @@ -146,7 +146,7 @@ class SongUsagePlugin(Plugin): song_usage_item.authors = u'' for author in audit[1]: song_usage_item.authors += author + u' ' - self.songusagemanager.insert_songusage(song_usage_item) + self.songusagemanager.insert_object(song_usage_item) def onSongUsageDelete(self): self.SongUsagedeleteform.exec_() From 85661fe6e468f657552174785ace5d1fe5accad8 Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Tue, 15 Jun 2010 16:42:52 +0100 Subject: [PATCH 06/11] RFC: Tweaks --- openlp/core/lib/__init__.py | 29 +++++++++++- openlp/migration/migratebibles.py | 3 +- openlp/migration/migratesongs.py | 5 +-- openlp/plugins/alerts/alertsplugin.py | 3 ++ openlp/plugins/bibles/lib/db.py | 63 +++++++++++++++++---------- openlp/plugins/custom/lib/db.py | 2 +- 6 files changed, 74 insertions(+), 31 deletions(-) diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py index ffc61cdcc..5e6547906 100644 --- a/openlp/core/lib/__init__.py +++ b/openlp/core/lib/__init__.py @@ -22,7 +22,6 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### - """ The :mod:`lib` module contains most of the components and libraries that make OpenLP work. @@ -47,6 +46,10 @@ def translate(context, text, comment=None): ``text`` The text to put into the translation tables for translation. + + ``comment`` + An identifying string for when the same text is used in different roles + within the same context. """ return QtCore.QCoreApplication.translate(context, text, comment) @@ -115,6 +118,18 @@ def build_icon(icon): def context_menu_action(base, icon, text, slot): """ Utility method to help build context menus for plugins + + ``base`` + The parent menu to add this menu item to + + ``icon`` + An icon for this action + + ``text`` + The text to display for this action + + ``slot`` + The code to run when this action is triggered """ action = QtGui.QAction(text, base) if icon: @@ -125,6 +140,15 @@ def context_menu_action(base, icon, text, slot): def context_menu(base, icon, text): """ Utility method to help build context menus for plugins + + ``base`` + The parent object to add this menu to + + ``icon`` + An icon for this menu + + ``text`` + The text to display for this menu """ action = QtGui.QMenu(text, base) action.setIcon(build_icon(icon)) @@ -133,6 +157,9 @@ def context_menu(base, icon, text): def context_menu_separator(base): """ Add a separator to a context menu + + ``base`` + The menu object to add the separator to """ action = QtGui.QAction(u'', base) action.setSeparator(True) diff --git a/openlp/migration/migratebibles.py b/openlp/migration/migratebibles.py index b024343a4..411da0ce6 100644 --- a/openlp/migration/migratebibles.py +++ b/openlp/migration/migratebibles.py @@ -33,7 +33,7 @@ from sqlalchemy.orm import mapper from openlp.core.lib import SettingsManager from openlp.core.lib.db import BaseModel from openlp.core.utils import AppLocation -from openlp.plugins.bibles.lib.models import * +from openlp.plugins.bibles.lib.db import BibleMeta, Book, Testament, Verse class TBibleMeta(BaseModel): """ @@ -196,4 +196,3 @@ class MigrateBibles(object): conn.commit() conn.execute(u'vacuum;') conn.commit() - diff --git a/openlp/migration/migratesongs.py b/openlp/migration/migratesongs.py index c4cab00bc..0ede63387 100644 --- a/openlp/migration/migratesongs.py +++ b/openlp/migration/migratesongs.py @@ -34,10 +34,7 @@ from sqlalchemy.orm import scoped_session, sessionmaker, mapper, relation from openlp.core.lib import SettingsManager from openlp.core.lib.db import BaseModel from openlp.core.utils import AppLocation -from openlp.plugins.songs.lib.models import metadata, songs_table, Song, \ - Author, Topic, Book -from openlp.plugins.songs.lib.tables import * -from openlp.plugins.songs.lib.classes import * +from openlp.plugins.songs.lib.db import songs_table, Song, Author, Topic, Book def init_models(url): engine = create_engine(url) diff --git a/openlp/plugins/alerts/alertsplugin.py b/openlp/plugins/alerts/alertsplugin.py index 3c14e23b1..bd783a7cb 100644 --- a/openlp/plugins/alerts/alertsplugin.py +++ b/openlp/plugins/alerts/alertsplugin.py @@ -48,6 +48,9 @@ class alertsPlugin(Plugin): self.status = PluginStatus.Active def get_settings_tab(self): + """ + Return the settings tab for the Alerts plugin + """ self.alertsTab = AlertsTab(self) return self.alertsTab diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py index 7733261db..eee149320 100644 --- a/openlp/plugins/bibles/lib/db.py +++ b/openlp/plugins/bibles/lib/db.py @@ -197,18 +197,11 @@ class BibleDB(QtCore.QObject, Manager): The actual Qt wizard form. """ self.wizard = wizard - self.create_tables() - return self.name - - def create_tables(self): - """ - Create some initial metadata. - """ - log.debug(u'createTables') self.create_meta(u'dbversion', u'2') self.insert_object(Testament.populate(name=u'Old Testament')) self.insert_object(Testament.populate(name=u'New Testament')) self.insert_object(Testament.populate(name=u'Apocrypha')) + return self.name def create_book(self, name, abbrev, testament=1): """ @@ -284,26 +277,32 @@ class BibleDB(QtCore.QObject, Manager): return verse def create_meta(self, key, value): + """ + Utility method to save BibleMeta objects in a Bible database + + ``key`` + The key for this instance + + ``value`` + The value for this instance + """ log.debug(u'save_meta %s/%s', key, value) self.insert_object(BibleMeta.populate(key=key, value=value)) def get_book(self, book): - log.debug(u'BibleDb.get_book("%s")', book) - db_book = self.session.query(Book)\ - .filter(Book.name.like(book + u'%'))\ - .first() - if db_book is None: - db_book = self.session.query(Book)\ - .filter(Book.abbreviation.like(book + u'%'))\ - .first() - return db_book + """ + Return a book object from the database - def get_chapter(self, id, chapter): - log.debug(u'BibleDB.get_chapter("%s", %s)', id, chapter) - return self.session.query(Verse)\ - .filter_by(chapter=chapter)\ - .filter_by(book_id=id)\ - .first() + ``book`` + The name of the book to return + """ + log.debug(u'BibleDb.get_book("%s")', book) + db_book = self.session.query(Book).filter( + Book.name.like(book + u'%')).first() + if db_book is None: + db_book = self.session.query(Book).filter( + Book.abbreviation.like(book + u'%')).first() + return db_book def get_verses(self, reference_list): """ @@ -370,6 +369,12 @@ class BibleDB(QtCore.QObject, Manager): return verses def get_chapter_count(self, book): + """ + Return the number of chapters in a book + + ``book`` + The book to get the chapter count for + """ log.debug(u'BibleDB.get_chapter_count("%s")', book) count = self.session.query(Verse.chapter).join(Book)\ .filter(Book.name==book)\ @@ -380,6 +385,15 @@ class BibleDB(QtCore.QObject, Manager): return count def get_verse_count(self, book, chapter): + """ + Return the number of verses in a chapter + + ``book`` + The book containing the chapter + + ``chapter`` + The chapter to get the verse count for + """ log.debug(u'BibleDB.get_verse_count("%s", %s)', book, chapter) count = self.session.query(Verse).join(Book)\ .filter(Book.name==book)\ @@ -391,6 +405,9 @@ class BibleDB(QtCore.QObject, Manager): return count def dump_bible(self): + """ + Utility debugging method to dump the contents of a bible + """ log.debug(u'.........Dumping Bible Database') log.debug('...............................Books ') books = self.session.query(Book).all() diff --git a/openlp/plugins/custom/lib/db.py b/openlp/plugins/custom/lib/db.py index 277f3a7e8..39d935d9a 100644 --- a/openlp/plugins/custom/lib/db.py +++ b/openlp/plugins/custom/lib/db.py @@ -34,7 +34,7 @@ from openlp.core.lib.db import BaseModel, init_db class CustomSlide(BaseModel): """ - Custom Slide model + CustomSlide model """ pass From b7e3ec4441bc386ed2a93317fe966a655e4c27ee Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Tue, 15 Jun 2010 19:08:02 +0100 Subject: [PATCH 07/11] RFC: Refactor a filter method --- openlp/core/lib/db.py | 12 ++++++++++++ openlp/plugins/songs/lib/manager.py | 20 +------------------- openlp/plugins/songs/lib/songimport.py | 12 ++++++------ 3 files changed, 19 insertions(+), 25 deletions(-) diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index 4c7b1ca23..87200faee 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -166,6 +166,18 @@ class Manager(object): else: return self.session.query(object_class).get(id) + def get_object_filtered(self, object_class, filter_string): + """ + Returns an object matching specified criteria + + ``object_class`` + The type of object to return + + ``filter_string`` + The criteria to select the object by + """ + return self.session.query(object_class).filter(filter_string).first() + def get_all_objects(self, object_class, order_by_ref=None): """ Returns all the objects from the database diff --git a/openlp/plugins/songs/lib/manager.py b/openlp/plugins/songs/lib/manager.py index f2edf6e75..10ec5aa34 100644 --- a/openlp/plugins/songs/lib/manager.py +++ b/openlp/plugins/songs/lib/manager.py @@ -26,7 +26,7 @@ import logging from openlp.core.lib.db import Manager -from openlp.plugins.songs.lib.db import init_schema, Song, Author, Topic, Book +from openlp.plugins.songs.lib.db import init_schema, Song, Author #from openlp.plugins.songs.lib import OpenLyricsSong, OpenSongSong, CCLISong, \ # CSVSong @@ -114,21 +114,3 @@ class SongManager(Manager): """ return self.session.query(Author).filter(Author.display_name.like( u'%' + keywords + u'%')).order_by(Author.display_name.asc()).all() - - def get_author_by_name(self, name): - """ - Get author by display name - """ - return self.session.query(Author).filter_by(display_name=name).first() - - def get_topic_by_name(self, name): - """ - Get topic by name - """ - return self.session.query(Topic).filter_by(name=name).first() - - def get_book_by_name(self, name): - """ - Get book by name - """ - return self.session.query(Book).filter_by(name=name).first() diff --git a/openlp/plugins/songs/lib/songimport.py b/openlp/plugins/songs/lib/songimport.py index 9b47a7501..814d13d5e 100644 --- a/openlp/plugins/songs/lib/songimport.py +++ b/openlp/plugins/songs/lib/songimport.py @@ -277,7 +277,6 @@ class SongImport(object): if len(self.authors) == 0: self.authors.append(u'Author unknown') self.commit_song() - #self.print_song() def commit_song(self): """ @@ -316,7 +315,8 @@ class SongImport(object): song.theme_name = self.theme_name song.ccli_number = self.ccli_number for authortext in self.authors: - author = self.manager.get_author_by_name(authortext) + filter_string = u'display_name=%s' % authortext + author = self.manager.get_object_filtered(Author, filter_string) if author is None: author = Author() author.display_name = authortext @@ -325,7 +325,8 @@ class SongImport(object): self.manager.insert_object(author) song.authors.append(author) if self.song_book_name: - song_book = self.manager.get_book_by_name(self.song_book_name) + filter_string = u'name=%s' % self.song_book_name + song_book = self.manager.get_object_filtered(Book, filter_string) if song_book is None: song_book = Book() song_book.name = self.song_book_name @@ -333,7 +334,8 @@ class SongImport(object): self.manager.insert_object(song_book) song.song_book_id = song_book.id for topictext in self.topics: - topic = self.manager.get_topic_by_name(topictext) + filter_string = u'name=%s' % topictext + topic = self.manager.get_object_filtered(Topic, filter_string) if topic is None: topic = Topic() topic.name = topictext @@ -370,5 +372,3 @@ class SongImport(object): print u'THEME: ' + self.theme_name if self.ccli_number: print u'CCLI: ' + self.ccli_number - - From 7f88043177999e3538e610515961568a8c29e80b Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Fri, 18 Jun 2010 02:26:01 +0100 Subject: [PATCH 08/11] RFC: Cleanups --- openlp/core/lib/db.py | 72 +++++++++---------- openlp/migration/migratebibles.py | 5 +- openlp/migration/migratesongs.py | 16 +++-- .../plugins/bibles/forms/importwizardform.py | 4 +- openlp/plugins/bibles/lib/db.py | 1 + openlp/plugins/custom/customplugin.py | 6 +- openlp/plugins/custom/forms/editcustomform.py | 3 +- openlp/plugins/songs/songsplugin.py | 4 +- openlp/plugins/songusage/lib/__init__.py | 6 +- 9 files changed, 63 insertions(+), 54 deletions(-) diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index 87200faee..19cd3eadf 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -26,6 +26,7 @@ The :mod:`db` module provides the core database functionality for OpenLP """ import logging +import os from PyQt4 import QtCore from sqlalchemy import create_engine, MetaData @@ -55,11 +56,34 @@ def init_db(url, auto_flush=True, auto_commit=False): autocommit=auto_commit, bind=engine)) return session, metadata +def delete_database(plugin_name, db_file_name=None): + """ + Remove a database file from the system. + + ``plugin_name`` + The name of the plugin to remove the database for + + ``db_file_name`` + The database file name. Defaults to None resulting in the + plugin_name being used. + """ + db_file_path = None + if db_file_name: + db_file_path = os.path.join( + AppLocation.get_section_data_path(plugin_name), db_file_name) + else: + db_file_path = os.path.join( + AppLocation.get_section_data_path(plugin_name), plugin_name) + try: + os.remove(db_file_path) + return True + except OSError: + return False + class BaseModel(object): """ BaseModel provides a base object with a set of generic functions """ - @classmethod def populate(cls, **kwargs): """ @@ -111,30 +135,6 @@ class Manager(object): settings.endGroup() self.session = init_schema(self.db_url) - def delete_database(self, plugin_name, db_file_name=None): - """ - Remove a database file from the system. - - ``plugin_name`` - The name of the plugin to remove the database for - - ``db_file_name`` - The database file name. Defaults to None resulting in the - plugin_name being used. - """ - db_file_path = None - if db_file_name: - db_file_path = os.path.join( - AppLocation.get_section_data_path(plugin_name), db_file_name) - else: - db_file_path = os.path.join( - AppLocation.get_section_data_path(plugin_name), plugin_name) - try: - os.remove(db_file_path) - return True - except OSError: - return False - def insert_object(self, object_instance): """ Save an object to the database @@ -151,20 +151,20 @@ class Manager(object): log.exception(u'Object save failed') return False - def get_object(self, object_class, id=None): + def get_object(self, object_class, key=None): """ Return the details of an object ``object_class`` The type of object to return - ``id`` - The unique reference for the class instance to return + ``key`` + The unique reference or primary key for the instance to return """ - if not id: + if not key: return object_class() else: - return self.session.query(object_class).get(id) + return self.session.query(object_class).get(key) def get_object_filtered(self, object_class, filter_string): """ @@ -204,20 +204,20 @@ class Manager(object): """ return self.session.query(object_class).filter(filter_string).all() - def delete_object(self, object_class, id): + def delete_object(self, object_class, key): """ Delete an object from the database ``object_class`` The type of object to delete - ``id`` - The unique reference for the class instance to be deleted + ``key`` + The unique reference or primary key for the instance to be deleted """ - if id != 0: - object = self.get_object(object_class, id) + if key != 0: + object_instance = self.get_object(object_class, key) try: - self.session.delete(object) + self.session.delete(object_instance) self.session.commit() return True except InvalidRequestError: diff --git a/openlp/migration/migratebibles.py b/openlp/migration/migratebibles.py index 411da0ce6..37a0df933 100644 --- a/openlp/migration/migratebibles.py +++ b/openlp/migration/migratebibles.py @@ -27,6 +27,7 @@ import os import sys import sqlite3 +from sqlalchemy import Column, MetaData, Table, types from sqlalchemy.exceptions import InvalidRequestError from sqlalchemy.orm import mapper @@ -34,7 +35,9 @@ from openlp.core.lib import SettingsManager from openlp.core.lib.db import BaseModel from openlp.core.utils import AppLocation from openlp.plugins.bibles.lib.db import BibleMeta, Book, Testament, Verse - + +metadata = MetaData() + class TBibleMeta(BaseModel): """ Bible Meta Data diff --git a/openlp/migration/migratesongs.py b/openlp/migration/migratesongs.py index 0ede63387..0a6912c78 100644 --- a/openlp/migration/migratesongs.py +++ b/openlp/migration/migratesongs.py @@ -27,14 +27,16 @@ import os import sys import sqlite3 -from sqlalchemy import create_engine +from sqlalchemy import Column, create_engine, MetaData, Table, types from sqlalchemy.exceptions import InvalidRequestError from sqlalchemy.orm import scoped_session, sessionmaker, mapper, relation from openlp.core.lib import SettingsManager from openlp.core.lib.db import BaseModel from openlp.core.utils import AppLocation -from openlp.plugins.songs.lib.db import songs_table, Song, Author, Topic, Book +from openlp.plugins.songs.lib.db import Author, Book, Song, Topic + +metadata = MetaData() def init_models(url): engine = create_engine(url) @@ -57,14 +59,14 @@ def init_models(url): temp_authors_table = Table(u'authors_temp', metadata, Column(u'authorid', types.Integer, primary_key=True), - Column(u'authorname', String(40)) + Column(u'authorname', types.Unicode(40)) ) temp_songs_table = Table(u'songs_temp', metadata, Column(u'songid', types.Integer, primary_key=True), - Column(u'songtitle', String(60)), + Column(u'songtitle', types.Unicode(60)), Column(u'lyrics', types.UnicodeText), - Column(u'copyrightinfo', String(255)), + Column(u'copyrightinfo', types.Unicode(255)), Column(u'settingsid', types.Integer) ) @@ -101,8 +103,8 @@ class MigrateSongs(object): def process(self): self.display.output(u'Songs processing started') - for f in self.database_files: - self.v_1_9_0(f) + for data_file in self.database_files: + self.v_1_9_0(data_file) self.display.output(u'Songs processing finished') def v_1_9_0(self, database): diff --git a/openlp/plugins/bibles/forms/importwizardform.py b/openlp/plugins/bibles/forms/importwizardform.py index ac6c0995e..bb6398bb1 100644 --- a/openlp/plugins/bibles/forms/importwizardform.py +++ b/openlp/plugins/bibles/forms/importwizardform.py @@ -32,6 +32,7 @@ from PyQt4 import QtCore, QtGui from bibleimportwizard import Ui_BibleImportWizard from openlp.core.lib import Receiver, SettingsManager, translate +from openlp.core.lib.db import delete_database from openlp.core.utils import AppLocation from openlp.plugins.bibles.lib.manager import BibleFormat @@ -449,8 +450,7 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): self.ImportProgressLabel.setText( translate(u'BiblesPlugin.ImportWizardForm', u'Your Bible import failed.')) - importer.delete_database(self.bibleplugin.settingsSection, - importer.file) + delete_database(self.bibleplugin.settingsSection, importer.file) def postImport(self): self.ImportProgressBar.setValue(self.ImportProgressBar.maximum()) diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py index e6178a098..16c3d918d 100644 --- a/openlp/plugins/bibles/lib/db.py +++ b/openlp/plugins/bibles/lib/db.py @@ -154,6 +154,7 @@ class BibleDB(QtCore.QObject, Manager): Manager.__init__(self, u'bibles', init_schema, self.file) if u'file' in kwargs: self.get_name() + self.wizard = None def stop_import(self): """ diff --git a/openlp/plugins/custom/customplugin.py b/openlp/plugins/custom/customplugin.py index a63bbdf47..9de676bf6 100644 --- a/openlp/plugins/custom/customplugin.py +++ b/openlp/plugins/custom/customplugin.py @@ -26,6 +26,7 @@ import logging from forms import EditCustomForm + from openlp.core.lib import Plugin, build_icon, PluginStatus, translate from openlp.core.lib.db import Manager from openlp.plugins.custom.lib import CustomMediaItem, CustomTab @@ -77,7 +78,8 @@ class CustomPlugin(Plugin): return about_text def can_delete_theme(self, theme): - filter = u'theme_name=%s' % theme - if not self.custommanager.get_all_objects_filtered(CustomSlide, filter): + filter_string = u'theme_name=%s' % theme + if not self.custommanager.get_all_objects_filtered(CustomSlide, + filter_string): return True return False diff --git a/openlp/plugins/custom/forms/editcustomform.py b/openlp/plugins/custom/forms/editcustomform.py index 2b8a5bc03..01296a329 100644 --- a/openlp/plugins/custom/forms/editcustomform.py +++ b/openlp/plugins/custom/forms/editcustomform.py @@ -167,8 +167,7 @@ class EditCustomForm(QtGui.QDialog, Ui_customEditDialog): u'utf-8') self.customSlide.theme_name = unicode(self.ThemeComboBox.currentText(), u'utf-8') - self.custommanager.insert_object(self.customSlide) - return True + return self.custommanager.insert_object(self.customSlide) def onUpButtonPressed(self): selectedRow = self.VerseListView.currentRow() diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py index 2462502b9..3dd467ad6 100644 --- a/openlp/plugins/songs/songsplugin.py +++ b/openlp/plugins/songs/songsplugin.py @@ -197,7 +197,7 @@ class SongsPlugin(Plugin): return about_text def can_delete_theme(self, theme): - filter = u'theme_name=%s' % theme - if not self.manager.get_all_objects_filtered(Song, filter): + filter_string = u'theme_name=%s' % theme + if not self.manager.get_all_objects_filtered(Song, filter_string): return True return False diff --git a/openlp/plugins/songusage/lib/__init__.py b/openlp/plugins/songusage/lib/__init__.py index 50bba3ddc..ae8425317 100644 --- a/openlp/plugins/songusage/lib/__init__.py +++ b/openlp/plugins/songusage/lib/__init__.py @@ -22,5 +22,7 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### - -from manager import SongUsageManager +""" +The :mod:`lib` module contains the library functions for the songusage plugin. +""" +from openlp.plugins.songusage.lib.manager import SongUsageManager From d9d976d64bfd05d6417d31197c509e5306a70743 Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Tue, 22 Jun 2010 16:09:49 +0100 Subject: [PATCH 09/11] Cleanup and import fix --- openlp/plugins/bibles/lib/db.py | 3 ++- openlp/plugins/custom/lib/mediaitem.py | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py index d7f59307e..d2a62ec59 100644 --- a/openlp/plugins/bibles/lib/db.py +++ b/openlp/plugins/bibles/lib/db.py @@ -32,7 +32,8 @@ from sqlalchemy import Column, ForeignKey, or_, Table, types from sqlalchemy.orm import class_mapper, mapper, relation from sqlalchemy.orm.exc import UnmappedClassError -from openlp.core.lib.db import BaseModel, init_db, Manager, translate +from openlp.core.lib import translate +from openlp.core.lib.db import BaseModel, init_db, Manager log = logging.getLogger(__name__) diff --git a/openlp/plugins/custom/lib/mediaitem.py b/openlp/plugins/custom/lib/mediaitem.py index 00ba3561c..b94da35d5 100644 --- a/openlp/plugins/custom/lib/mediaitem.py +++ b/openlp/plugins/custom/lib/mediaitem.py @@ -86,10 +86,10 @@ class CustomMediaItem(MediaManagerItem): def loadCustomListView(self, list): self.ListView.clear() - for CustomSlide in list: - custom_name = QtGui.QListWidgetItem(CustomSlide.title) + for customSlide in list: + custom_name = QtGui.QListWidgetItem(customSlide.title) custom_name.setData( - QtCore.Qt.UserRole, QtCore.QVariant(CustomSlide.id)) + QtCore.Qt.UserRole, QtCore.QVariant(customSlide.id)) self.ListView.addItem(custom_name) def onNewClick(self): From ad9328a30f84c79e89946b2352a35d5aec89ae87 Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Mon, 28 Jun 2010 12:24:18 +0100 Subject: [PATCH 10/11] RFC: Fix couple of leftovers --- openlp/plugins/songs/forms/editsongform.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py index ace2d4f24..7a103931a 100644 --- a/openlp/plugins/songs/forms/editsongform.py +++ b/openlp/plugins/songs/forms/editsongform.py @@ -290,7 +290,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): QtGui.QMessageBox.Yes) == QtGui.QMessageBox.Yes: author = Author.populate(first_name=text.rsplit(u' ', 1)[0], last_name=text.rsplit(u' ', 1)[1], display_name=text) - self.songmanager.save_author(author) + self.songmanager.insert_object(author) self.song.authors.append(author) author_item = QtGui.QListWidgetItem( unicode(author.display_name)) @@ -342,7 +342,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, QtGui.QMessageBox.Yes) == QtGui.QMessageBox.Yes: topic = Topic.populate(name=text) - self.songmanager.save_topic(topic) + self.songmanager.insert_object(topic) self.song.topics.append(topic) topic_item = QtGui.QListWidgetItem(unicode(topic.name)) topic_item.setData(QtCore.Qt.UserRole, @@ -392,7 +392,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, QtGui.QMessageBox.Yes) == QtGui.QMessageBox.Yes: book = Book.populate(name=text) - self.songmanager.save_book(book) + self.songmanager.insert_object(book) self.song.book = book self.loadBooks() else: From 3be57e57e7b5e42f55cb46c587253e8354fa1265 Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Mon, 28 Jun 2010 14:38:29 +0100 Subject: [PATCH 11/11] Rename method to save_object() --- openlp/core/lib/db.py | 2 +- openlp/plugins/alerts/forms/alertform.py | 4 ++-- openlp/plugins/bibles/lib/db.py | 10 +++++----- openlp/plugins/custom/forms/editcustomform.py | 2 +- openlp/plugins/songs/forms/editsongform.py | 8 ++++---- openlp/plugins/songs/forms/songmaintenanceform.py | 12 ++++++------ openlp/plugins/songs/lib/songimport.py | 8 ++++---- openlp/plugins/songusage/songusageplugin.py | 4 ++-- 8 files changed, 25 insertions(+), 25 deletions(-) diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index 19cd3eadf..b000fe918 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -135,7 +135,7 @@ class Manager(object): settings.endGroup() self.session = init_schema(self.db_url) - def insert_object(self, object_instance): + def save_object(self, object_instance): """ Save an object to the database diff --git a/openlp/plugins/alerts/forms/alertform.py b/openlp/plugins/alerts/forms/alertform.py index 446f9698f..bf75f9ced 100644 --- a/openlp/plugins/alerts/forms/alertform.py +++ b/openlp/plugins/alerts/forms/alertform.py @@ -98,7 +98,7 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): else: alert = AlertItem() alert.text = unicode(self.AlertTextEdit.text()) - self.manager.insert_object(alert) + self.manager.save_object(alert) self.AlertTextEdit.setText(u'') self.loadList() @@ -109,7 +109,7 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): if self.item_id: alert = self.manager.get_object(AlertItem, self.item_id) alert.text = unicode(self.AlertTextEdit.text()) - self.manager.insert_object(alert) + self.manager.save_object(alert) self.item_id = None self.loadList() else: diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py index d2a62ec59..c799d71dd 100644 --- a/openlp/plugins/bibles/lib/db.py +++ b/openlp/plugins/bibles/lib/db.py @@ -200,9 +200,9 @@ class BibleDB(QtCore.QObject, Manager): """ self.wizard = wizard self.create_meta(u'dbversion', u'2') - self.insert_object(Testament.populate(name=u'Old Testament')) - self.insert_object(Testament.populate(name=u'New Testament')) - self.insert_object(Testament.populate(name=u'Apocrypha')) + self.save_object(Testament.populate(name=u'Old Testament')) + self.save_object(Testament.populate(name=u'New Testament')) + self.save_object(Testament.populate(name=u'Apocrypha')) return self.name def create_book(self, name, abbrev, testament=1): @@ -221,7 +221,7 @@ class BibleDB(QtCore.QObject, Manager): log.debug(u'create_book %s,%s', name, abbrev) book = Book.populate(name=name, abbreviation=abbrev, testament_id=testament) - self.insert_object(book) + self.save_object(book) return book def create_chapter(self, book_id, chapter, textlist): @@ -289,7 +289,7 @@ class BibleDB(QtCore.QObject, Manager): The value for this instance """ log.debug(u'save_meta %s/%s', key, value) - self.insert_object(BibleMeta.populate(key=key, value=value)) + self.save_object(BibleMeta.populate(key=key, value=value)) def get_book(self, book): """ diff --git a/openlp/plugins/custom/forms/editcustomform.py b/openlp/plugins/custom/forms/editcustomform.py index c3d25eabb..a266c44c5 100644 --- a/openlp/plugins/custom/forms/editcustomform.py +++ b/openlp/plugins/custom/forms/editcustomform.py @@ -166,7 +166,7 @@ class EditCustomForm(QtGui.QDialog, Ui_customEditDialog): u'utf-8') self.customSlide.theme_name = unicode(self.ThemeComboBox.currentText(), u'utf-8') - return self.custommanager.insert_object(self.customSlide) + return self.custommanager.save_object(self.customSlide) def onUpButtonPressed(self): selectedRow = self.VerseListView.currentRow() diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py index 7a103931a..c122c622c 100644 --- a/openlp/plugins/songs/forms/editsongform.py +++ b/openlp/plugins/songs/forms/editsongform.py @@ -290,7 +290,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): QtGui.QMessageBox.Yes) == QtGui.QMessageBox.Yes: author = Author.populate(first_name=text.rsplit(u' ', 1)[0], last_name=text.rsplit(u' ', 1)[1], display_name=text) - self.songmanager.insert_object(author) + self.songmanager.save_object(author) self.song.authors.append(author) author_item = QtGui.QListWidgetItem( unicode(author.display_name)) @@ -342,7 +342,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, QtGui.QMessageBox.Yes) == QtGui.QMessageBox.Yes: topic = Topic.populate(name=text) - self.songmanager.insert_object(topic) + self.songmanager.save_object(topic) self.song.topics.append(topic) topic_item = QtGui.QListWidgetItem(unicode(topic.name)) topic_item.setData(QtCore.Qt.UserRole, @@ -392,7 +392,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, QtGui.QMessageBox.Yes) == QtGui.QMessageBox.Yes: book = Book.populate(name=text) - self.songmanager.insert_object(book) + self.songmanager.save_object(book) self.song.book = book self.loadBooks() else: @@ -631,7 +631,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): if self._validate_song(): self.processLyrics() self.processTitle() - self.songmanager.insert_object(self.song) + self.songmanager.save_object(self.song) return True return False diff --git a/openlp/plugins/songs/forms/songmaintenanceform.py b/openlp/plugins/songs/forms/songmaintenanceform.py index ca56a5492..54a8d539f 100644 --- a/openlp/plugins/songs/forms/songmaintenanceform.py +++ b/openlp/plugins/songs/forms/songmaintenanceform.py @@ -131,7 +131,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): first_name=unicode(self.authorform.FirstNameEdit.text()), last_name=unicode(self.authorform.LastNameEdit.text()), display_name=unicode(self.authorform.DisplayEdit.text())) - if self.songmanager.insert_object(author): + if self.songmanager.save_object(author): self.resetAuthors() else: QtGui.QMessageBox.critical( @@ -143,7 +143,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): def onTopicAddButtonClick(self): if self.topicform.exec_(): topic = Topic.populate(name=unicode(self.topicform.NameEdit.text())) - if self.songmanager.insert_object(topic): + if self.songmanager.save_object(topic): self.resetTopics() else: QtGui.QMessageBox.critical( @@ -157,7 +157,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): book = Book.populate( name=unicode(self.bookform.NameEdit.text()), publisher=unicode(self.bookform.PublisherEdit.text())) - if self.songmanager.insert_object(book): + if self.songmanager.save_object(book): self.resetBooks() else: QtGui.QMessageBox.critical( @@ -187,7 +187,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): author.last_name = unicode(self.authorform.LastNameEdit.text()) author.display_name = unicode( self.authorform.DisplayEdit.text()) - if self.songmanager.insert_object(author): + if self.songmanager.save_object(author): self.resetAuthors() else: QtGui.QMessageBox.critical( @@ -203,7 +203,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): self.topicform.NameEdit.setText(topic.name) if self.topicform.exec_(False): topic.name = unicode(self.topicform.NameEdit.text()) - if self.songmanager.insert_object(topic): + if self.songmanager.save_object(topic): self.resetTopics() else: QtGui.QMessageBox.critical( @@ -221,7 +221,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): if self.bookform.exec_(False): book.name = unicode(self.bookform.NameEdit.text()) book.publisher = unicode(self.bookform.PublisherEdit.text()) - if self.songmanager.insert_object(book): + if self.songmanager.save_object(book): self.resetBooks() else: QtGui.QMessageBox.critical( diff --git a/openlp/plugins/songs/lib/songimport.py b/openlp/plugins/songs/lib/songimport.py index bc77e7f9b..08855f01a 100644 --- a/openlp/plugins/songs/lib/songimport.py +++ b/openlp/plugins/songs/lib/songimport.py @@ -309,7 +309,7 @@ class SongImport(object): author.display_name = authortext author.last_name = authortext.split(u' ')[-1] author.first_name = u' '.join(authortext.split(u' ')[:-1]) - self.manager.insert_object(author) + self.manager.save_object(author) song.authors.append(author) if self.song_book_name: filter_string = u'name=%s' % self.song_book_name @@ -318,7 +318,7 @@ class SongImport(object): song_book = Book() song_book.name = self.song_book_name song_book.publisher = self.song_book_pub - self.manager.insert_object(song_book) + self.manager.save_object(song_book) song.song_book_id = song_book.id for topictext in self.topics: filter_string = u'name=%s' % topictext @@ -326,9 +326,9 @@ class SongImport(object): if topic is None: topic = Topic() topic.name = topictext - self.manager.insert_object(topic) + self.manager.save_object(topic) song.topics.append(topictext) - self.manager.insert_object(song) + self.manager.save_object(song) def print_song(self): """ diff --git a/openlp/plugins/songusage/songusageplugin.py b/openlp/plugins/songusage/songusageplugin.py index 179ff41af..06687acfe 100644 --- a/openlp/plugins/songusage/songusageplugin.py +++ b/openlp/plugins/songusage/songusageplugin.py @@ -148,7 +148,7 @@ class SongUsagePlugin(Plugin): song_usage_item.authors = u'' for author in audit[1]: song_usage_item.authors += author + u' ' - self.songusagemanager.insert_object(song_usage_item) + self.songusagemanager.save_object(song_usage_item) def onSongUsageDelete(self): self.SongUsagedeleteform.exec_() @@ -162,4 +162,4 @@ class SongUsagePlugin(Plugin): 'SongUsage Plugin
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