diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py index 5408c611d..d6f805c98 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) @@ -200,5 +227,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/basemodel.py deleted file mode 100644 index f56336c7b..000000000 --- a/openlp/core/lib/basemodel.py +++ /dev/null @@ -1,40 +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 # -############################################################################### - -class BaseModel(object): - """ - BaseModel provides a base object with a set of generic functions - """ - - @classmethod - def populate(cls, **kwargs): - """ - Creates an instance of a class and populates it, returning the instance - """ - me = cls() - for key in kwargs: - me.__setattr__(key, kwargs[key]) - return me - diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py new file mode 100644 index 000000000..b000fe918 --- /dev/null +++ b/openlp/core/lib/db.py @@ -0,0 +1,245 @@ +# -*- 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 core database functionality for OpenLP +""" +import logging +import os + +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 + + ``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 + +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): + """ + Creates an instance of a class and populates it, returning the instance + """ + me = cls() + 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, 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) + self.db_url = u'' + db_type = unicode( + settings.value(u'db type', QtCore.QVariant(u'sqlite')).toString()) + if db_type == u'sqlite': + 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()), + 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 save_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, key=None): + """ + Return the details of an object + + ``object_class`` + The type of object to return + + ``key`` + The unique reference or primary key for the instance to return + """ + if not key: + return object_class() + else: + return self.session.query(object_class).get(key) + + 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 + + ``object_class`` + The type of objects 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 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, key): + """ + Delete an object from the database + + ``object_class`` + The type of object to delete + + ``key`` + The unique reference or primary key for the instance to be deleted + """ + if key != 0: + object_instance = self.get_object(object_class, key) + try: + self.session.delete(object_instance) + 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 4127afaac..b442edc5b 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,11 +43,14 @@ 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 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/alerts/forms/alertform.py b/openlp/plugins/alerts/forms/alertform.py index e783d718a..bf75f9ced 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 @@ -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,7 +98,7 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): else: alert = AlertItem() alert.text = unicode(self.AlertTextEdit.text()) - self.manager.save_alert(alert) + self.manager.save_object(alert) self.AlertTextEdit.setText(u'') self.loadList() @@ -107,9 +107,9 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): Save an alert """ 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.save_object(alert) self.item_id = None self.loadList() else: 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/classes.py b/openlp/plugins/alerts/lib/classes.py deleted file mode 100644 index e58f80829..000000000 --- a/openlp/plugins/alerts/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 import BaseModel - -class AlertItem(BaseModel): - """ - Custom Slide model - """ - pass diff --git a/openlp/plugins/alerts/lib/models.py b/openlp/plugins/alerts/lib/db.py similarity index 72% rename from openlp/plugins/alerts/lib/models.py rename to openlp/plugins/alerts/lib/db.py index f222345f1..5e4b1a99a 100644 --- a/openlp/plugins/alerts/lib/models.py +++ b/openlp/plugins/alerts/lib/db.py @@ -22,18 +22,36 @@ # 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 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.alerts.lib.meta import metadata -from openlp.plugins.alerts.lib.tables import * -from openlp.plugins.alerts.lib.classes import * +from openlp.core.lib.db import BaseModel, init_db + +class AlertItem(BaseModel): + """ + 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)) -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) + + metadata.create_all(checkfirst=True) return session diff --git a/openlp/plugins/alerts/lib/manager.py b/openlp/plugins/alerts/lib/manager.py deleted file mode 100644 index 088f0cbae..000000000 --- a/openlp/plugins/alerts/lib/manager.py +++ /dev/null @@ -1,114 +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.models import init_models, metadata, 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_models(self.db_url) - metadata.create_all(checkfirst=True) - 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/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/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/forms/importwizardform.py b/openlp/plugins/bibles/forms/importwizardform.py index 12b7bbaae..da225b782 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 @@ -224,7 +225,7 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): Show the file open dialog for the OSIS file. """ self.getFileName( - translate('BiblesPlugin.ImportWizardForm', 'Open OSIS File'), + translate('BiblesPlugin.ImportWizardForm', 'Open OSIS File'), self.OSISLocationEdit) def onBooksFileButtonClicked(self): @@ -239,10 +240,8 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): """ Show the file open dialog for the verses CSV file. """ - self.getFileName( - translate('BiblesPlugin.ImportWizardForm', - 'Open Verses CSV File'), - self.CsvVerseLocationEdit) + self.getFileName(translate('BiblesPlugin.ImportWizardForm', + 'Open Verses CSV File'), self.CsvVerseLocationEdit) def onOpenSongBrowseButtonClicked(self): """ @@ -451,7 +450,7 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): self.ImportProgressLabel.setText( translate('BiblesPlugin.ImportWizardForm', 'Your Bible import failed.')) - importer.delete() + delete_database(self.bibleplugin.settingsSection, importer.file) def postImport(self): self.ImportProgressBar.setValue(self.ImportProgressBar.maximum()) 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 863f7f40a..c799d71dd 100644 --- a/openlp/plugins/bibles/lib/db.py +++ b/openlp/plugins/bibles/lib/db.py @@ -23,20 +23,99 @@ # 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, QtGui +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 import translate -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 @@ -73,26 +152,10 @@ 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() + self.wizard = None def stop_import(self): """ @@ -105,7 +168,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: @@ -125,16 +188,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 @@ -146,36 +199,11 @@ class BibleDB(QtCore.QObject): The actual Qt wizard form. """ self.wizard = wizard - 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.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): """ @@ -193,8 +221,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.save_object(book) return book def create_chapter(self, book_id, chapter, textlist): @@ -221,7 +248,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,31 +279,32 @@ class BibleDB(QtCore.QObject): return verse def create_meta(self, key, value): - log.debug(u'save_meta %s/%s', key, value) - self.session.add(BibleMeta.populate(key=key, value=value)) - self.commit() + """ + Utility method to save BibleMeta objects in a Bible database - def get_books(self): - log.debug(u'BibleDB.get_books()') - return self.session.query(Book).order_by(Book.id).all() + ``key`` + The key for this instance + + ``value`` + The value for this instance + """ + log.debug(u'save_meta %s/%s', key, value) + self.save_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): """ @@ -351,6 +379,12 @@ class BibleDB(QtCore.QObject): 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)\ @@ -361,6 +395,15 @@ class BibleDB(QtCore.QObject): 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)\ @@ -371,20 +414,10 @@ 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): + """ + 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/bibles/lib/http.py b/openlp/plugins/bibles/lib/http.py index 073b03118..8bf7ac63e 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 d970bce08..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 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 d4458815f..7c7beb7f6 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('BiblesPlugin.Opensong', '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 844d31052..8437fd843 100644 --- a/openlp/plugins/bibles/lib/osis.py +++ b/openlp/plugins/bibles/lib/osis.py @@ -140,7 +140,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)) @@ -169,7 +169,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/custom/customplugin.py b/openlp/plugins/custom/customplugin.py index d4f18058e..7f64aab52 100644 --- a/openlp/plugins/custom/customplugin.py +++ b/openlp/plugins/custom/customplugin.py @@ -26,8 +26,11 @@ 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 +48,7 @@ class CustomPlugin(Plugin): def __init__(self, plugin_helpers): Plugin.__init__(self, u'Custom', u'1.9.2', 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 +78,8 @@ class CustomPlugin(Plugin): return about_text def can_delete_theme(self, theme): - if len(self.custommanager.get_customs_for_theme(theme)) == 0: + filter_string = u'theme_name=%s' % theme + if not self.custommanager.get_all_objects_filtered(CustomSlide, + filter_string): return True return False \ No newline at end of file diff --git a/openlp/plugins/custom/forms/editcustomform.py b/openlp/plugins/custom/forms/editcustomform.py index d387e7543..a266c44c5 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__) @@ -116,7 +116,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) @@ -166,8 +166,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) - return True + return self.custommanager.save_object(self.customSlide) def onUpButtonPressed(self): selectedRow = self.VerseListView.currentRow() 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/classes.py deleted file mode 100644 index dc6c5c1b8..000000000 --- a/openlp/plugins/custom/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 import BaseModel - -class CustomSlide(BaseModel): - """ - Custom Slide model - """ - pass diff --git a/openlp/plugins/custom/lib/models.py b/openlp/plugins/custom/lib/db.py similarity index 67% rename from openlp/plugins/custom/lib/models.py rename to openlp/plugins/custom/lib/db.py index 3bd2886bd..39d935d9a 100644 --- a/openlp/plugins/custom/lib/models.py +++ b/openlp/plugins/custom/lib/db.py @@ -22,18 +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 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.custom.lib.meta import metadata -from openlp.plugins.custom.lib.tables import * -from openlp.plugins.custom.lib.classes import * +from openlp.core.lib.db import BaseModel, init_db + +class CustomSlide(BaseModel): + """ + CustomSlide 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)) + ) -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) + + 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 a4fb54932..b5fb4c224 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, check_item_selected +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. @@ -84,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): @@ -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] @@ -136,7 +138,7 @@ class CustomMediaItem(MediaManagerItem): 'You must select an item to delete.')): item = self.ListView.currentItem() 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) @@ -158,7 +160,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/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/forms/authorsdialog.py b/openlp/plugins/songs/forms/authorsdialog.py index 972cab053..76e9dda55 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 5c5f019d9..c219b12ac 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 1d23a4df9..ce3291988 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 8bd839e3f..8c04bed0a 100644 --- a/openlp/plugins/songs/forms/editsongform.py +++ b/openlp/plugins/songs/forms/editsongform.py @@ -31,7 +31,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 import VerseType -from openlp.plugins.songs.lib.models import Song, Author, Topic, Book +from openlp.plugins.songs.lib.db import Book, Song, Author, Topic from editsongdialog import Ui_EditSongDialog log = logging.getLogger(__name__) @@ -118,7 +118,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) self.AuthorsSelectionComboItem.clear() self.AuthorsSelectionComboItem.addItem(u'') for author in authors: @@ -128,7 +128,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) self.SongTopicCombo.clear() self.SongTopicCombo.addItem(u'') for topic in topics: @@ -137,7 +137,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) self.SongbookCombo.clear() self.SongbookCombo.addItem(u'') for book in books: @@ -178,11 +178,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: @@ -289,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.save_object(author) self.song.authors.append(author) author_item = QtGui.QListWidgetItem( unicode(author.display_name)) @@ -302,7 +303,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): return elif item > 0: 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)) @@ -325,7 +326,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) @@ -341,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.save_object(topic) self.song.topics.append(topic) topic_item = QtGui.QListWidgetItem(unicode(topic.name)) topic_item.setData(QtCore.Qt.UserRole, @@ -353,7 +354,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): return elif item > 0: 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)) @@ -375,7 +376,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) @@ -391,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.save_object(book) self.song.book = book self.loadBooks() else: @@ -630,7 +631,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): if self._validate_song(): self.processLyrics() self.processTitle() - self.songmanager.save_song(self.song) + self.songmanager.save_object(self.song) return True return False diff --git a/openlp/plugins/songs/forms/songbookdialog.py b/openlp/plugins/songs/forms/songbookdialog.py index eb791cd69..2ab223b34 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 fd447db22..6316a8002 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 4a666c3c5..54a8d539f 100644 --- a/openlp/plugins/songs/forms/songmaintenanceform.py +++ b/openlp/plugins/songs/forms/songmaintenanceform.py @@ -25,12 +25,10 @@ from PyQt4 import QtGui, QtCore -from openlp.plugins.songs.lib.classes 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 +from openlp.plugins.songs.forms import AuthorsForm, TopicsForm, SongBookForm +from openlp.plugins.songs.lib.db import Author, Book, Topic +from songmaintenancedialog import Ui_SongMaintenanceDialog 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.save_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.save_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.save_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) # Just make sure none of the fields is None if author.first_name is None: author.first_name = u'' @@ -189,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.save_author(author): + if self.songmanager.save_object(author): self.resetAuthors() else: QtGui.QMessageBox.critical( @@ -201,11 +199,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.save_object(topic): self.resetTopics() else: QtGui.QMessageBox.critical( @@ -217,13 +215,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.save_object(book): self.resetBooks() else: QtGui.QMessageBox.critical( @@ -236,11 +234,9 @@ 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('SongsPlugin.SongMaintenanceForm', 'Delete Author'), - translate('SongsPlugin.SongMaintenanceForm', + translate('SongsPlugin.SongMaintenanceForm', 'Are you sure you want to delete the selected author?'), translate('SongsPlugin.SongMaintenanceForm', 'This author can\'t be deleted, they are currently ' @@ -252,13 +248,11 @@ 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('SongsPlugin.SongMaintenanceForm', 'Delete Topic'), - translate('SongsPlugin.SongMaintenanceForm', + translate('SongsPlugin.SongMaintenanceForm', 'Are you sure you want to delete the selected topic?'), - translate('SongsPlugin.SongMaintenanceForm', + translate('SongsPlugin.SongMaintenanceForm', 'This topic can\'t be deleted, it is currently ' 'assigned to at least one song.'), translate('SongsPlugin.SongMaintenanceForm', @@ -268,13 +262,11 @@ 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('SongsPlugin.SongMaintenanceForm', 'Delete Book'), translate('SongsPlugin.SongMaintenanceForm', 'Are you sure you want to delete the selected book?'), - translate('SongsPlugin.SongMaintenanceForm', + translate('SongsPlugin.SongMaintenanceForm', 'This book can\'t be deleted, it is currently ' 'assigned to at least one song.'), - translate('SongsPlugin.SongMaintenanceForm', 'No book selected!')) + translate('SongsPlugin.SongMaintenanceForm', u'No book selected!')) diff --git a/openlp/plugins/songs/forms/topicsdialog.py b/openlp/plugins/songs/forms/topicsdialog.py index 463367683..6ee06c9c0 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 cf93ff0f2..51d649ebe 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..655043144 --- /dev/null +++ b/openlp/plugins/songs/lib/db.py @@ -0,0 +1,151 @@ +# -*- 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) + + metadata.create_all(checkfirst=True) + return session diff --git a/openlp/plugins/songs/lib/manager.py b/openlp/plugins/songs/lib/manager.py index 4276303d5..10ec5aa34 100644 --- a/openlp/plugins/songs/lib/manager.py +++ b/openlp/plugins/songs/lib/manager.py @@ -25,12 +25,8 @@ import logging -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.core.lib.db import Manager +from openlp.plugins.songs.lib.db import init_schema, Song, Author #from openlp.plugins.songs.lib import OpenLyricsSong, OpenSongSong, CCLISong, \ # CSVSong @@ -80,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. @@ -93,35 +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'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_models(self.db_url) - metadata.create_all(checkfirst=True) - 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. @@ -144,175 +114,3 @@ 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 385e391d3..94002b6f4 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, check_item_selected from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \ ImportWizardForm +from openlp.plugins.songs.lib.db import Song log = logging.getLogger(__name__) @@ -268,7 +269,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] @@ -310,7 +311,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): @@ -331,7 +332,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'= 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 743a333d3..06687acfe 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__) @@ -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_songusage(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