This commit is contained in:
Tim Bentley 2010-06-28 20:14:31 +01:00
commit ebb368559f
54 changed files with 800 additions and 1470 deletions

View File

@ -22,7 +22,6 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59 # # with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
""" """
The :mod:`lib` module contains most of the components and libraries that make The :mod:`lib` module contains most of the components and libraries that make
OpenLP work. OpenLP work.
@ -47,6 +46,10 @@ def translate(context, text, comment=None):
``text`` ``text``
The text to put into the translation tables for translation. 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) return QtCore.QCoreApplication.translate(context, text, comment)
@ -115,6 +118,18 @@ def build_icon(icon):
def context_menu_action(base, icon, text, slot): def context_menu_action(base, icon, text, slot):
""" """
Utility method to help build context menus for plugins 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) action = QtGui.QAction(text, base)
if icon: if icon:
@ -125,6 +140,15 @@ def context_menu_action(base, icon, text, slot):
def context_menu(base, icon, text): def context_menu(base, icon, text):
""" """
Utility method to help build context menus for plugins 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 = QtGui.QMenu(text, base)
action.setIcon(build_icon(icon)) action.setIcon(build_icon(icon))
@ -133,6 +157,9 @@ def context_menu(base, icon, text):
def context_menu_separator(base): def context_menu_separator(base):
""" """
Add a separator to a context menu Add a separator to a context menu
``base``
The menu object to add the separator to
""" """
action = QtGui.QAction(u'', base) action = QtGui.QAction(u'', base)
action.setSeparator(True) action.setSeparator(True)
@ -200,5 +227,4 @@ from themexmlhandler import ThemeXML
from renderer import Renderer from renderer import Renderer
from rendermanager import RenderManager from rendermanager import RenderManager
from mediamanageritem import MediaManagerItem from mediamanageritem import MediaManagerItem
from basemodel import BaseModel
from baselistwithdnd import BaseListWithDnD from baselistwithdnd import BaseListWithDnD

View File

@ -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

245
openlp/core/lib/db.py Normal file
View File

@ -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

View File

@ -28,7 +28,9 @@ import logging
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import Plugin, build_icon, PluginStatus, translate 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 from openlp.plugins.alerts.forms import AlertForm
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -41,11 +43,14 @@ class alertsPlugin(Plugin):
self.weight = -3 self.weight = -3
self.icon = build_icon(u':/media/media_image.png') self.icon = build_icon(u':/media/media_image.png')
self.alertsmanager = AlertsManager(self) self.alertsmanager = AlertsManager(self)
self.manager = DBManager() self.manager = Manager(u'alerts', init_schema)
self.alertForm = AlertForm(self.manager, self) self.alertForm = AlertForm(self.manager, self)
self.status = PluginStatus.Active self.status = PluginStatus.Active
def get_settings_tab(self): def get_settings_tab(self):
"""
Return the settings tab for the Alerts plugin
"""
self.alertsTab = AlertsTab(self) self.alertsTab = AlertsTab(self)
return self.alertsTab return self.alertsTab

View File

@ -25,8 +25,8 @@
from PyQt4 import QtGui, QtCore from PyQt4 import QtGui, QtCore
from openlp.plugins.alerts.lib.models import AlertItem
from openlp.core.lib import translate from openlp.core.lib import translate
from openlp.plugins.alerts.lib.db import AlertItem
from alertdialog import Ui_AlertDialog from alertdialog import Ui_AlertDialog
@ -62,7 +62,7 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog):
def loadList(self): def loadList(self):
self.AlertListWidget.clear() self.AlertListWidget.clear()
alerts = self.manager.get_all_alerts() alerts = self.manager.get_all_objects(AlertItem, AlertItem.text)
for alert in alerts: for alert in alerts:
item_name = QtGui.QListWidgetItem(alert.text) item_name = QtGui.QListWidgetItem(alert.text)
item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(alert.id)) item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(alert.id))
@ -82,7 +82,7 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog):
item = self.AlertListWidget.currentItem() item = self.AlertListWidget.currentItem()
if item: if item:
item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] 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) row = self.AlertListWidget.row(item)
self.AlertListWidget.takeItem(row) self.AlertListWidget.takeItem(row)
self.AlertTextEdit.setText(u'') self.AlertTextEdit.setText(u'')
@ -98,7 +98,7 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog):
else: else:
alert = AlertItem() alert = AlertItem()
alert.text = unicode(self.AlertTextEdit.text()) alert.text = unicode(self.AlertTextEdit.text())
self.manager.save_alert(alert) self.manager.save_object(alert)
self.AlertTextEdit.setText(u'') self.AlertTextEdit.setText(u'')
self.loadList() self.loadList()
@ -107,9 +107,9 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog):
Save an alert Save an alert
""" """
if self.item_id: 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()) alert.text = unicode(self.AlertTextEdit.text())
self.manager.save_alert(alert) self.manager.save_object(alert)
self.item_id = None self.item_id = None
self.loadList() self.loadList()
else: else:

View File

@ -25,4 +25,3 @@
from alertsmanager import AlertsManager from alertsmanager import AlertsManager
from alertstab import AlertsTab from alertstab import AlertsTab
from manager import DBManager

View File

@ -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

View File

@ -22,18 +22,36 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59 # # with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # 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 import Column, Table, types
from sqlalchemy.orm import scoped_session, sessionmaker, mapper from sqlalchemy.orm import mapper
from openlp.plugins.alerts.lib.meta import metadata from openlp.core.lib.db import BaseModel, init_db
from openlp.plugins.alerts.lib.tables import *
from openlp.plugins.alerts.lib.classes import * 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) mapper(AlertItem, alerts_table)
metadata.create_all(checkfirst=True)
return session return session

View File

@ -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

View File

@ -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()

View File

@ -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))

View File

@ -32,6 +32,7 @@ from PyQt4 import QtCore, QtGui
from bibleimportwizard import Ui_BibleImportWizard from bibleimportwizard import Ui_BibleImportWizard
from openlp.core.lib import Receiver, SettingsManager, translate from openlp.core.lib import Receiver, SettingsManager, translate
from openlp.core.lib.db import delete_database
from openlp.core.utils import AppLocation from openlp.core.utils import AppLocation
from openlp.plugins.bibles.lib.manager import BibleFormat 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. Show the file open dialog for the OSIS file.
""" """
self.getFileName( self.getFileName(
translate('BiblesPlugin.ImportWizardForm', 'Open OSIS File'), translate('BiblesPlugin.ImportWizardForm', 'Open OSIS File'),
self.OSISLocationEdit) self.OSISLocationEdit)
def onBooksFileButtonClicked(self): def onBooksFileButtonClicked(self):
@ -239,10 +240,8 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
""" """
Show the file open dialog for the verses CSV file. Show the file open dialog for the verses CSV file.
""" """
self.getFileName( self.getFileName(translate('BiblesPlugin.ImportWizardForm',
translate('BiblesPlugin.ImportWizardForm', 'Open Verses CSV File'), self.CsvVerseLocationEdit)
'Open Verses CSV File'),
self.CsvVerseLocationEdit)
def onOpenSongBrowseButtonClicked(self): def onOpenSongBrowseButtonClicked(self):
""" """
@ -451,7 +450,7 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
self.ImportProgressLabel.setText( self.ImportProgressLabel.setText(
translate('BiblesPlugin.ImportWizardForm', translate('BiblesPlugin.ImportWizardForm',
'Your Bible import failed.')) 'Your Bible import failed.'))
importer.delete() delete_database(self.bibleplugin.settingsSection, importer.file)
def postImport(self): def postImport(self):
self.ImportProgressBar.setValue(self.ImportProgressBar.maximum()) self.ImportProgressBar.setValue(self.ImportProgressBar.maximum())

View File

@ -97,11 +97,11 @@ class CSVBible(BibleDB):
book_ptr = book.name book_ptr = book.name
self.wizard.incrementProgressBar( self.wizard.incrementProgressBar(
u'Importing %s %s' % (book.name, line[1])) u'Importing %s %s' % (book.name, line[1]))
self.commit() self.session.commit()
self.create_verse(book.id, line[1], line[2], self.create_verse(book.id, line[1], line[2],
unicode(line[3], details['encoding'])) unicode(line[3], details['encoding']))
Receiver.send_message(u'openlp_process_events') Receiver.send_message(u'openlp_process_events')
self.commit() self.session.commit()
except IOError: except IOError:
log.exception(u'Loading verses from file failed') log.exception(u'Loading verses from file failed')
success = False success = False
@ -113,5 +113,3 @@ class CSVBible(BibleDB):
return False return False
else: else:
return success return success

View File

@ -23,20 +23,99 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
import os
import logging import logging
import chardet import chardet
import re import re
from sqlalchemy import or_
from PyQt4 import QtCore, QtGui 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.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__) 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 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 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) self.file = self.clean_filename(self.name)
if u'file' in kwargs: if u'file' in kwargs:
self.file = kwargs[u'file'] self.file = kwargs[u'file']
self.db_file = os.path.join(kwargs[u'path'], self.file) Manager.__init__(self, u'bibles', init_schema, 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)
if u'file' in kwargs: if u'file' in kwargs:
self.get_name() self.get_name()
self.wizard = None
def stop_import(self): def stop_import(self):
""" """
@ -105,7 +168,7 @@ class BibleDB(QtCore.QObject):
""" """
Returns the version name of the Bible. 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: if version_name:
self.name = version_name.value self.name = version_name.value
else: else:
@ -125,16 +188,6 @@ class BibleDB(QtCore.QObject):
old_filename = re.sub(r'[^\w]+', u'_', old_filename).strip(u'_') old_filename = re.sub(r'[^\w]+', u'_', old_filename).strip(u'_')
return old_filename + u'.sqlite' 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): def register(self, wizard):
""" """
This method basically just initialialises the database. It is called This method basically just initialialises the database. It is called
@ -146,36 +199,11 @@ class BibleDB(QtCore.QObject):
The actual Qt wizard form. The actual Qt wizard form.
""" """
self.wizard = wizard 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_meta(u'dbversion', u'2')
self.create_testament(u'Old Testament') self.save_object(Testament.populate(name=u'Old Testament'))
self.create_testament(u'New Testament') self.save_object(Testament.populate(name=u'New Testament'))
self.create_testament(u'Apocrypha') self.save_object(Testament.populate(name=u'Apocrypha'))
return self.name
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()
def create_book(self, name, abbrev, testament=1): 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) log.debug(u'create_book %s,%s', name, abbrev)
book = Book.populate(name=name, abbreviation=abbrev, book = Book.populate(name=name, abbreviation=abbrev,
testament_id=testament) testament_id=testament)
self.session.add(book) self.save_object(book)
self.commit()
return book return book
def create_chapter(self, book_id, chapter, textlist): def create_chapter(self, book_id, chapter, textlist):
@ -221,7 +248,7 @@ class BibleDB(QtCore.QObject):
text = verse_text text = verse_text
) )
self.session.add(verse) self.session.add(verse)
self.commit() self.session.commit()
def create_verse(self, book_id, chapter, verse, text): def create_verse(self, book_id, chapter, verse, text):
""" """
@ -252,31 +279,32 @@ class BibleDB(QtCore.QObject):
return verse return verse
def create_meta(self, key, value): def create_meta(self, key, value):
log.debug(u'save_meta %s/%s', key, value) """
self.session.add(BibleMeta.populate(key=key, value=value)) Utility method to save BibleMeta objects in a Bible database
self.commit()
def get_books(self): ``key``
log.debug(u'BibleDB.get_books()') The key for this instance
return self.session.query(Book).order_by(Book.id).all()
``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): def get_book(self, book):
log.debug(u'BibleDb.get_book("%s")', book) """
db_book = self.session.query(Book)\ Return a book object from the database
.filter(Book.name.like(book + u'%'))\
.first()
if db_book is None:
db_book = self.session.query(Book)\
.filter(Book.abbreviation.like(book + u'%'))\
.first()
return db_book
def get_chapter(self, id, chapter): ``book``
log.debug(u'BibleDB.get_chapter("%s", %s)', id, chapter) The name of the book to return
return self.session.query(Verse)\ """
.filter_by(chapter=chapter)\ log.debug(u'BibleDb.get_book("%s")', book)
.filter_by(book_id=id)\ db_book = self.session.query(Book).filter(
.first() 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): def get_verses(self, reference_list):
""" """
@ -351,6 +379,12 @@ class BibleDB(QtCore.QObject):
return verses return verses
def get_chapter_count(self, book): 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) log.debug(u'BibleDB.get_chapter_count("%s")', book)
count = self.session.query(Verse.chapter).join(Book)\ count = self.session.query(Verse.chapter).join(Book)\
.filter(Book.name==book)\ .filter(Book.name==book)\
@ -361,6 +395,15 @@ class BibleDB(QtCore.QObject):
return count return count
def get_verse_count(self, book, chapter): 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) log.debug(u'BibleDB.get_verse_count("%s", %s)', book, chapter)
count = self.session.query(Verse).join(Book)\ count = self.session.query(Verse).join(Book)\
.filter(Book.name==book)\ .filter(Book.name==book)\
@ -371,20 +414,10 @@ class BibleDB(QtCore.QObject):
else: else:
return count 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): def dump_bible(self):
"""
Utility debugging method to dump the contents of a bible
"""
log.debug(u'.........Dumping Bible Database') log.debug(u'.........Dumping Bible Database')
log.debug('...............................Books ') log.debug('...............................Books ')
books = self.session.query(Book).all() books = self.session.query(Book).all()

View File

@ -35,8 +35,7 @@ from openlp.core.lib import Receiver
from openlp.core.utils import AppLocation from openlp.core.utils import AppLocation
from openlp.plugins.bibles.lib.common import BibleCommon, SearchResults, \ from openlp.plugins.bibles.lib.common import BibleCommon, SearchResults, \
unescape unescape
from openlp.plugins.bibles.lib.db import BibleDB from openlp.plugins.bibles.lib.db import BibleDB, Book
from openlp.plugins.bibles.lib.models import Book
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View File

@ -29,12 +29,12 @@ from PyQt4 import QtCore
from openlp.core.lib import SettingsManager from openlp.core.lib import SettingsManager
from openlp.core.utils import AppLocation from openlp.core.utils import AppLocation
from openlp.plugins.bibles.lib.db import BibleDB, Book, BibleMeta
from common import parse_reference from common import parse_reference
from opensong import OpenSongBible from opensong import OpenSongBible
from osis import OSISBible from osis import OSISBible
from csvbible import CSVBible from csvbible import CSVBible
from db import BibleDB
from http import HTTPBible from http import HTTPBible
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -137,11 +137,13 @@ class BibleManager(object):
log.debug(u'Bible Name: "%s"', name) log.debug(u'Bible Name: "%s"', name)
self.db_cache[name] = bible self.db_cache[name] = bible
# look to see if lazy load bible exists and get create getter. # 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: if source:
download_name = \ download_name = self.db_cache[name].get_object(BibleMeta,
self.db_cache[name].get_meta(u'download name').value u'download name').value
meta_proxy = self.db_cache[name].get_meta(u'proxy url') meta_proxy = self.db_cache[name].get_object(BibleMeta,
u'proxy url')
web_bible = HTTPBible(self.parent, path=self.path, web_bible = HTTPBible(self.parent, path=self.path,
file=filename, download_source=source.value, file=filename, download_source=source.value,
download_name=download_name) download_name=download_name)
@ -196,7 +198,7 @@ class BibleManager(object):
u'name': book.name, u'name': book.name,
u'chapters': self.db_cache[bible].get_chapter_count(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): def get_chapter_count(self, bible, book):
@ -249,7 +251,7 @@ class BibleManager(object):
Returns the meta data for a given key Returns the meta data for a given key
""" """
log.debug(u'get_meta %s,%s', bible, 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): def exists(self, name):
""" """

View File

@ -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)

View File

@ -90,7 +90,7 @@ class OpenSongBible(BibleDB):
QtCore.QString('%s %s %s' % ( QtCore.QString('%s %s %s' % (
translate('BiblesPlugin.Opensong', 'Importing'), \ translate('BiblesPlugin.Opensong', 'Importing'), \
db_book.name, chapter.attrib[u'n']))) db_book.name, chapter.attrib[u'n'])))
self.commit() self.session.commit()
except IOError: except IOError:
log.exception(u'Loading bible from OpenSong file failed') log.exception(u'Loading bible from OpenSong file failed')
success = False success = False

View File

@ -140,7 +140,7 @@ class OSISBible(BibleDB):
self.wizard.ImportProgressBar.setMaximum(260) self.wizard.ImportProgressBar.setMaximum(260)
if last_chapter != chapter: if last_chapter != chapter:
if last_chapter != 0: if last_chapter != 0:
self.commit() self.session.commit()
self.wizard.incrementProgressBar( self.wizard.incrementProgressBar(
u'Importing %s %s...' % \ u'Importing %s %s...' % \
(self.books[match.group(1)][0], chapter)) (self.books[match.group(1)][0], chapter))
@ -169,7 +169,7 @@ class OSISBible(BibleDB):
verse_text = self.spaces_regex.sub(u' ', verse_text) verse_text = self.spaces_regex.sub(u' ', verse_text)
self.create_verse(db_book.id, chapter, verse, verse_text) self.create_verse(db_book.id, chapter, verse, verse_text)
Receiver.send_message(u'openlp_process_events') Receiver.send_message(u'openlp_process_events')
self.commit() self.session.commit()
self.wizard.incrementProgressBar(u'Finishing import...') self.wizard.incrementProgressBar(u'Finishing import...')
if match_count == 0: if match_count == 0:
success = False success = False

View File

@ -26,8 +26,11 @@
import logging import logging
from forms import EditCustomForm from forms import EditCustomForm
from openlp.core.lib import Plugin, build_icon, PluginStatus, translate 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__) log = logging.getLogger(__name__)
@ -45,7 +48,7 @@ class CustomPlugin(Plugin):
def __init__(self, plugin_helpers): def __init__(self, plugin_helpers):
Plugin.__init__(self, u'Custom', u'1.9.2', plugin_helpers) Plugin.__init__(self, u'Custom', u'1.9.2', plugin_helpers)
self.weight = -5 self.weight = -5
self.custommanager = CustomManager() self.custommanager = Manager(u'custom', init_schema)
self.edit_custom_form = EditCustomForm(self.custommanager) self.edit_custom_form = EditCustomForm(self.custommanager)
self.icon = build_icon(u':/media/media_custom.png') self.icon = build_icon(u':/media/media_custom.png')
self.status = PluginStatus.Active self.status = PluginStatus.Active
@ -75,6 +78,8 @@ class CustomPlugin(Plugin):
return about_text return about_text
def can_delete_theme(self, theme): 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 True
return False return False

View File

@ -29,7 +29,7 @@ from PyQt4 import QtCore, QtGui
from editcustomdialog import Ui_customEditDialog from editcustomdialog import Ui_customEditDialog
from openlp.core.lib import SongXMLBuilder, SongXMLParser, Receiver, translate 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__) log = logging.getLogger(__name__)
@ -116,7 +116,7 @@ class EditCustomForm(QtGui.QDialog, Ui_customEditDialog):
self.customSlide = CustomSlide() self.customSlide = CustomSlide()
self.initialise() self.initialise()
if id != 0: 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.TitleEdit.setText(self.customSlide.title)
self.CreditEdit.setText(self.customSlide.credits) self.CreditEdit.setText(self.customSlide.credits)
songXML = SongXMLParser(self.customSlide.text) songXML = SongXMLParser(self.customSlide.text)
@ -166,8 +166,7 @@ class EditCustomForm(QtGui.QDialog, Ui_customEditDialog):
u'utf-8') u'utf-8')
self.customSlide.theme_name = unicode(self.ThemeComboBox.currentText(), self.customSlide.theme_name = unicode(self.ThemeComboBox.currentText(),
u'utf-8') u'utf-8')
self.custommanager.save_slide(self.customSlide) return self.custommanager.save_object(self.customSlide)
return True
def onUpButtonPressed(self): def onUpButtonPressed(self):
selectedRow = self.VerseListView.currentRow() selectedRow = self.VerseListView.currentRow()

View File

@ -23,6 +23,5 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
from manager import CustomManager
from mediaitem import CustomMediaItem from mediaitem import CustomMediaItem
from customtab import CustomTab from customtab import CustomTab

View File

@ -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

View File

@ -22,18 +22,40 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59 # # with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # 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 import Column, Table, types
from sqlalchemy.orm import scoped_session, sessionmaker, mapper from sqlalchemy.orm import mapper
from openlp.plugins.custom.lib.meta import metadata from openlp.core.lib.db import BaseModel, init_db
from openlp.plugins.custom.lib.tables import *
from openlp.plugins.custom.lib.classes import * 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) mapper(CustomSlide, custom_slide_table)
metadata.create_all(checkfirst=True)
return session return session

View File

@ -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()

View File

@ -29,6 +29,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import MediaManagerItem, SongXMLParser, BaseListWithDnD, \ from openlp.core.lib import MediaManagerItem, SongXMLParser, BaseListWithDnD, \
Receiver, ItemCapabilities, translate, check_item_selected Receiver, ItemCapabilities, translate, check_item_selected
from openlp.plugins.custom.lib.db import CustomSlide
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -72,7 +73,8 @@ class CustomMediaItem(MediaManagerItem):
MediaManagerItem.requiredIcons(self) MediaManagerItem.requiredIcons(self)
def initialise(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 #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 #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. #Trigger it and clean up so it will not update again.
@ -84,10 +86,10 @@ class CustomMediaItem(MediaManagerItem):
def loadCustomListView(self, list): def loadCustomListView(self, list):
self.ListView.clear() self.ListView.clear()
for CustomSlide in list: for customSlide in list:
custom_name = QtGui.QListWidgetItem(CustomSlide.title) custom_name = QtGui.QListWidgetItem(customSlide.title)
custom_name.setData( custom_name.setData(
QtCore.Qt.UserRole, QtCore.QVariant(CustomSlide.id)) QtCore.Qt.UserRole, QtCore.QVariant(customSlide.id))
self.ListView.addItem(custom_name) self.ListView.addItem(custom_name)
def onNewClick(self): def onNewClick(self):
@ -106,7 +108,7 @@ class CustomMediaItem(MediaManagerItem):
type of display is required. type of display is required.
""" """
fields = customid.split(u':') fields = customid.split(u':')
valid = self.parent.custommanager.get_custom(fields[1]) valid = self.parent.custommanager.get_object(CustomSlide, fields[1])
if valid: if valid:
self.remoteCustom = fields[1] self.remoteCustom = fields[1]
self.remoteTriggered = fields[0] self.remoteTriggered = fields[0]
@ -136,7 +138,7 @@ class CustomMediaItem(MediaManagerItem):
'You must select an item to delete.')): 'You must select an item to delete.')):
item = self.ListView.currentItem() item = self.ListView.currentItem()
item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] 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) row = self.ListView.row(item)
self.ListView.takeItem(row) self.ListView.takeItem(row)
@ -158,7 +160,7 @@ class CustomMediaItem(MediaManagerItem):
service_item.add_capability(ItemCapabilities.AllowsEdit) service_item.add_capability(ItemCapabilities.AllowsEdit)
service_item.add_capability(ItemCapabilities.AllowsPreview) service_item.add_capability(ItemCapabilities.AllowsPreview)
service_item.add_capability(ItemCapabilities.AllowsLoop) 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 title = customSlide.title
credit = customSlide.credits credit = customSlide.credits
service_item.editId = item_id service_item.editId = item_id

View File

@ -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()

View File

@ -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))
)

View File

@ -24,6 +24,7 @@
############################################################################### ###############################################################################
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate from openlp.core.lib import translate
class Ui_AuthorsDialog(object): class Ui_AuthorsDialog(object):

View File

@ -28,7 +28,6 @@ from PyQt4 import QtGui, QtCore
from openlp.core.lib import translate from openlp.core.lib import translate
from openlp.plugins.songs.forms.authorsdialog import Ui_AuthorsDialog from openlp.plugins.songs.forms.authorsdialog import Ui_AuthorsDialog
class AuthorsForm(QtGui.QDialog, Ui_AuthorsDialog): class AuthorsForm(QtGui.QDialog, Ui_AuthorsDialog):
""" """
Class to control the Maintenance of Authors Dialog Class to control the Maintenance of Authors Dialog

View File

@ -24,9 +24,8 @@
############################################################################### ###############################################################################
from PyQt4 import QtCore, QtGui 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): class Ui_EditSongDialog(object):
def setupUi(self, EditSongDialog): def setupUi(self, EditSongDialog):

View File

@ -31,7 +31,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import SongXMLBuilder, SongXMLParser, Receiver, translate from openlp.core.lib import SongXMLBuilder, SongXMLParser, Receiver, translate
from openlp.plugins.songs.forms import EditVerseForm from openlp.plugins.songs.forms import EditVerseForm
from openlp.plugins.songs.lib import VerseType 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 from editsongdialog import Ui_EditSongDialog
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -118,7 +118,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.TopicRemoveButton.setEnabled(False) self.TopicRemoveButton.setEnabled(False)
def loadAuthors(self): def loadAuthors(self):
authors = self.songmanager.get_authors() authors = self.songmanager.get_all_objects(Author, Author.display_name)
self.AuthorsSelectionComboItem.clear() self.AuthorsSelectionComboItem.clear()
self.AuthorsSelectionComboItem.addItem(u'') self.AuthorsSelectionComboItem.addItem(u'')
for author in authors: for author in authors:
@ -128,7 +128,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
row, QtCore.QVariant(author.id)) row, QtCore.QVariant(author.id))
def loadTopics(self): def loadTopics(self):
topics = self.songmanager.get_topics() topics = self.songmanager.get_all_objects(Topic, Topic.name)
self.SongTopicCombo.clear() self.SongTopicCombo.clear()
self.SongTopicCombo.addItem(u'') self.SongTopicCombo.addItem(u'')
for topic in topics: for topic in topics:
@ -137,7 +137,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.SongTopicCombo.setItemData(row, QtCore.QVariant(topic.id)) self.SongTopicCombo.setItemData(row, QtCore.QVariant(topic.id))
def loadBooks(self): def loadBooks(self):
books = self.songmanager.get_books() books = self.songmanager.get_all_objects(Book, Book.name)
self.SongbookCombo.clear() self.SongbookCombo.clear()
self.SongbookCombo.addItem(u'') self.SongbookCombo.addItem(u'')
for book in books: for book in books:
@ -178,11 +178,12 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.loadAuthors() self.loadAuthors()
self.loadTopics() self.loadTopics()
self.loadBooks() self.loadBooks()
self.song = self.songmanager.get_song(id) self.song = self.songmanager.get_object(Song, id)
self.TitleEditItem.setText(self.song.title) self.TitleEditItem.setText(self.song.title)
title = self.song.search_title.split(u'@') title = self.song.search_title.split(u'@')
if self.song.song_book_id != 0: 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( id = self.SongbookCombo.findText(
unicode(book_name.name), QtCore.Qt.MatchExactly) unicode(book_name.name), QtCore.Qt.MatchExactly)
if id == -1: if id == -1:
@ -289,7 +290,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
QtGui.QMessageBox.Yes) == QtGui.QMessageBox.Yes: QtGui.QMessageBox.Yes) == QtGui.QMessageBox.Yes:
author = Author.populate(first_name=text.rsplit(u' ', 1)[0], author = Author.populate(first_name=text.rsplit(u' ', 1)[0],
last_name=text.rsplit(u' ', 1)[1], display_name=text) 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) self.song.authors.append(author)
author_item = QtGui.QListWidgetItem( author_item = QtGui.QListWidgetItem(
unicode(author.display_name)) unicode(author.display_name))
@ -302,7 +303,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
return return
elif item > 0: elif item > 0:
item_id = (self.AuthorsSelectionComboItem.itemData(item)).toInt()[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) self.song.authors.append(author)
author_item = QtGui.QListWidgetItem(unicode(author.display_name)) author_item = QtGui.QListWidgetItem(unicode(author.display_name))
author_item.setData(QtCore.Qt.UserRole, QtCore.QVariant(author.id)) author_item.setData(QtCore.Qt.UserRole, QtCore.QVariant(author.id))
@ -325,7 +326,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.AuthorRemoveButton.setEnabled(False) self.AuthorRemoveButton.setEnabled(False)
item = self.AuthorsListView.currentItem() item = self.AuthorsListView.currentItem()
author_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] 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) self.song.authors.remove(author)
row = self.AuthorsListView.row(item) row = self.AuthorsListView.row(item)
self.AuthorsListView.takeItem(row) 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.No,
QtGui.QMessageBox.Yes) == QtGui.QMessageBox.Yes: QtGui.QMessageBox.Yes) == QtGui.QMessageBox.Yes:
topic = Topic.populate(name=text) topic = Topic.populate(name=text)
self.songmanager.save_topic(topic) self.songmanager.save_object(topic)
self.song.topics.append(topic) self.song.topics.append(topic)
topic_item = QtGui.QListWidgetItem(unicode(topic.name)) topic_item = QtGui.QListWidgetItem(unicode(topic.name))
topic_item.setData(QtCore.Qt.UserRole, topic_item.setData(QtCore.Qt.UserRole,
@ -353,7 +354,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
return return
elif item > 0: elif item > 0:
item_id = (self.SongTopicCombo.itemData(item)).toInt()[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) self.song.topics.append(topic)
topic_item = QtGui.QListWidgetItem(unicode(topic.name)) topic_item = QtGui.QListWidgetItem(unicode(topic.name))
topic_item.setData(QtCore.Qt.UserRole, QtCore.QVariant(topic.id)) topic_item.setData(QtCore.Qt.UserRole, QtCore.QVariant(topic.id))
@ -375,7 +376,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.TopicRemoveButton.setEnabled(False) self.TopicRemoveButton.setEnabled(False)
item = self.TopicsListView.currentItem() item = self.TopicsListView.currentItem()
topic_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] 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) self.song.topics.remove(topic)
row = self.TopicsListView.row(item) row = self.TopicsListView.row(item)
self.TopicsListView.takeItem(row) 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.No,
QtGui.QMessageBox.Yes) == QtGui.QMessageBox.Yes: QtGui.QMessageBox.Yes) == QtGui.QMessageBox.Yes:
book = Book.populate(name=text) book = Book.populate(name=text)
self.songmanager.save_book(book) self.songmanager.save_object(book)
self.song.book = book self.song.book = book
self.loadBooks() self.loadBooks()
else: else:
@ -630,7 +631,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
if self._validate_song(): if self._validate_song():
self.processLyrics() self.processLyrics()
self.processTitle() self.processTitle()
self.songmanager.save_song(self.song) self.songmanager.save_object(self.song)
return True return True
return False return False

View File

@ -24,6 +24,7 @@
############################################################################### ###############################################################################
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate from openlp.core.lib import translate
class Ui_SongBookDialog(object): class Ui_SongBookDialog(object):

View File

@ -28,7 +28,6 @@ from PyQt4 import QtGui
from openlp.core.lib import translate from openlp.core.lib import translate
from openlp.plugins.songs.forms.songbookdialog import Ui_SongBookDialog from openlp.plugins.songs.forms.songbookdialog import Ui_SongBookDialog
class SongBookForm(QtGui.QDialog, Ui_SongBookDialog): class SongBookForm(QtGui.QDialog, Ui_SongBookDialog):
""" """
Class documentation goes here. Class documentation goes here.

View File

@ -25,12 +25,10 @@
from PyQt4 import QtGui, QtCore 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.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): class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
""" """
@ -81,17 +79,17 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
else: else:
return -1 return -1
def _deleteItem(self, list_widget, get_func, del_func, reset_func, def _deleteItem(self, item_class, list_widget, reset_func, dlg_title,
dlg_title, del_text, err_text, sel_text): del_text, err_text, sel_text):
item_id = self._getCurrentItemId(list_widget) item_id = self._getCurrentItemId(list_widget)
if item_id != -1: 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 item and len(item.songs) == 0:
if QtGui.QMessageBox.warning(self, dlg_title, del_text, if QtGui.QMessageBox.warning(self, dlg_title, del_text,
QtGui.QMessageBox.StandardButtons( QtGui.QMessageBox.StandardButtons(
QtGui.QMessageBox.No | QtGui.QMessageBox.Yes) QtGui.QMessageBox.No | QtGui.QMessageBox.Yes)
) == QtGui.QMessageBox.Yes: ) == QtGui.QMessageBox.Yes:
del_func(item.id) self.songmanager.delete_object(item_class, item.id)
reset_func() reset_func()
else: else:
QtGui.QMessageBox.critical(self, dlg_title, err_text) QtGui.QMessageBox.critical(self, dlg_title, err_text)
@ -100,7 +98,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
def resetAuthors(self): def resetAuthors(self):
self.AuthorsListWidget.clear() self.AuthorsListWidget.clear()
authors = self.songmanager.get_authors() authors = self.songmanager.get_all_objects(Author, Author.display_name)
for author in authors: for author in authors:
if author.display_name: if author.display_name:
author_name = QtGui.QListWidgetItem(author.display_name) author_name = QtGui.QListWidgetItem(author.display_name)
@ -112,7 +110,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
def resetTopics(self): def resetTopics(self):
self.TopicsListWidget.clear() self.TopicsListWidget.clear()
topics = self.songmanager.get_topics() topics = self.songmanager.get_all_objects(Topic, Topic.name)
for topic in topics: for topic in topics:
topic_name = QtGui.QListWidgetItem(topic.name) topic_name = QtGui.QListWidgetItem(topic.name)
topic_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(topic.id)) topic_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(topic.id))
@ -120,7 +118,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
def resetBooks(self): def resetBooks(self):
self.BooksListWidget.clear() self.BooksListWidget.clear()
books = self.songmanager.get_books() books = self.songmanager.get_all_objects(Book, Book.name)
for book in books: for book in books:
book_name = QtGui.QListWidgetItem(book.name) book_name = QtGui.QListWidgetItem(book.name)
book_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(book.id)) 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()), first_name=unicode(self.authorform.FirstNameEdit.text()),
last_name=unicode(self.authorform.LastNameEdit.text()), last_name=unicode(self.authorform.LastNameEdit.text()),
display_name=unicode(self.authorform.DisplayEdit.text())) display_name=unicode(self.authorform.DisplayEdit.text()))
if self.songmanager.save_author(author): if self.songmanager.save_object(author):
self.resetAuthors() self.resetAuthors()
else: else:
QtGui.QMessageBox.critical( QtGui.QMessageBox.critical(
@ -145,7 +143,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
def onTopicAddButtonClick(self): def onTopicAddButtonClick(self):
if self.topicform.exec_(): if self.topicform.exec_():
topic = Topic.populate(name=unicode(self.topicform.NameEdit.text())) topic = Topic.populate(name=unicode(self.topicform.NameEdit.text()))
if self.songmanager.save_topic(topic): if self.songmanager.save_object(topic):
self.resetTopics() self.resetTopics()
else: else:
QtGui.QMessageBox.critical( QtGui.QMessageBox.critical(
@ -159,7 +157,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
book = Book.populate( book = Book.populate(
name=unicode(self.bookform.NameEdit.text()), name=unicode(self.bookform.NameEdit.text()),
publisher=unicode(self.bookform.PublisherEdit.text())) publisher=unicode(self.bookform.PublisherEdit.text()))
if self.songmanager.save_book(book): if self.songmanager.save_object(book):
self.resetBooks() self.resetBooks()
else: else:
QtGui.QMessageBox.critical( QtGui.QMessageBox.critical(
@ -171,7 +169,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
def onAuthorEditButtonClick(self): def onAuthorEditButtonClick(self):
author_id = self._getCurrentItemId(self.AuthorsListWidget) author_id = self._getCurrentItemId(self.AuthorsListWidget)
if author_id != -1: 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 # Just make sure none of the fields is None
if author.first_name is None: if author.first_name is None:
author.first_name = u'' author.first_name = u''
@ -189,7 +187,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
author.last_name = unicode(self.authorform.LastNameEdit.text()) author.last_name = unicode(self.authorform.LastNameEdit.text())
author.display_name = unicode( author.display_name = unicode(
self.authorform.DisplayEdit.text()) self.authorform.DisplayEdit.text())
if self.songmanager.save_author(author): if self.songmanager.save_object(author):
self.resetAuthors() self.resetAuthors()
else: else:
QtGui.QMessageBox.critical( QtGui.QMessageBox.critical(
@ -201,11 +199,11 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
def onTopicEditButtonClick(self): def onTopicEditButtonClick(self):
topic_id = self._getCurrentItemId(self.TopicsListWidget) topic_id = self._getCurrentItemId(self.TopicsListWidget)
if topic_id != -1: 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) self.topicform.NameEdit.setText(topic.name)
if self.topicform.exec_(False): if self.topicform.exec_(False):
topic.name = unicode(self.topicform.NameEdit.text()) topic.name = unicode(self.topicform.NameEdit.text())
if self.songmanager.save_topic(topic): if self.songmanager.save_object(topic):
self.resetTopics() self.resetTopics()
else: else:
QtGui.QMessageBox.critical( QtGui.QMessageBox.critical(
@ -217,13 +215,13 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
def onBookEditButtonClick(self): def onBookEditButtonClick(self):
book_id = self._getCurrentItemId(self.BooksListWidget) book_id = self._getCurrentItemId(self.BooksListWidget)
if book_id != -1: 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.NameEdit.setText(book.name)
self.bookform.PublisherEdit.setText(book.publisher) self.bookform.PublisherEdit.setText(book.publisher)
if self.bookform.exec_(False): if self.bookform.exec_(False):
book.name = unicode(self.bookform.NameEdit.text()) book.name = unicode(self.bookform.NameEdit.text())
book.publisher = unicode(self.bookform.PublisherEdit.text()) book.publisher = unicode(self.bookform.PublisherEdit.text())
if self.songmanager.save_book(book): if self.songmanager.save_object(book):
self.resetBooks() self.resetBooks()
else: else:
QtGui.QMessageBox.critical( 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 Delete the author if the author is not attached to any songs
""" """
self._deleteItem( self._deleteItem(Author, self.AuthorsListWidget, self.resetAuthors,
self.AuthorsListWidget, self.songmanager.get_author,
self.songmanager.delete_author, self.resetAuthors,
translate('SongsPlugin.SongMaintenanceForm', 'Delete Author'), translate('SongsPlugin.SongMaintenanceForm', 'Delete Author'),
translate('SongsPlugin.SongMaintenanceForm', translate('SongsPlugin.SongMaintenanceForm',
'Are you sure you want to delete the selected author?'), 'Are you sure you want to delete the selected author?'),
translate('SongsPlugin.SongMaintenanceForm', translate('SongsPlugin.SongMaintenanceForm',
'This author can\'t be deleted, they are currently ' '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 Delete the Book is the Book is not attached to any songs
""" """
self._deleteItem( self._deleteItem(Topic, self.TopicsListWidget, self.resetTopics,
self.TopicsListWidget, self.songmanager.get_topic,
self.songmanager.delete_topic, self.resetTopics,
translate('SongsPlugin.SongMaintenanceForm', 'Delete Topic'), translate('SongsPlugin.SongMaintenanceForm', 'Delete Topic'),
translate('SongsPlugin.SongMaintenanceForm', translate('SongsPlugin.SongMaintenanceForm',
'Are you sure you want to delete the selected topic?'), '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 ' 'This topic can\'t be deleted, it is currently '
'assigned to at least one song.'), 'assigned to at least one song.'),
translate('SongsPlugin.SongMaintenanceForm', 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 Delete the Book is the Book is not attached to any songs
""" """
self._deleteItem( self._deleteItem(Book, self.BooksListWidget, self.resetBooks,
self.BooksListWidget, self.songmanager.get_book,
self.songmanager.delete_book, self.resetBooks,
translate('SongsPlugin.SongMaintenanceForm', 'Delete Book'), translate('SongsPlugin.SongMaintenanceForm', 'Delete Book'),
translate('SongsPlugin.SongMaintenanceForm', translate('SongsPlugin.SongMaintenanceForm',
'Are you sure you want to delete the selected book?'), '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 ' 'This book can\'t be deleted, it is currently '
'assigned to at least one song.'), 'assigned to at least one song.'),
translate('SongsPlugin.SongMaintenanceForm', 'No book selected!')) translate('SongsPlugin.SongMaintenanceForm', u'No book selected!'))

View File

@ -24,6 +24,7 @@
############################################################################### ###############################################################################
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate from openlp.core.lib import translate
class Ui_TopicsDialog(object): class Ui_TopicsDialog(object):

View File

@ -28,7 +28,6 @@ from PyQt4 import QtGui
from openlp.core.lib import translate from openlp.core.lib import translate
from openlp.plugins.songs.forms.topicsdialog import Ui_TopicsDialog from openlp.plugins.songs.forms.topicsdialog import Ui_TopicsDialog
class TopicsForm(QtGui.QDialog, Ui_TopicsDialog): class TopicsForm(QtGui.QDialog, Ui_TopicsDialog):
""" """
Class documentation goes here. Class documentation goes here.

View File

@ -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'<Book id="%s" name="%s" publisher="%s" />' % (
str(self.id), self.name, self.publisher)
class Song(BaseModel):
"""
Song model
"""
pass
class Topic(BaseModel):
"""
Topic model
"""
pass

View File

@ -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'<Book id="%s" name="%s" publisher="%s" />' % (
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

View File

@ -25,12 +25,8 @@
import logging import logging
from PyQt4 import QtCore from openlp.core.lib.db import Manager
from sqlalchemy.exceptions import InvalidRequestError from openlp.plugins.songs.lib.db import init_schema, Song, Author
from openlp.core.utils import AppLocation
from openlp.plugins.songs.lib.models import init_models, metadata, Song, \
Author, Topic, Book
#from openlp.plugins.songs.lib import OpenLyricsSong, OpenSongSong, CCLISong, \ #from openlp.plugins.songs.lib import OpenLyricsSong, OpenSongSong, CCLISong, \
# CSVSong # 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 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. class takes care of connecting to the database and running all the queries.
@ -93,35 +89,9 @@ class SongManager(object):
don't exist. don't exist.
""" """
log.debug(u'Song Initialising') log.debug(u'Song Initialising')
settings = QtCore.QSettings() Manager.__init__(self, u'songs', init_schema)
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()
log.debug(u'Song Initialised') 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): def search_song_title(self, keywords):
""" """
Searches the song title for keywords. Searches the song title for keywords.
@ -144,175 +114,3 @@ class SongManager(object):
""" """
return self.session.query(Author).filter(Author.display_name.like( return self.session.query(Author).filter(Author.display_name.like(
u'%' + keywords + u'%')).order_by(Author.display_name.asc()).all() 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()

View File

@ -31,6 +31,7 @@ from openlp.core.lib import MediaManagerItem, SongXMLParser, \
BaseListWithDnD, Receiver, ItemCapabilities, translate, check_item_selected BaseListWithDnD, Receiver, ItemCapabilities, translate, check_item_selected
from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \ from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \
ImportWizardForm ImportWizardForm
from openlp.plugins.songs.lib.db import Song
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -268,7 +269,7 @@ class SongMediaItem(MediaManagerItem):
type of display is required. type of display is required.
""" """
fields = songid.split(u':') fields = songid.split(u':')
valid = self.parent.manager.get_song(fields[1]) valid = self.parent.manager.get_object(Song, fields[1])
if valid: if valid:
self.remoteSong = fields[1] self.remoteSong = fields[1]
self.remoteTriggered = fields[0] self.remoteTriggered = fields[0]
@ -310,7 +311,7 @@ class SongMediaItem(MediaManagerItem):
return return
for item in items: for item in items:
item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] 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() self.onSearchTextButtonClick()
def generateSlideData(self, service_item, item=None): 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.AllowsEdit)
service_item.add_capability(ItemCapabilities.AllowsPreview) service_item.add_capability(ItemCapabilities.AllowsPreview)
service_item.add_capability(ItemCapabilities.AllowsLoop) 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.theme = song.theme_name
service_item.editId = item_id service_item.editId = item_id
if song.lyrics.startswith(u'<?xml version='): if song.lyrics.startswith(u'<?xml version='):

View File

@ -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()

View File

@ -1,48 +0,0 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2010 Raoul Snyman #
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin #
# Thompson, Jon Tibble, Carsten Tinggaard #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker, mapper, relation
from openlp.plugins.songs.lib.meta import metadata
from openlp.plugins.songs.lib.tables import *
from openlp.plugins.songs.lib.classes import *
def init_models(url):
engine = create_engine(url)
metadata.bind = engine
session = scoped_session(sessionmaker(autoflush=False, autocommit=False,
bind=engine))
mapper(Author, authors_table)
mapper(Book, song_books_table)
mapper(Song, songs_table,
properties={'authors': relation(Author, backref='songs',
secondary=authors_songs_table),
'book': relation(Book, backref='songs'),
'topics': relation(Topic, backref='songs',
secondary=songs_topics_table)})
mapper(Topic, topics_table)
return session

View File

@ -27,7 +27,7 @@ import re
from openlp.core.lib import SongXMLBuilder, translate from openlp.core.lib import SongXMLBuilder, translate
from openlp.plugins.songs.lib import VerseType 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 Song, Author, Topic, Book
class SongImport(object): class SongImport(object):
""" """
@ -264,7 +264,6 @@ class SongImport(object):
if len(self.authors) == 0: if len(self.authors) == 0:
self.authors.append(u'Author unknown') self.authors.append(u'Author unknown')
self.commit_song() self.commit_song()
#self.print_song()
def commit_song(self): def commit_song(self):
""" """
@ -303,30 +302,33 @@ class SongImport(object):
song.theme_name = self.theme_name song.theme_name = self.theme_name
song.ccli_number = self.ccli_number song.ccli_number = self.ccli_number
for authortext in self.authors: for authortext in self.authors:
author = self.manager.get_author_by_name(authortext) filter_string = u'display_name=%s' % authortext
author = self.manager.get_object_filtered(Author, filter_string)
if author is None: if author is None:
author = Author() author = Author()
author.display_name = authortext author.display_name = authortext
author.last_name = authortext.split(u' ')[-1] author.last_name = authortext.split(u' ')[-1]
author.first_name = u' '.join(authortext.split(u' ')[:-1]) author.first_name = u' '.join(authortext.split(u' ')[:-1])
self.manager.save_author(author) self.manager.save_object(author)
song.authors.append(author) song.authors.append(author)
if self.song_book_name: if self.song_book_name:
song_book = self.manager.get_book_by_name(self.song_book_name) filter_string = u'name=%s' % self.song_book_name
song_book = self.manager.get_object_filtered(Book, filter_string)
if song_book is None: if song_book is None:
song_book = Book() song_book = Book()
song_book.name = self.song_book_name song_book.name = self.song_book_name
song_book.publisher = self.song_book_pub song_book.publisher = self.song_book_pub
self.manager.save_book(song_book) self.manager.save_object(song_book)
song.song_book_id = song_book.id song.song_book_id = song_book.id
for topictext in self.topics: for topictext in self.topics:
topic = self.manager.get_topic_by_name(topictext) filter_string = u'name=%s' % topictext
topic = self.manager.get_object_filtered(Topic, filter_string)
if topic is None: if topic is None:
topic = Topic() topic = Topic()
topic.name = topictext topic.name = topictext
self.manager.save_topic(topic) self.manager.save_object(topic)
song.topics.append(topictext) song.topics.append(topictext)
self.manager.save_song(song) self.manager.save_object(song)
def print_song(self): def print_song(self):
""" """
@ -357,5 +359,3 @@ class SongImport(object):
print u'THEME: ' + self.theme_name print u'THEME: ' + self.theme_name
if self.ccli_number: if self.ccli_number:
print u'CCLI: ' + self.ccli_number print u'CCLI: ' + self.ccli_number

View File

@ -1,99 +0,0 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2010 Raoul Snyman #
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin #
# Thompson, Jon Tibble, Carsten Tinggaard #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
from sqlalchemy import *
from sqlalchemy import Column, Table, ForeignKey, types
from openlp.plugins.songs.lib.meta import metadata
# Definition of the "authors" table
authors_table = Table(u'authors', metadata,
Column(u'id', types.Integer, primary_key=True),
Column(u'first_name', types.Unicode(128)),
Column(u'last_name', types.Unicode(128)),
Column(u'display_name', types.Unicode(255), nullable=False)
)
# Definition of the "song_books" table
song_books_table = Table(u'song_books', metadata,
Column(u'id', types.Integer, primary_key=True),
Column(u'name', types.Unicode(128), nullable=False),
Column(u'publisher', types.Unicode(128))
)
# Definition of the "songs" table
songs_table = Table(u'songs', metadata,
Column(u'id', types.Integer, primary_key=True),
Column(u'song_book_id', types.Integer,
ForeignKey(u'song_books.id'), default=0),
Column(u'title', types.Unicode(255), nullable=False),
Column(u'lyrics', types.UnicodeText, nullable=False),
Column(u'verse_order', types.Unicode(128)),
Column(u'copyright', types.Unicode(255)),
Column(u'comments', types.UnicodeText),
Column(u'ccli_number', types.Unicode(64)),
Column(u'song_number', types.Unicode(64)),
Column(u'theme_name', types.Unicode(128)),
Column(u'search_title', types.Unicode(255), index=True, nullable=False),
Column(u'search_lyrics', types.UnicodeText, index=True, nullable=False)
)
# Definition of the "topics" table
topics_table = Table(u'topics', metadata,
Column(u'id', types.Integer, primary_key=True),
Column(u'name', types.Unicode(128), nullable=False)
)
# Definition of the "authors_songs" table
authors_songs_table = Table(u'authors_songs', metadata,
Column(u'author_id', types.Integer,
ForeignKey(u'authors.id'), primary_key=True),
Column(u'song_id', types.Integer,
ForeignKey(u'songs.id'), primary_key=True)
)
# Definition of the "songs_topics" table
songs_topics_table = Table(u'songs_topics', metadata,
Column(u'song_id', types.Integer,
ForeignKey(u'songs.id'), primary_key=True),
Column(u'topic_id', types.Integer,
ForeignKey(u'topics.id'), primary_key=True)
)
# Define table indexes
Index(u'authors_id', authors_table.c.id)
Index(u'authors_display_name_id', authors_table.c.display_name,
authors_table.c.id)
Index(u'song_books_id', song_books_table.c.id)
Index(u'songs_id', songs_table.c.id)
Index(u'topics_id', topics_table.c.id)
Index(u'authors_songs_author', authors_songs_table.c.author_id,
authors_songs_table.c.song_id)
Index(u'authors_songs_song', authors_songs_table.c.song_id,
authors_songs_table.c.author_id)
Index(u'topics_song_topic', songs_topics_table.c.topic_id,
songs_topics_table.c.song_id)
Index(u'topics_song_song', songs_topics_table.c.song_id,
songs_topics_table.c.topic_id)

View File

@ -30,6 +30,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import Plugin, build_icon, PluginStatus, Receiver, \ from openlp.core.lib import Plugin, build_icon, PluginStatus, Receiver, \
translate translate
from openlp.plugins.songs.lib import SongManager, SongMediaItem, SongsTab from openlp.plugins.songs.lib import SongManager, SongMediaItem, SongsTab
from openlp.plugins.songs.lib.db import Song
try: try:
from openlp.plugins.songs.lib import SofImport, OooImport from openlp.plugins.songs.lib import SofImport, OooImport
@ -39,7 +40,6 @@ except ImportError:
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
class SongsPlugin(Plugin): class SongsPlugin(Plugin):
""" """
This is the number 1 plugin, if importance were placed on any This is the number 1 plugin, if importance were placed on any
@ -69,7 +69,8 @@ class SongsPlugin(Plugin):
# self.songmanager = SongManager() # self.songmanager = SongManager()
Plugin.initialise(self) Plugin.initialise(self)
self.insert_toolbox_item() self.insert_toolbox_item()
self.media_item.displayResultsSong(self.manager.get_songs()) self.media_item.displayResultsSong(
self.manager.get_all_objects(Song, Song.title))
def finalise(self): def finalise(self):
log.info(u'Plugin Finalise') log.info(u'Plugin Finalise')
@ -198,6 +199,7 @@ class SongsPlugin(Plugin):
return about_text return about_text
def can_delete_theme(self, theme): def can_delete_theme(self, theme):
if len(self.manager.get_songs_for_theme(theme)) == 0: filter_string = u'theme_name=%s' % theme
if not self.manager.get_all_objects_filtered(Song, filter_string):
return True return True
return False return False

View File

@ -74,16 +74,16 @@ class SongUsageDetailForm(QtGui.QDialog, Ui_SongUsageDetailDialog):
filename = u'usage_detail_%s_%s.txt' % ( filename = u'usage_detail_%s_%s.txt' % (
self.FromDate.selectedDate().toString(u'ddMMyyyy'), self.FromDate.selectedDate().toString(u'ddMMyyyy'),
self.ToDate.selectedDate().toString(u'ddMMyyyy')) self.ToDate.selectedDate().toString(u'ddMMyyyy'))
usage = self.parent.songusagemanager.get_all_songusage( usage = self.parent.songusagemanager.get_songusage_for_period(
self.FromDate.selectedDate(), self.ToDate.selectedDate()) self.FromDate.selectedDate(), self.ToDate.selectedDate())
outname = os.path.join(unicode(self.FileLineEdit.text()), filename) outname = os.path.join(unicode(self.FileLineEdit.text()), filename)
file = None file = None
try: try:
file = open(outname, u'w') file = open(outname, u'w')
for instance in usage: for instance in usage:
record = u'\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"\n' % \ record = u'\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"\n' % (
(instance.usagedate,instance.usagetime, instance.title, instance.usagedate, instance.usagetime, instance.title,
instance.copyright, instance.ccl_number , instance.authors) instance.copyright, instance.ccl_number, instance.authors)
file.write(record) file.write(record)
except IOError: except IOError:
log.exception(u'Failed to write out song usage records') log.exception(u'Failed to write out song usage records')

View File

@ -22,5 +22,7 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59 # # with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
"""
from manager import SongUsageManager The :mod:`lib` module contains the library functions for the songusage plugin.
"""
from openlp.plugins.songusage.lib.manager import SongUsageManager

View File

@ -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 SongUsageItem(BaseModel):
"""
Audit model
"""
pass

View File

@ -22,18 +22,42 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59 # # with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
"""
The :mod:`db` module provides the database and schema that is the backend for
the SongUsage plugin
"""
from sqlalchemy import create_engine from sqlalchemy import Column, Table, types
from sqlalchemy.orm import scoped_session, sessionmaker, mapper from sqlalchemy.orm import mapper
from openlp.plugins.songusage.lib.meta import metadata from openlp.core.lib.db import BaseModel, init_db
from openlp.plugins.songusage.lib.tables import *
from openlp.plugins.songusage.lib.classes import * class SongUsageItem(BaseModel):
"""
SongUsageItem model
"""
pass
def init_schema(url):
"""
Setup the songusage database connection and initialise the database schema
``url``
The database to setup
"""
session, metadata = init_db(url)
songusage_table = Table(u'songusage_data', metadata,
Column(u'id', types.Integer(), primary_key=True),
Column(u'usagedate', types.Date, index=True, nullable=False),
Column(u'usagetime', types.Time, index=True, nullable=False),
Column(u'title', types.Unicode(255), nullable=False),
Column(u'authors', types.Unicode(255), nullable=False),
Column(u'copyright', types.Unicode(255)),
Column(u'ccl_number', types.Unicode(65))
)
def init_models(url):
engine = create_engine(url)
metadata.bind = engine
session = scoped_session(sessionmaker(autoflush=True, autocommit=False,
bind=engine))
mapper(SongUsageItem, songusage_table) mapper(SongUsageItem, songusage_table)
metadata.create_all(checkfirst=True)
return session return session

View File

@ -25,16 +25,14 @@
import logging import logging
from PyQt4 import QtCore
from sqlalchemy.exceptions import InvalidRequestError from sqlalchemy.exceptions import InvalidRequestError
from openlp.core.utils import AppLocation from openlp.core.lib.db import Manager
from openlp.plugins.songusage.lib.models import init_models, metadata, \ from openlp.plugins.songusage.lib.db import init_schema, SongUsageItem
SongUsageItem
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
class SongUsageManager(object): class SongUsageManager(Manager):
""" """
The Song Manager provides a central location for all database code. This 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. class takes care of connecting to the database and running all the queries.
@ -47,98 +45,31 @@ class SongUsageManager(object):
don't exist. don't exist.
""" """
log.debug(u'SongUsage Initialising') log.debug(u'SongUsage Initialising')
settings = QtCore.QSettings() Manager.__init__(self, u'songusage', init_schema)
settings.beginGroup(u'songusage')
self.db_url = u''
db_type = unicode(
settings.value(u'db type', QtCore.QVariant(u'sqlite')).toString())
if db_type == u'sqlite':
self.db_url = u'sqlite:///%s/songusage.sqlite' % \
AppLocation.get_section_data_path(u'songusage')
else:
self.db_url = u'%s://%s:%s@%s/%s' % (db_type,
unicode(settings.value(u'db username',
QtCore.QVariant(u'')).toString()),
unicode(settings.value(u'db password',
QtCore.QVariant(u'')).toString()),
unicode(settings.value(u'db hostname',
QtCore.QVariant(u'')).toString()),
unicode(settings.value(u'db database',
QtCore.QVariant(u'')).toString()))
self.session = init_models(self.db_url)
metadata.create_all(checkfirst=True)
settings.endGroup()
log.debug(u'SongUsage Initialised') log.debug(u'SongUsage Initialised')
def get_all_songusage(self, start_date, end_date): def get_songusage_for_period(self, start_date, end_date):
""" """
Returns the details of SongUsage Returns the details of SongUsage for a designated time period
``start_date``
The start of the period to return
``end_date``
The end of the period to return
""" """
return self.session.query(SongUsageItem) \ return self.session.query(SongUsageItem) \
.filter(SongUsageItem.usagedate >= start_date.toPyDate()) \ .filter(SongUsageItem.usagedate >= start_date.toPyDate()) \
.filter(SongUsageItem.usagedate < end_date.toPyDate()) \ .filter(SongUsageItem.usagedate < end_date.toPyDate()) \
.order_by(SongUsageItem.usagedate, SongUsageItem.usagetime ).all() .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
def delete_to_date(self, date): def delete_to_date(self, date):
""" """
Delete SongUsage records before given date Delete SongUsage records before given date
""" """
try: try:
self.session.query(SongUsageItem)\ self.session.query(SongUsageItem) \
.filter(SongUsageItem.usagedate <= date)\ .filter(SongUsageItem.usagedate <= date) \
.delete(synchronize_session=False) .delete(synchronize_session=False)
self.session.commit() self.session.commit()
return True return True
@ -146,4 +77,3 @@ class SongUsageManager(object):
self.session.rollback() self.session.rollback()
log.exception(u'Failed to delete all Song Usage items to %s' % date) log.exception(u'Failed to delete all Song Usage items to %s' % date)
return False return False

View File

@ -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()

View File

@ -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))
)

View File

@ -23,16 +23,16 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
from datetime import datetime
import logging import logging
from datetime import datetime
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import Plugin, Receiver, build_icon, translate from openlp.core.lib import Plugin, Receiver, build_icon, translate
from openlp.plugins.songusage.lib import SongUsageManager from openlp.plugins.songusage.lib import SongUsageManager
from openlp.plugins.songusage.forms import SongUsageDetailForm, \ from openlp.plugins.songusage.forms import SongUsageDetailForm, \
SongUsageDeleteForm SongUsageDeleteForm
from openlp.plugins.songusage.lib.models import SongUsageItem from openlp.plugins.songusage.lib.db import SongUsageItem
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -148,7 +148,7 @@ class SongUsagePlugin(Plugin):
song_usage_item.authors = u'' song_usage_item.authors = u''
for author in audit[1]: for author in audit[1]:
song_usage_item.authors += author + u' ' song_usage_item.authors += author + u' '
self.songusagemanager.insert_songusage(song_usage_item) self.songusagemanager.save_object(song_usage_item)
def onSongUsageDelete(self): def onSongUsageDelete(self):
self.SongUsagedeleteform.exec_() self.SongUsagedeleteform.exec_()
@ -162,4 +162,4 @@ class SongUsagePlugin(Plugin):
'<b>SongUsage Plugin</b><br>This plugin ' '<b>SongUsage Plugin</b><br>This plugin '
'records the use of songs and when they have been used during ' 'records the use of songs and when they have been used during '
'a live service') 'a live service')
return about_text return about_text