From 55f6197212478480665e3310e744ef536a53aeb1 Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Sat, 12 Jun 2010 02:52:04 +0100 Subject: [PATCH 01/49] RFC: Refactor database setup code A possible way to refactor database code to remove code duplication and, I hope, provide a simpler, more intuitive model to be copied by others --- openlp/core/lib/__init__.py | 1 - openlp/core/lib/{basemodel.py => db.py} | 26 ++- openlp/migration/migratebibles.py | 3 +- openlp/migration/migratesongs.py | 3 +- openlp/plugins/alerts/forms/alertform.py | 2 +- .../plugins/alerts/lib/{classes.py => db.py} | 28 +++- openlp/plugins/alerts/lib/manager.py | 7 +- openlp/plugins/alerts/lib/meta.py | 38 ----- openlp/plugins/alerts/lib/models.py | 39 ----- openlp/plugins/alerts/lib/tables.py | 33 ---- openlp/plugins/bibles/lib/models.py | 2 +- openlp/plugins/custom/lib/classes.py | 2 +- openlp/plugins/songs/forms/authorsdialog.py | 1 + openlp/plugins/songs/forms/authorsform.py | 1 - openlp/plugins/songs/forms/editsongdialog.py | 3 +- openlp/plugins/songs/forms/editsongform.py | 2 +- openlp/plugins/songs/forms/songbookdialog.py | 1 + openlp/plugins/songs/forms/songbookform.py | 1 - .../songs/forms/songmaintenanceform.py | 4 +- openlp/plugins/songs/forms/topicsdialog.py | 1 + openlp/plugins/songs/forms/topicsform.py | 1 - openlp/plugins/songs/lib/classes.py | 52 ------ openlp/plugins/songs/lib/db.py | 150 ++++++++++++++++++ openlp/plugins/songs/lib/manager.py | 7 +- openlp/plugins/songs/lib/meta.py | 38 ----- openlp/plugins/songs/lib/models.py | 48 ------ openlp/plugins/songs/lib/songimport.py | 2 +- openlp/plugins/songs/lib/tables.py | 99 ------------ openlp/plugins/songs/songsplugin.py | 1 - openlp/plugins/songusage/lib/classes.py | 2 +- 30 files changed, 223 insertions(+), 375 deletions(-) rename openlp/core/lib/{basemodel.py => db.py} (74%) rename openlp/plugins/alerts/lib/{classes.py => db.py} (72%) delete mode 100644 openlp/plugins/alerts/lib/meta.py delete mode 100644 openlp/plugins/alerts/lib/models.py delete mode 100644 openlp/plugins/alerts/lib/tables.py delete mode 100644 openlp/plugins/songs/lib/classes.py create mode 100644 openlp/plugins/songs/lib/db.py delete mode 100644 openlp/plugins/songs/lib/meta.py delete mode 100644 openlp/plugins/songs/lib/models.py delete mode 100644 openlp/plugins/songs/lib/tables.py diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py index d5b46e6cb..e09b6f1b4 100644 --- a/openlp/core/lib/__init__.py +++ b/openlp/core/lib/__init__.py @@ -184,5 +184,4 @@ from themexmlhandler import ThemeXML from renderer import Renderer from rendermanager import RenderManager from mediamanageritem import MediaManagerItem -from basemodel import BaseModel from baselistwithdnd import BaseListWithDnD diff --git a/openlp/core/lib/basemodel.py b/openlp/core/lib/db.py similarity index 74% rename from openlp/core/lib/basemodel.py rename to openlp/core/lib/db.py index f56336c7b..4762da157 100644 --- a/openlp/core/lib/basemodel.py +++ b/openlp/core/lib/db.py @@ -22,6 +22,31 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### +""" +The :mod:`db` module provides the core database functionality for OpenLP +""" + +from sqlalchemy import create_engine, MetaData +from sqlalchemy.orm import scoped_session, sessionmaker + +def init_db(url, auto_flush=True, auto_commit=False): + """ + Initialise and return the session and metadata for a database + + ``url`` + The database to initialise connection with + + ``auto_flush`` + Sets the flushing behaviour of the session + + ``auto_commit`` + Sets the commit behaviour of the session + """ + engine = create_engine(url) + metadata = MetaData(bind=engine) + session = scoped_session(sessionmaker(autoflush=auto_flush, + autocommit=auto_commit, bind=engine)) + return session, metadata class BaseModel(object): """ @@ -37,4 +62,3 @@ class BaseModel(object): for key in kwargs: me.__setattr__(key, kwargs[key]) return me - diff --git a/openlp/migration/migratebibles.py b/openlp/migration/migratebibles.py index 89bb5ffdf..b024343a4 100644 --- a/openlp/migration/migratebibles.py +++ b/openlp/migration/migratebibles.py @@ -30,7 +30,8 @@ import sqlite3 from sqlalchemy.exceptions import InvalidRequestError from sqlalchemy.orm import mapper -from openlp.core.lib import BaseModel, SettingsManager +from openlp.core.lib import SettingsManager +from openlp.core.lib.db import BaseModel from openlp.core.utils import AppLocation from openlp.plugins.bibles.lib.models import * diff --git a/openlp/migration/migratesongs.py b/openlp/migration/migratesongs.py index 87d5de40b..c4cab00bc 100644 --- a/openlp/migration/migratesongs.py +++ b/openlp/migration/migratesongs.py @@ -31,7 +31,8 @@ from sqlalchemy import create_engine from sqlalchemy.exceptions import InvalidRequestError from sqlalchemy.orm import scoped_session, sessionmaker, mapper, relation -from openlp.core.lib import BaseModel, SettingsManager +from openlp.core.lib import SettingsManager +from openlp.core.lib.db import BaseModel from openlp.core.utils import AppLocation from openlp.plugins.songs.lib.models import metadata, songs_table, Song, \ Author, Topic, Book diff --git a/openlp/plugins/alerts/forms/alertform.py b/openlp/plugins/alerts/forms/alertform.py index 04028fc1b..e8fc0d2fe 100644 --- a/openlp/plugins/alerts/forms/alertform.py +++ b/openlp/plugins/alerts/forms/alertform.py @@ -25,8 +25,8 @@ from PyQt4 import QtGui, QtCore -from openlp.plugins.alerts.lib.models import AlertItem from openlp.core.lib import translate +from openlp.plugins.alerts.lib.db import AlertItem from alertdialog import Ui_AlertDialog diff --git a/openlp/plugins/alerts/lib/classes.py b/openlp/plugins/alerts/lib/db.py similarity index 72% rename from openlp/plugins/alerts/lib/classes.py rename to openlp/plugins/alerts/lib/db.py index e58f80829..3656d41b8 100644 --- a/openlp/plugins/alerts/lib/classes.py +++ b/openlp/plugins/alerts/lib/db.py @@ -22,11 +22,35 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### +""" +The :mod:`db` module provides the database and schema that is the backend for +the Alerts plugin +""" -from openlp.core.lib import BaseModel +from sqlalchemy import Column, Table, types +from sqlalchemy.orm import mapper + +from openlp.core.lib.db import BaseModel, init_db class AlertItem(BaseModel): """ - Custom Slide model + AlertItem model """ pass + +def init_schema(url): + """ + Setup the alerts database connection and initialise the database schema + + ``url`` + The database to setup + """ + session, metadata = init_db(url) + + alerts_table = Table(u'alerts', metadata, + Column(u'id', types.Integer(), primary_key=True), + Column(u'text', types.UnicodeText, nullable=False)) + + mapper(AlertItem, alerts_table) + + return session, metadata diff --git a/openlp/plugins/alerts/lib/manager.py b/openlp/plugins/alerts/lib/manager.py index 088f0cbae..814e3dca6 100644 --- a/openlp/plugins/alerts/lib/manager.py +++ b/openlp/plugins/alerts/lib/manager.py @@ -29,7 +29,7 @@ from PyQt4 import QtCore from sqlalchemy.exceptions import InvalidRequestError from openlp.core.utils import AppLocation -from openlp.plugins.alerts.lib.models import init_models, metadata, AlertItem +from openlp.plugins.alerts.lib.db import init_schema, AlertItem log = logging.getLogger(__name__) @@ -61,8 +61,8 @@ class DBManager(object): unicode(settings.value(u'db hostname').toString()), unicode(settings.value(u'db database').toString())) settings.endGroup() - self.session = init_models(self.db_url) - metadata.create_all(checkfirst=True) + self.session, self.metadata = init_schema(self.db_url) + self.metadata.create_all(checkfirst=True) log.debug(u'Alerts Initialised') def get_all_alerts(self): @@ -111,4 +111,3 @@ class DBManager(object): return False else: return True - diff --git a/openlp/plugins/alerts/lib/meta.py b/openlp/plugins/alerts/lib/meta.py deleted file mode 100644 index affa31969..000000000 --- a/openlp/plugins/alerts/lib/meta.py +++ /dev/null @@ -1,38 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin # -# Thompson, Jon Tibble, Carsten Tinggaard # -# --------------------------------------------------------------------------- # -# This program is free software; you can redistribute it and/or modify it # -# under the terms of the GNU General Public License as published by the Free # -# Software Foundation; version 2 of the License. # -# # -# This program is distributed in the hope that it will be useful, but WITHOUT # -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # -# more details. # -# # -# You should have received a copy of the GNU General Public License along # -# with this program; if not, write to the Free Software Foundation, Inc., 59 # -# Temple Place, Suite 330, Boston, MA 02111-1307 USA # -############################################################################### - -from sqlalchemy import MetaData - -__all__ = ['session', 'metadata', 'engine'] - -# SQLAlchemy database engine. Updated by model.init_model() -engine = None - -# SQLAlchemy session manager. Updated by model.init_model() -session = None - -# Global metadata. If you have multiple databases with overlapping table -# names, you'll need a metadata for each database -metadata = MetaData() diff --git a/openlp/plugins/alerts/lib/models.py b/openlp/plugins/alerts/lib/models.py deleted file mode 100644 index f222345f1..000000000 --- a/openlp/plugins/alerts/lib/models.py +++ /dev/null @@ -1,39 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin # -# Thompson, Jon Tibble, Carsten Tinggaard # -# --------------------------------------------------------------------------- # -# This program is free software; you can redistribute it and/or modify it # -# under the terms of the GNU General Public License as published by the Free # -# Software Foundation; version 2 of the License. # -# # -# This program is distributed in the hope that it will be useful, but WITHOUT # -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # -# more details. # -# # -# You should have received a copy of the GNU General Public License along # -# with this program; if not, write to the Free Software Foundation, Inc., 59 # -# Temple Place, Suite 330, Boston, MA 02111-1307 USA # -############################################################################### - -from sqlalchemy import create_engine -from sqlalchemy.orm import scoped_session, sessionmaker, mapper - -from openlp.plugins.alerts.lib.meta import metadata -from openlp.plugins.alerts.lib.tables import * -from openlp.plugins.alerts.lib.classes import * - -def init_models(url): - engine = create_engine(url) - metadata.bind = engine - session = scoped_session(sessionmaker(autoflush=True, autocommit=False, - bind=engine)) - mapper(AlertItem, alerts_table) - return session diff --git a/openlp/plugins/alerts/lib/tables.py b/openlp/plugins/alerts/lib/tables.py deleted file mode 100644 index 0e707570d..000000000 --- a/openlp/plugins/alerts/lib/tables.py +++ /dev/null @@ -1,33 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin # -# Thompson, Jon Tibble, Carsten Tinggaard # -# --------------------------------------------------------------------------- # -# This program is free software; you can redistribute it and/or modify it # -# under the terms of the GNU General Public License as published by the Free # -# Software Foundation; version 2 of the License. # -# # -# This program is distributed in the hope that it will be useful, but WITHOUT # -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # -# more details. # -# # -# You should have received a copy of the GNU General Public License along # -# with this program; if not, write to the Free Software Foundation, Inc., 59 # -# Temple Place, Suite 330, Boston, MA 02111-1307 USA # -############################################################################### - -from sqlalchemy import Column, Table, types - -from openlp.plugins.alerts.lib.meta import metadata - -# Definition of the "alerts" table -alerts_table = Table(u'alerts', metadata, - Column(u'id', types.Integer(), primary_key=True), - Column(u'text', types.UnicodeText, nullable=False)) diff --git a/openlp/plugins/bibles/lib/models.py b/openlp/plugins/bibles/lib/models.py index d970bce08..2cd52fb0b 100644 --- a/openlp/plugins/bibles/lib/models.py +++ b/openlp/plugins/bibles/lib/models.py @@ -27,7 +27,7 @@ from sqlalchemy import Column, Table, MetaData, ForeignKey, types, \ create_engine from sqlalchemy.orm import mapper, relation, sessionmaker, scoped_session -from openlp.core.lib import BaseModel +from openlp.core.lib.db import BaseModel class BibleMeta(BaseModel): diff --git a/openlp/plugins/custom/lib/classes.py b/openlp/plugins/custom/lib/classes.py index dc6c5c1b8..6d8c623d1 100644 --- a/openlp/plugins/custom/lib/classes.py +++ b/openlp/plugins/custom/lib/classes.py @@ -23,7 +23,7 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from openlp.core.lib import BaseModel +from openlp.core.lib.db import BaseModel class CustomSlide(BaseModel): """ diff --git a/openlp/plugins/songs/forms/authorsdialog.py b/openlp/plugins/songs/forms/authorsdialog.py index 082b1133d..1a7a4ccb5 100644 --- a/openlp/plugins/songs/forms/authorsdialog.py +++ b/openlp/plugins/songs/forms/authorsdialog.py @@ -24,6 +24,7 @@ ############################################################################### from PyQt4 import QtCore, QtGui + from openlp.core.lib import translate class Ui_AuthorsDialog(object): diff --git a/openlp/plugins/songs/forms/authorsform.py b/openlp/plugins/songs/forms/authorsform.py index 4d7fcd4b6..c5d0b2fa4 100644 --- a/openlp/plugins/songs/forms/authorsform.py +++ b/openlp/plugins/songs/forms/authorsform.py @@ -28,7 +28,6 @@ from PyQt4 import QtGui, QtCore from openlp.core.lib import translate from openlp.plugins.songs.forms.authorsdialog import Ui_AuthorsDialog - class AuthorsForm(QtGui.QDialog, Ui_AuthorsDialog): """ Class to control the Maintenance of Authors Dialog diff --git a/openlp/plugins/songs/forms/editsongdialog.py b/openlp/plugins/songs/forms/editsongdialog.py index d613715dd..9c088ea30 100644 --- a/openlp/plugins/songs/forms/editsongdialog.py +++ b/openlp/plugins/songs/forms/editsongdialog.py @@ -24,9 +24,8 @@ ############################################################################### from PyQt4 import QtCore, QtGui -from openlp.core.lib import translate -from openlp.core.lib import build_icon +from openlp.core.lib import build_icon, translate class Ui_EditSongDialog(object): def setupUi(self, EditSongDialog): diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py index d23bcd298..1ae8796f5 100644 --- a/openlp/plugins/songs/forms/editsongform.py +++ b/openlp/plugins/songs/forms/editsongform.py @@ -30,7 +30,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import SongXMLBuilder, SongXMLParser, Receiver, translate from openlp.plugins.songs.forms import EditVerseForm -from openlp.plugins.songs.lib.models import Song +from openlp.plugins.songs.lib.db import Song from editsongdialog import Ui_EditSongDialog log = logging.getLogger(__name__) diff --git a/openlp/plugins/songs/forms/songbookdialog.py b/openlp/plugins/songs/forms/songbookdialog.py index 06e27d04e..578be03fc 100644 --- a/openlp/plugins/songs/forms/songbookdialog.py +++ b/openlp/plugins/songs/forms/songbookdialog.py @@ -24,6 +24,7 @@ ############################################################################### from PyQt4 import QtCore, QtGui + from openlp.core.lib import translate class Ui_SongBookDialog(object): diff --git a/openlp/plugins/songs/forms/songbookform.py b/openlp/plugins/songs/forms/songbookform.py index ad85990f0..172b74892 100644 --- a/openlp/plugins/songs/forms/songbookform.py +++ b/openlp/plugins/songs/forms/songbookform.py @@ -28,7 +28,6 @@ from PyQt4 import QtGui from openlp.core.lib import translate from openlp.plugins.songs.forms.songbookdialog import Ui_SongBookDialog - class SongBookForm(QtGui.QDialog, Ui_SongBookDialog): """ Class documentation goes here. diff --git a/openlp/plugins/songs/forms/songmaintenanceform.py b/openlp/plugins/songs/forms/songmaintenanceform.py index 34388dd62..d6ac7bf04 100644 --- a/openlp/plugins/songs/forms/songmaintenanceform.py +++ b/openlp/plugins/songs/forms/songmaintenanceform.py @@ -25,12 +25,12 @@ from PyQt4 import QtGui, QtCore -from openlp.plugins.songs.lib.classes import Author, Book, Topic +from openlp.core.lib import translate +from openlp.plugins.songs.lib.db import Author, Book, Topic from songmaintenancedialog import Ui_SongMaintenanceDialog from authorsform import AuthorsForm from topicsform import TopicsForm from songbookform import SongBookForm -from openlp.core.lib import translate class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): """ diff --git a/openlp/plugins/songs/forms/topicsdialog.py b/openlp/plugins/songs/forms/topicsdialog.py index 3ed9da3c3..9200285f7 100644 --- a/openlp/plugins/songs/forms/topicsdialog.py +++ b/openlp/plugins/songs/forms/topicsdialog.py @@ -24,6 +24,7 @@ ############################################################################### from PyQt4 import QtCore, QtGui + from openlp.core.lib import translate class Ui_TopicsDialog(object): diff --git a/openlp/plugins/songs/forms/topicsform.py b/openlp/plugins/songs/forms/topicsform.py index fc5efe38d..a78c88c5a 100644 --- a/openlp/plugins/songs/forms/topicsform.py +++ b/openlp/plugins/songs/forms/topicsform.py @@ -28,7 +28,6 @@ from PyQt4 import QtGui from openlp.core.lib import translate from openlp.plugins.songs.forms.topicsdialog import Ui_TopicsDialog - class TopicsForm(QtGui.QDialog, Ui_TopicsDialog): """ Class documentation goes here. diff --git a/openlp/plugins/songs/lib/classes.py b/openlp/plugins/songs/lib/classes.py deleted file mode 100644 index c465588a4..000000000 --- a/openlp/plugins/songs/lib/classes.py +++ /dev/null @@ -1,52 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin # -# Thompson, Jon Tibble, Carsten Tinggaard # -# --------------------------------------------------------------------------- # -# This program is free software; you can redistribute it and/or modify it # -# under the terms of the GNU General Public License as published by the Free # -# Software Foundation; version 2 of the License. # -# # -# This program is distributed in the hope that it will be useful, but WITHOUT # -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # -# more details. # -# # -# You should have received a copy of the GNU General Public License along # -# with this program; if not, write to the Free Software Foundation, Inc., 59 # -# Temple Place, Suite 330, Boston, MA 02111-1307 USA # -############################################################################### - -from openlp.core.lib import BaseModel - -class Author(BaseModel): - """ - Author model - """ - pass - -class Book(BaseModel): - """ - Book model - """ - def __repr__(self): - return u'' % ( - str(self.id), self.name, self.publisher) - -class Song(BaseModel): - """ - Song model - """ - pass - -class Topic(BaseModel): - """ - Topic model - """ - pass diff --git a/openlp/plugins/songs/lib/db.py b/openlp/plugins/songs/lib/db.py new file mode 100644 index 000000000..3c1aae7cb --- /dev/null +++ b/openlp/plugins/songs/lib/db.py @@ -0,0 +1,150 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2010 Raoul Snyman # +# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # +# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin # +# Thompson, Jon Tibble, Carsten Tinggaard # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### +""" +The :mod:`db` module provides the database and schema that is the backend for +the Songs plugin +""" + +from sqlalchemy import Column, ForeignKey, Index, Table, types +from sqlalchemy.orm import mapper, relation + +from openlp.core.lib.db import BaseModel, init_db + +class Author(BaseModel): + """ + Author model + """ + pass + +class Book(BaseModel): + """ + Book model + """ + def __repr__(self): + return u'' % ( + str(self.id), self.name, self.publisher) + +class Song(BaseModel): + """ + Song model + """ + pass + +class Topic(BaseModel): + """ + Topic model + """ + pass + +def init_schema(url): + """ + Setup the songs database connection and initialise the database schema + + ``url`` + The database to setup + """ + session, metadata = init_db(url, auto_flush=False) + + # Definition of the "authors" table + authors_table = Table(u'authors', metadata, + Column(u'id', types.Integer, primary_key=True), + Column(u'first_name', types.Unicode(128)), + Column(u'last_name', types.Unicode(128)), + Column(u'display_name', types.Unicode(255), nullable=False) + ) + + # Definition of the "song_books" table + song_books_table = Table(u'song_books', metadata, + Column(u'id', types.Integer, primary_key=True), + Column(u'name', types.Unicode(128), nullable=False), + Column(u'publisher', types.Unicode(128)) + ) + + # Definition of the "songs" table + songs_table = Table(u'songs', metadata, + Column(u'id', types.Integer, primary_key=True), + Column(u'song_book_id', types.Integer, + ForeignKey(u'song_books.id'), default=0), + Column(u'title', types.Unicode(255), nullable=False), + Column(u'lyrics', types.UnicodeText, nullable=False), + Column(u'verse_order', types.Unicode(128)), + Column(u'copyright', types.Unicode(255)), + Column(u'comments', types.UnicodeText), + Column(u'ccli_number', types.Unicode(64)), + Column(u'song_number', types.Unicode(64)), + Column(u'theme_name', types.Unicode(128)), + Column(u'search_title', types.Unicode(255), index=True, nullable=False), + Column(u'search_lyrics', types.UnicodeText, index=True, nullable=False) + ) + + # Definition of the "topics" table + topics_table = Table(u'topics', metadata, + Column(u'id', types.Integer, primary_key=True), + Column(u'name', types.Unicode(128), nullable=False) + ) + + # Definition of the "authors_songs" table + authors_songs_table = Table(u'authors_songs', metadata, + Column(u'author_id', types.Integer, + ForeignKey(u'authors.id'), primary_key=True), + Column(u'song_id', types.Integer, + ForeignKey(u'songs.id'), primary_key=True) + ) + + # Definition of the "songs_topics" table + songs_topics_table = Table(u'songs_topics', metadata, + Column(u'song_id', types.Integer, + ForeignKey(u'songs.id'), primary_key=True), + Column(u'topic_id', types.Integer, + ForeignKey(u'topics.id'), primary_key=True) + ) + + # Define table indexes + Index(u'authors_id', authors_table.c.id) + Index(u'authors_display_name_id', authors_table.c.display_name, + authors_table.c.id) + Index(u'song_books_id', song_books_table.c.id) + Index(u'songs_id', songs_table.c.id) + Index(u'topics_id', topics_table.c.id) + Index(u'authors_songs_author', authors_songs_table.c.author_id, + authors_songs_table.c.song_id) + Index(u'authors_songs_song', authors_songs_table.c.song_id, + authors_songs_table.c.author_id) + Index(u'topics_song_topic', songs_topics_table.c.topic_id, + songs_topics_table.c.song_id) + Index(u'topics_song_song', songs_topics_table.c.song_id, + songs_topics_table.c.topic_id) + + mapper(Author, authors_table) + mapper(Book, song_books_table) + mapper(Song, songs_table, + properties={'authors': relation(Author, backref='songs', + secondary=authors_songs_table), + 'book': relation(Book, backref='songs'), + 'topics': relation(Topic, backref='songs', + secondary=songs_topics_table)}) + mapper(Topic, topics_table) + + return session, metadata diff --git a/openlp/plugins/songs/lib/manager.py b/openlp/plugins/songs/lib/manager.py index 0b833fb0b..0194cea5b 100644 --- a/openlp/plugins/songs/lib/manager.py +++ b/openlp/plugins/songs/lib/manager.py @@ -29,8 +29,7 @@ from PyQt4 import QtCore from sqlalchemy.exceptions import InvalidRequestError from openlp.core.utils import AppLocation -from openlp.plugins.songs.lib.models import init_models, metadata, Song, \ - Author, Topic, Book +from openlp.plugins.songs.lib.db import init_schema, Song, Author, Topic, Book #from openlp.plugins.songs.lib import OpenLyricsSong, OpenSongSong, CCLISong, \ # CSVSong @@ -111,8 +110,8 @@ class SongManager(object): u'db hostname', QtCore.QVariant(u'')).toString()), unicode(settings.value( u'db database', QtCore.QVariant(u'')).toString())) - self.session = init_models(self.db_url) - metadata.create_all(checkfirst=True) + self.session, self.metadata = init_schema(self.db_url) + self.metadata.create_all(checkfirst=True) settings.endGroup() log.debug(u'Song Initialised') diff --git a/openlp/plugins/songs/lib/meta.py b/openlp/plugins/songs/lib/meta.py deleted file mode 100644 index affa31969..000000000 --- a/openlp/plugins/songs/lib/meta.py +++ /dev/null @@ -1,38 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin # -# Thompson, Jon Tibble, Carsten Tinggaard # -# --------------------------------------------------------------------------- # -# This program is free software; you can redistribute it and/or modify it # -# under the terms of the GNU General Public License as published by the Free # -# Software Foundation; version 2 of the License. # -# # -# This program is distributed in the hope that it will be useful, but WITHOUT # -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # -# more details. # -# # -# You should have received a copy of the GNU General Public License along # -# with this program; if not, write to the Free Software Foundation, Inc., 59 # -# Temple Place, Suite 330, Boston, MA 02111-1307 USA # -############################################################################### - -from sqlalchemy import MetaData - -__all__ = ['session', 'metadata', 'engine'] - -# SQLAlchemy database engine. Updated by model.init_model() -engine = None - -# SQLAlchemy session manager. Updated by model.init_model() -session = None - -# Global metadata. If you have multiple databases with overlapping table -# names, you'll need a metadata for each database -metadata = MetaData() diff --git a/openlp/plugins/songs/lib/models.py b/openlp/plugins/songs/lib/models.py deleted file mode 100644 index 272981d20..000000000 --- a/openlp/plugins/songs/lib/models.py +++ /dev/null @@ -1,48 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin # -# Thompson, Jon Tibble, Carsten Tinggaard # -# --------------------------------------------------------------------------- # -# This program is free software; you can redistribute it and/or modify it # -# under the terms of the GNU General Public License as published by the Free # -# Software Foundation; version 2 of the License. # -# # -# This program is distributed in the hope that it will be useful, but WITHOUT # -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # -# more details. # -# # -# You should have received a copy of the GNU General Public License along # -# with this program; if not, write to the Free Software Foundation, Inc., 59 # -# Temple Place, Suite 330, Boston, MA 02111-1307 USA # -############################################################################### - -from sqlalchemy import create_engine -from sqlalchemy.orm import scoped_session, sessionmaker, mapper, relation - -from openlp.plugins.songs.lib.meta import metadata -from openlp.plugins.songs.lib.tables import * -from openlp.plugins.songs.lib.classes import * - -def init_models(url): - engine = create_engine(url) - metadata.bind = engine - session = scoped_session(sessionmaker(autoflush=False, autocommit=False, - bind=engine)) - mapper(Author, authors_table) - mapper(Book, song_books_table) - mapper(Song, songs_table, - properties={'authors': relation(Author, backref='songs', - secondary=authors_songs_table), - 'book': relation(Book, backref='songs'), - 'topics': relation(Topic, backref='songs', - secondary=songs_topics_table)}) - mapper(Topic, topics_table) - return session - diff --git a/openlp/plugins/songs/lib/songimport.py b/openlp/plugins/songs/lib/songimport.py index fa016729d..f2222e09b 100644 --- a/openlp/plugins/songs/lib/songimport.py +++ b/openlp/plugins/songs/lib/songimport.py @@ -28,7 +28,7 @@ import string from PyQt4 import QtGui from openlp.core.lib import SongXMLBuilder -from openlp.plugins.songs.lib.models import Song, Author, Topic, Book +from openlp.plugins.songs.lib.db import Song, Author, Topic, Book from openlp.plugins.songs.forms import VerseType class SongImport(object): diff --git a/openlp/plugins/songs/lib/tables.py b/openlp/plugins/songs/lib/tables.py deleted file mode 100644 index 24137d7b1..000000000 --- a/openlp/plugins/songs/lib/tables.py +++ /dev/null @@ -1,99 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin # -# Thompson, Jon Tibble, Carsten Tinggaard # -# --------------------------------------------------------------------------- # -# This program is free software; you can redistribute it and/or modify it # -# under the terms of the GNU General Public License as published by the Free # -# Software Foundation; version 2 of the License. # -# # -# This program is distributed in the hope that it will be useful, but WITHOUT # -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # -# more details. # -# # -# You should have received a copy of the GNU General Public License along # -# with this program; if not, write to the Free Software Foundation, Inc., 59 # -# Temple Place, Suite 330, Boston, MA 02111-1307 USA # -############################################################################### - -from sqlalchemy import * -from sqlalchemy import Column, Table, ForeignKey, types - -from openlp.plugins.songs.lib.meta import metadata - -# Definition of the "authors" table -authors_table = Table(u'authors', metadata, - Column(u'id', types.Integer, primary_key=True), - Column(u'first_name', types.Unicode(128)), - Column(u'last_name', types.Unicode(128)), - Column(u'display_name', types.Unicode(255), nullable=False) -) - -# Definition of the "song_books" table -song_books_table = Table(u'song_books', metadata, - Column(u'id', types.Integer, primary_key=True), - Column(u'name', types.Unicode(128), nullable=False), - Column(u'publisher', types.Unicode(128)) -) - -# Definition of the "songs" table -songs_table = Table(u'songs', metadata, - Column(u'id', types.Integer, primary_key=True), - Column(u'song_book_id', types.Integer, - ForeignKey(u'song_books.id'), default=0), - Column(u'title', types.Unicode(255), nullable=False), - Column(u'lyrics', types.UnicodeText, nullable=False), - Column(u'verse_order', types.Unicode(128)), - Column(u'copyright', types.Unicode(255)), - Column(u'comments', types.UnicodeText), - Column(u'ccli_number', types.Unicode(64)), - Column(u'song_number', types.Unicode(64)), - Column(u'theme_name', types.Unicode(128)), - Column(u'search_title', types.Unicode(255), index=True, nullable=False), - Column(u'search_lyrics', types.UnicodeText, index=True, nullable=False) -) - -# Definition of the "topics" table -topics_table = Table(u'topics', metadata, - Column(u'id', types.Integer, primary_key=True), - Column(u'name', types.Unicode(128), nullable=False) -) - -# Definition of the "authors_songs" table -authors_songs_table = Table(u'authors_songs', metadata, - Column(u'author_id', types.Integer, - ForeignKey(u'authors.id'), primary_key=True), - Column(u'song_id', types.Integer, - ForeignKey(u'songs.id'), primary_key=True) -) - -# Definition of the "songs_topics" table -songs_topics_table = Table(u'songs_topics', metadata, - Column(u'song_id', types.Integer, - ForeignKey(u'songs.id'), primary_key=True), - Column(u'topic_id', types.Integer, - ForeignKey(u'topics.id'), primary_key=True) -) - -# Define table indexes -Index(u'authors_id', authors_table.c.id) -Index(u'authors_display_name_id', authors_table.c.display_name, - authors_table.c.id) -Index(u'song_books_id', song_books_table.c.id) -Index(u'songs_id', songs_table.c.id) -Index(u'topics_id', topics_table.c.id) -Index(u'authors_songs_author', authors_songs_table.c.author_id, - authors_songs_table.c.song_id) -Index(u'authors_songs_song', authors_songs_table.c.song_id, - authors_songs_table.c.author_id) -Index(u'topics_song_topic', songs_topics_table.c.topic_id, - songs_topics_table.c.song_id) -Index(u'topics_song_song', songs_topics_table.c.song_id, - songs_topics_table.c.topic_id) diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py index 993b18bb9..09485082c 100644 --- a/openlp/plugins/songs/songsplugin.py +++ b/openlp/plugins/songs/songsplugin.py @@ -34,7 +34,6 @@ from openlp.plugins.songs.lib import SongManager, SongMediaItem, SongsTab, \ log = logging.getLogger(__name__) - class SongsPlugin(Plugin): """ This is the number 1 plugin, if importance were placed on any diff --git a/openlp/plugins/songusage/lib/classes.py b/openlp/plugins/songusage/lib/classes.py index 298380f58..885d87faf 100644 --- a/openlp/plugins/songusage/lib/classes.py +++ b/openlp/plugins/songusage/lib/classes.py @@ -23,7 +23,7 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from openlp.core.lib import BaseModel +from openlp.core.lib.db import BaseModel class SongUsageItem(BaseModel): """ From 5f2042168da20d5ebe51e57da091aa5142af761c Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Sat, 12 Jun 2010 03:14:18 +0100 Subject: [PATCH 02/49] RFC: Cleanup DB metadata for RFC --- openlp/plugins/alerts/lib/db.py | 3 ++- openlp/plugins/alerts/lib/manager.py | 3 +-- openlp/plugins/songs/lib/db.py | 3 ++- openlp/plugins/songs/lib/manager.py | 3 +-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/openlp/plugins/alerts/lib/db.py b/openlp/plugins/alerts/lib/db.py index 3656d41b8..5e4b1a99a 100644 --- a/openlp/plugins/alerts/lib/db.py +++ b/openlp/plugins/alerts/lib/db.py @@ -53,4 +53,5 @@ def init_schema(url): mapper(AlertItem, alerts_table) - return session, metadata + metadata.create_all(checkfirst=True) + return session diff --git a/openlp/plugins/alerts/lib/manager.py b/openlp/plugins/alerts/lib/manager.py index 814e3dca6..7b5cf2da0 100644 --- a/openlp/plugins/alerts/lib/manager.py +++ b/openlp/plugins/alerts/lib/manager.py @@ -61,8 +61,7 @@ class DBManager(object): unicode(settings.value(u'db hostname').toString()), unicode(settings.value(u'db database').toString())) settings.endGroup() - self.session, self.metadata = init_schema(self.db_url) - self.metadata.create_all(checkfirst=True) + self.session = init_schema(self.db_url) log.debug(u'Alerts Initialised') def get_all_alerts(self): diff --git a/openlp/plugins/songs/lib/db.py b/openlp/plugins/songs/lib/db.py index 3c1aae7cb..655043144 100644 --- a/openlp/plugins/songs/lib/db.py +++ b/openlp/plugins/songs/lib/db.py @@ -147,4 +147,5 @@ def init_schema(url): secondary=songs_topics_table)}) mapper(Topic, topics_table) - return session, metadata + metadata.create_all(checkfirst=True) + return session diff --git a/openlp/plugins/songs/lib/manager.py b/openlp/plugins/songs/lib/manager.py index 0194cea5b..8e0a79ef7 100644 --- a/openlp/plugins/songs/lib/manager.py +++ b/openlp/plugins/songs/lib/manager.py @@ -110,8 +110,7 @@ class SongManager(object): u'db hostname', QtCore.QVariant(u'')).toString()), unicode(settings.value( u'db database', QtCore.QVariant(u'')).toString())) - self.session, self.metadata = init_schema(self.db_url) - self.metadata.create_all(checkfirst=True) + self.session = init_schema(self.db_url) settings.endGroup() log.debug(u'Song Initialised') From 54aa8958fee401780392f77ba1277e148533d436 Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Sun, 13 Jun 2010 00:00:14 +0100 Subject: [PATCH 03/49] RFC PT2: Refactor Manager --- openlp/core/lib/db.py | 121 ++++++++++++ openlp/plugins/alerts/alertsplugin.py | 6 +- openlp/plugins/alerts/forms/alertform.py | 11 +- openlp/plugins/alerts/lib/__init__.py | 1 - openlp/plugins/alerts/lib/manager.py | 112 ----------- openlp/plugins/songs/forms/editsongform.py | 24 +-- .../songs/forms/songmaintenanceform.py | 48 ++--- openlp/plugins/songs/lib/manager.py | 185 +----------------- openlp/plugins/songs/lib/mediaitem.py | 7 +- openlp/plugins/songs/lib/songimport.py | 8 +- openlp/plugins/songs/songsplugin.py | 4 +- 11 files changed, 176 insertions(+), 351 deletions(-) delete mode 100644 openlp/plugins/alerts/lib/manager.py diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index 4762da157..323b48e39 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -25,10 +25,17 @@ """ The :mod:`db` module provides the core database functionality for OpenLP """ +import logging +from PyQt4 import QtCore from sqlalchemy import create_engine, MetaData +from sqlalchemy.exceptions import InvalidRequestError from sqlalchemy.orm import scoped_session, sessionmaker +from openlp.core.utils import AppLocation + +log = logging.getLogger(__name__) + def init_db(url, auto_flush=True, auto_commit=False): """ Initialise and return the session and metadata for a database @@ -62,3 +69,117 @@ class BaseModel(object): for key in kwargs: me.__setattr__(key, kwargs[key]) return me + +class Manager(object): + """ + Provide generic object persistence management + """ + def __init__(self, plugin_name, init_schema): + """ + Runs the initialisation process that includes creating the connection + to the database and the tables if they don't exist. + + ``plugin_name`` + The name to setup paths and settings section names + """ + settings = QtCore.QSettings() + settings.beginGroup(plugin_name) + self.db_url = u'' + db_type = unicode( + settings.value(u'db type', QtCore.QVariant(u'sqlite')).toString()) + if db_type == u'sqlite': + self.db_url = u'sqlite:///%s/%s.sqlite' % ( + AppLocation.get_section_data_path(plugin_name), plugin_name) + else: + self.db_url = u'%s://%s:%s@%s/%s' % (db_type, + unicode(settings.value(u'db username').toString()), + unicode(settings.value(u'db password').toString()), + unicode(settings.value(u'db hostname').toString()), + unicode(settings.value(u'db database').toString())) + settings.endGroup() + self.session = init_schema(self.db_url) + + def insert_object(self, object_instance): + """ + Save an object to the database + + ``object_instance`` + The object to save + """ + try: + self.session.add(object_instance) + self.session.commit() + return True + except InvalidRequestError: + self.session.rollback() + log.exception(u'Object save failed') + return False + + def get_object(self, object_class, id=None): + """ + Return the details of an object + + ``object_class`` + The type of object to return + + ``id`` + The unique reference for the class instance to return + """ + if not id: + return object_class() + else: + return self.session.query(object_class).get(id) + + def get_all_objects(self, object_class, order_by_ref=None): + """ + Returns all the objects from the database + + ``object_class`` + The type of object to return + + ``order_by_ref`` + Any parameters to order the returned objects by. Defaults to None. + """ + if order_by_ref: + return self.session.query(object_class).order_by(order_by_ref).all() + return self.session.query(object_class).all() + + def delete_object(self, object_class, id): + """ + Delete an object from the database + + ``object_class`` + The type of object to delete + + ``id`` + The unique reference for the class instance to be deleted + """ + if id != 0: + object = self.get_object(object_class, id) + try: + self.session.delete(object) + self.session.commit() + return True + except InvalidRequestError: + self.session.rollback() + log.exception(u'Failed to delete object') + return False + else: + return True + + def delete_all_objects(self, object_class): + """ + Delete all object records + + ``object_class`` + The type of object to delete + """ + try: + self.session.query(object_class).delete(synchronize_session=False) + self.session.commit() + return True + except InvalidRequestError: + self.session.rollback() + log.exception(u'Failed to delete all %s records', + object_class.__name__) + return False diff --git a/openlp/plugins/alerts/alertsplugin.py b/openlp/plugins/alerts/alertsplugin.py index 7474a0564..3c14e23b1 100644 --- a/openlp/plugins/alerts/alertsplugin.py +++ b/openlp/plugins/alerts/alertsplugin.py @@ -28,7 +28,9 @@ import logging from PyQt4 import QtCore, QtGui from openlp.core.lib import Plugin, build_icon, PluginStatus, translate -from openlp.plugins.alerts.lib import AlertsManager, AlertsTab, DBManager +from openlp.core.lib.db import Manager +from openlp.plugins.alerts.lib import AlertsManager, AlertsTab +from openlp.plugins.alerts.lib.db import init_schema from openlp.plugins.alerts.forms import AlertForm log = logging.getLogger(__name__) @@ -41,7 +43,7 @@ class alertsPlugin(Plugin): self.weight = -3 self.icon = build_icon(u':/media/media_image.png') self.alertsmanager = AlertsManager(self) - self.manager = DBManager() + self.manager = Manager(u'alerts', init_schema) self.alertForm = AlertForm(self.manager, self) self.status = PluginStatus.Active diff --git a/openlp/plugins/alerts/forms/alertform.py b/openlp/plugins/alerts/forms/alertform.py index e8fc0d2fe..b00ba0f05 100644 --- a/openlp/plugins/alerts/forms/alertform.py +++ b/openlp/plugins/alerts/forms/alertform.py @@ -62,7 +62,7 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): def loadList(self): self.AlertListWidget.clear() - alerts = self.manager.get_all_alerts() + alerts = self.manager.get_all_objects(AlertItem, AlertItem.text) for alert in alerts: item_name = QtGui.QListWidgetItem(alert.text) item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(alert.id)) @@ -82,7 +82,7 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): item = self.AlertListWidget.currentItem() if item: item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] - self.parent.manager.delete_alert(item_id) + self.manager.delete_object(AlertItem, item_id) row = self.AlertListWidget.row(item) self.AlertListWidget.takeItem(row) self.AlertTextEdit.setText(u'') @@ -98,15 +98,15 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): else: alert = AlertItem() alert.text = unicode(self.AlertTextEdit.text()) - self.manager.save_alert(alert) + self.manager.insert_object(alert) self.AlertTextEdit.setText(u'') self.loadList() def onSaveClick(self): if self.item_id: - alert = self.manager.get_alert(self.item_id) + alert = self.manager.get_object(AlertItem, self.item_id) alert.text = unicode(self.AlertTextEdit.text()) - self.manager.save_alert(alert) + self.manager.insert_object(alert) self.item_id = None self.loadList() else: @@ -148,4 +148,3 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): self.parent.alertsmanager.displayAlert(text) return True return False - diff --git a/openlp/plugins/alerts/lib/__init__.py b/openlp/plugins/alerts/lib/__init__.py index 81a2641f6..2c22e5375 100644 --- a/openlp/plugins/alerts/lib/__init__.py +++ b/openlp/plugins/alerts/lib/__init__.py @@ -25,4 +25,3 @@ from alertsmanager import AlertsManager from alertstab import AlertsTab -from manager import DBManager diff --git a/openlp/plugins/alerts/lib/manager.py b/openlp/plugins/alerts/lib/manager.py deleted file mode 100644 index 7b5cf2da0..000000000 --- a/openlp/plugins/alerts/lib/manager.py +++ /dev/null @@ -1,112 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin # -# Thompson, Jon Tibble, Carsten Tinggaard # -# --------------------------------------------------------------------------- # -# This program is free software; you can redistribute it and/or modify it # -# under the terms of the GNU General Public License as published by the Free # -# Software Foundation; version 2 of the License. # -# # -# This program is distributed in the hope that it will be useful, but WITHOUT # -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # -# more details. # -# # -# You should have received a copy of the GNU General Public License along # -# with this program; if not, write to the Free Software Foundation, Inc., 59 # -# Temple Place, Suite 330, Boston, MA 02111-1307 USA # -############################################################################### - -import logging - -from PyQt4 import QtCore -from sqlalchemy.exceptions import InvalidRequestError - -from openlp.core.utils import AppLocation -from openlp.plugins.alerts.lib.db import init_schema, AlertItem - -log = logging.getLogger(__name__) - -class DBManager(object): - """ - The Song Manager provides a central location for all database code. This - class takes care of connecting to the database and running all the queries. - """ - log.info(u'Alerts DB loaded') - - def __init__(self): - """ - Creates the connection to the database, and creates the tables if they - don't exist. - """ - log.debug(u'Alerts Initialising') - settings = QtCore.QSettings() - settings.beginGroup(u'alerts') - self.db_url = u'' - db_type = unicode( - settings.value(u'db type', QtCore.QVariant(u'sqlite')).toString()) - if db_type == u'sqlite': - self.db_url = u'sqlite:///%s/alerts.sqlite' % \ - AppLocation.get_section_data_path(u'alerts') - else: - self.db_url = u'%s://%s:%s@%s/%s' % (db_type, - unicode(settings.value(u'db username').toString()), - unicode(settings.value(u'db password').toString()), - unicode(settings.value(u'db hostname').toString()), - unicode(settings.value(u'db database').toString())) - settings.endGroup() - self.session = init_schema(self.db_url) - log.debug(u'Alerts Initialised') - - def get_all_alerts(self): - """ - Returns the details of a Alert Show - """ - return self.session.query(AlertItem).order_by(AlertItem.text).all() - - def save_alert(self, alert_item): - """ - Saves a Alert show to the database - """ - log.debug(u'Alert added') - try: - self.session.add(alert_item) - self.session.commit() - log.debug(u'Alert saved') - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'Alert save failed') - return False - - def get_alert(self, id=None): - """ - Returns the details of a Alert - """ - if id is None: - return AlertItem() - else: - return self.session.query(AlertItem).get(id) - - def delete_alert(self, id): - """ - Delete a Alert show - """ - if id != 0: - alert_item = self.get_alert(id) - try: - self.session.delete(alert_item) - self.session.commit() - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'Alert deleton failed') - return False - else: - return True diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py index 1ae8796f5..ecee8975d 100644 --- a/openlp/plugins/songs/forms/editsongform.py +++ b/openlp/plugins/songs/forms/editsongform.py @@ -30,7 +30,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import SongXMLBuilder, SongXMLParser, Receiver, translate from openlp.plugins.songs.forms import EditVerseForm -from openlp.plugins.songs.lib.db import Song +from openlp.plugins.songs.lib.db import Book, Song, Author, Topic from editsongdialog import Ui_EditSongDialog log = logging.getLogger(__name__) @@ -125,7 +125,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.TopicRemoveButton.setEnabled(False) def loadAuthors(self): - authors = self.songmanager.get_authors() + authors = self.songmanager.get_all_objects(Author, Author.display_name) authorsCompleter = QtGui.QCompleter( [author.display_name for author in authors], self.AuthorsSelectionComboItem) @@ -139,7 +139,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): row, QtCore.QVariant(author.id)) def loadTopics(self): - topics = self.songmanager.get_topics() + topics = self.songmanager.get_all_objects(Topic, Topic.name) topicsCompleter = QtGui.QCompleter( [topic.name for topic in topics], self.SongTopicCombo) topicsCompleter.setCaseSensitivity(QtCore.Qt.CaseInsensitive) @@ -151,7 +151,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.SongTopicCombo.setItemData(row, QtCore.QVariant(topic.id)) def loadBooks(self): - books = self.songmanager.get_books() + books = self.songmanager.get_all_objects(Book, Book.name) booksCompleter = QtGui.QCompleter( [book.name for book in books], self.SongbookCombo) booksCompleter.setCaseSensitivity(QtCore.Qt.CaseInsensitive) @@ -201,11 +201,12 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.loadAuthors() self.loadTopics() self.loadBooks() - self.song = self.songmanager.get_song(id) + self.song = self.songmanager.get_object(Song, id) self.TitleEditItem.setText(self.song.title) title = self.song.search_title.split(u'@') if self.song.song_book_id != 0: - book_name = self.songmanager.get_book(self.song.song_book_id) + book_name = self.songmanager.get_object(Book, + self.song.song_book_id) id = self.SongbookCombo.findText( unicode(book_name.name), QtCore.Qt.MatchExactly) if id == -1: @@ -301,7 +302,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): item = int(self.AuthorsSelectionComboItem.currentIndex()) if item > -1: item_id = (self.AuthorsSelectionComboItem.itemData(item)).toInt()[0] - author = self.songmanager.get_author(item_id) + author = self.songmanager.get_object(Author, item_id) self.song.authors.append(author) author_item = QtGui.QListWidgetItem(unicode(author.display_name)) author_item.setData(QtCore.Qt.UserRole, QtCore.QVariant(author.id)) @@ -315,7 +316,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.AuthorRemoveButton.setEnabled(False) item = self.AuthorsListView.currentItem() author_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] - author = self.songmanager.get_author(author_id) + author = self.songmanager.get_object(Author, author_id) self.song.authors.remove(author) row = self.AuthorsListView.row(item) self.AuthorsListView.takeItem(row) @@ -324,7 +325,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): item = int(self.SongTopicCombo.currentIndex()) if item > -1: item_id = (self.SongTopicCombo.itemData(item)).toInt()[0] - topic = self.songmanager.get_topic(item_id) + topic = self.songmanager.get_object(Topic, item_id) self.song.topics.append(topic) topic_item = QtGui.QListWidgetItem(unicode(topic.name)) topic_item.setData(QtCore.Qt.UserRole, QtCore.QVariant(topic.id)) @@ -337,7 +338,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.TopicRemoveButton.setEnabled(False) item = self.TopicsListView.currentItem() topic_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] - topic = self.songmanager.get_topic(topic_id) + topic = self.songmanager.get_object(Topic, topic_id) self.song.topics.remove(topic) row = self.TopicsListView.row(item) self.TopicsListView.takeItem(row) @@ -550,7 +551,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.song.ccli_number = unicode(self.CCLNumberEdit.text()) self.processLyrics() self.processTitle() - self.songmanager.save_song(self.song) + self.songmanager.insert_object(self.song) return True def processLyrics(self): @@ -596,4 +597,3 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.song.search_title = self.song.search_title.replace(u'{', u'') self.song.search_title = self.song.search_title.replace(u'}', u'') self.song.search_title = self.song.search_title.replace(u'?', u'') - diff --git a/openlp/plugins/songs/forms/songmaintenanceform.py b/openlp/plugins/songs/forms/songmaintenanceform.py index d6ac7bf04..c0134f100 100644 --- a/openlp/plugins/songs/forms/songmaintenanceform.py +++ b/openlp/plugins/songs/forms/songmaintenanceform.py @@ -26,11 +26,9 @@ from PyQt4 import QtGui, QtCore from openlp.core.lib import translate +from openlp.plugins.songs.forms import AuthorsForm, TopicsForm, SongBookForm from openlp.plugins.songs.lib.db import Author, Book, Topic from songmaintenancedialog import Ui_SongMaintenanceDialog -from authorsform import AuthorsForm -from topicsform import TopicsForm -from songbookform import SongBookForm class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): """ @@ -81,17 +79,17 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): else: return -1 - def _deleteItem(self, list_widget, get_func, del_func, reset_func, - dlg_title, del_text, err_text, sel_text): + def _deleteItem(self, item_class, list_widget, reset_func, dlg_title, + del_text, err_text, sel_text): item_id = self._getCurrentItemId(list_widget) if item_id != -1: - item = get_func(item_id) + item = self.songmanager.get_object(item_class, item_id) if item and len(item.songs) == 0: if QtGui.QMessageBox.warning(self, dlg_title, del_text, QtGui.QMessageBox.StandardButtons( QtGui.QMessageBox.No | QtGui.QMessageBox.Yes) ) == QtGui.QMessageBox.Yes: - del_func(item.id) + self.songmanager.delete_object(item_class, item.id) reset_func() else: QtGui.QMessageBox.critical(self, dlg_title, err_text) @@ -100,7 +98,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): def resetAuthors(self): self.AuthorsListWidget.clear() - authors = self.songmanager.get_authors() + authors = self.songmanager.get_all_objects(Author, Author.display_name) for author in authors: if author.display_name: author_name = QtGui.QListWidgetItem(author.display_name) @@ -112,7 +110,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): def resetTopics(self): self.TopicsListWidget.clear() - topics = self.songmanager.get_topics() + topics = self.songmanager.get_all_objects(Topic, Topic.name) for topic in topics: topic_name = QtGui.QListWidgetItem(topic.name) topic_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(topic.id)) @@ -120,7 +118,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): def resetBooks(self): self.BooksListWidget.clear() - books = self.songmanager.get_books() + books = self.songmanager.get_all_objects(Book, Book.name) for book in books: book_name = QtGui.QListWidgetItem(book.name) book_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(book.id)) @@ -133,7 +131,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): first_name=unicode(self.authorform.FirstNameEdit.text()), last_name=unicode(self.authorform.LastNameEdit.text()), display_name=unicode(self.authorform.DisplayEdit.text())) - if self.songmanager.save_author(author): + if self.songmanager.insert_object(author): self.resetAuthors() else: QtGui.QMessageBox.critical( @@ -145,7 +143,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): def onTopicAddButtonClick(self): if self.topicform.exec_(): topic = Topic.populate(name=unicode(self.topicform.NameEdit.text())) - if self.songmanager.save_topic(topic): + if self.songmanager.insert_object(topic): self.resetTopics() else: QtGui.QMessageBox.critical( @@ -159,7 +157,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): book = Book.populate( name=unicode(self.bookform.NameEdit.text()), publisher=unicode(self.bookform.PublisherEdit.text())) - if self.songmanager.save_book(book): + if self.songmanager.insert_object(book): self.resetBooks() else: QtGui.QMessageBox.critical( @@ -171,7 +169,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): def onAuthorEditButtonClick(self): author_id = self._getCurrentItemId(self.AuthorsListWidget) if author_id != -1: - author = self.songmanager.get_author(author_id) + author = self.songmanager.get_object(Author, author_id) self.authorform.setAutoDisplayName(False) self.authorform.FirstNameEdit.setText(author.first_name) self.authorform.LastNameEdit.setText(author.last_name) @@ -182,7 +180,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): author.last_name = unicode(self.authorform.LastNameEdit.text()) author.display_name = unicode( self.authorform.DisplayEdit.text()) - if self.songmanager.save_author(author): + if self.songmanager.insert_object(author): self.resetAuthors() else: QtGui.QMessageBox.critical( @@ -194,11 +192,11 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): def onTopicEditButtonClick(self): topic_id = self._getCurrentItemId(self.TopicsListWidget) if topic_id != -1: - topic = self.songmanager.get_topic(topic_id) + topic = self.songmanager.get_object(Topic, topic_id) self.topicform.NameEdit.setText(topic.name) if self.topicform.exec_(False): topic.name = unicode(self.topicform.NameEdit.text()) - if self.songmanager.save_topic(topic): + if self.songmanager.insert_object(topic): self.resetTopics() else: QtGui.QMessageBox.critical( @@ -210,13 +208,13 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): def onBookEditButtonClick(self): book_id = self._getCurrentItemId(self.BooksListWidget) if book_id != -1: - book = self.songmanager.get_book(book_id) + book = self.songmanager.get_object(Book, book_id) self.bookform.NameEdit.setText(book.name) self.bookform.PublisherEdit.setText(book.publisher) if self.bookform.exec_(False): book.name = unicode(self.bookform.NameEdit.text()) book.publisher = unicode(self.bookform.PublisherEdit.text()) - if self.songmanager.save_book(book): + if self.songmanager.insert_object(book): self.resetBooks() else: QtGui.QMessageBox.critical( @@ -229,9 +227,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): """ Delete the author if the author is not attached to any songs """ - self._deleteItem( - self.AuthorsListWidget, self.songmanager.get_author, - self.songmanager.delete_author, self.resetAuthors, + self._deleteItem(Author, self.AuthorsListWidget, self.resetAuthors, translate(u'SongsPlugin.SongMaintenanceForm', u'Delete Author'), translate(u'SongsPlugin.SongMaintenanceForm', u'Are you sure you want to delete the selected author?'), @@ -245,9 +241,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): """ Delete the Book is the Book is not attached to any songs """ - self._deleteItem( - self.TopicsListWidget, self.songmanager.get_topic, - self.songmanager.delete_topic, self.resetTopics, + self._deleteItem(Topic, self.TopicsListWidget, self.resetTopics, translate(u'SongsPlugin.SongMaintenanceForm', u'Delete Topic'), translate(u'SongsPlugin.SongMaintenanceForm', u'Are you sure you want to delete the selected topic?'), @@ -261,9 +255,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): """ Delete the Book is the Book is not attached to any songs """ - self._deleteItem( - self.BooksListWidget, self.songmanager.get_book, - self.songmanager.delete_book, self.resetBooks, + self._deleteItem(Book, self.BooksListWidget, self.resetBooks, translate(u'SongsPlugin.SongMaintenanceForm', u'Delete Book'), translate(u'SongsPlugin.SongMaintenanceForm', u'Are you sure you want to delete the selected book?'), diff --git a/openlp/plugins/songs/lib/manager.py b/openlp/plugins/songs/lib/manager.py index 8e0a79ef7..6cd9a90ad 100644 --- a/openlp/plugins/songs/lib/manager.py +++ b/openlp/plugins/songs/lib/manager.py @@ -25,10 +25,7 @@ import logging -from PyQt4 import QtCore -from sqlalchemy.exceptions import InvalidRequestError - -from openlp.core.utils import AppLocation +from openlp.core.lib.db import Manager from openlp.plugins.songs.lib.db import init_schema, Song, Author, Topic, Book #from openlp.plugins.songs.lib import OpenLyricsSong, OpenSongSong, CCLISong, \ # CSVSong @@ -79,7 +76,7 @@ class SongFormat(object): ] -class SongManager(object): +class SongManager(Manager): """ The Song Manager provides a central location for all database code. This class takes care of connecting to the database and running all the queries. @@ -92,34 +89,9 @@ class SongManager(object): don't exist. """ log.debug(u'Song Initialising') - settings = QtCore.QSettings() - settings.beginGroup(u'songs') - self.db_url = u'' - db_type = unicode(settings.value(u'songs/db type', - QtCore.QVariant(u'sqlite')).toString()) - if db_type == u'sqlite': - self.db_url = u'sqlite:///%s/songs.sqlite' % \ - AppLocation.get_section_data_path(u'songs') - else: - self.db_url = u'%s://%s:%s@%s/%s' % (db_type, - unicode(settings.value( - u'db username', QtCore.QVariant(u'')).toString()), - unicode(settings.value( - u'db password', QtCore.QVariant(u'')).toString()), - unicode(settings.value( - u'db hostname', QtCore.QVariant(u'')).toString()), - unicode(settings.value( - u'db database', QtCore.QVariant(u'')).toString())) - self.session = init_schema(self.db_url) - settings.endGroup() + Manager.__init__(self, u'songs', init_schema) log.debug(u'Song Initialised') - def get_songs(self): - """ - Returns the details of a song - """ - return self.session.query(Song).order_by(Song.title).all() - def search_song_title(self, keywords): """ Searches the song title for keywords. @@ -143,174 +115,23 @@ class SongManager(object): return self.session.query(Author).filter(Author.display_name.like( u'%' + keywords + u'%')).order_by(Author.display_name.asc()).all() - def get_song(self, id=None): - """ - Returns the details of a song - """ - if id is None: - return Song() - else: - return self.session.query(Song).get(id) - - def save_song(self, song): - """ - Saves a song to the database - """ - try: - self.session.add(song) - self.session.commit() - return True - except InvalidRequestError: - log.exception(u'Could not save song to song database') - self.session.rollback() - return False - - def delete_song(self, songid): - song = self.get_song(songid) - try: - self.session.delete(song) - self.session.commit() - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'Could not delete song from song database') - return False - - def get_authors(self): - """ - Returns a list of all the authors - """ - return self.session.query(Author).order_by(Author.display_name).all() - - def get_author(self, id): - """ - Details of the Author - """ - return self.session.query(Author).get(id) - def get_author_by_name(self, name): """ Get author by display name """ return self.session.query(Author).filter_by(display_name=name).first() - def save_author(self, author): - """ - Save the Author and refresh the cache - """ - try: - self.session.add(author) - self.session.commit() - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'Could not save author to song database') - return False - - def delete_author(self, authorid): - """ - Delete the author - """ - author = self.get_author(authorid) - try: - self.session.delete(author) - self.session.commit() - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'Could not delete author from song database') - return False - - def get_topics(self): - """ - Returns a list of all the topics - """ - return self.session.query(Topic).order_by(Topic.name).all() - - def get_topic(self, id): - """ - Details of the Topic - """ - return self.session.query(Topic).get(id) - def get_topic_by_name(self, name): """ Get topic by name """ return self.session.query(Topic).filter_by(name=name).first() - def save_topic(self, topic): - """ - Save the Topic - """ - try: - self.session.add(topic) - self.session.commit() - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'Could not save topic to song database') - return False - - def delete_topic(self, topicid): - """ - Delete the topic - """ - topic = self.get_topic(topicid) - try: - self.session.delete(topic) - self.session.commit() - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'Could not delete topic from song database') - return False - - def get_books(self): - """ - Returns a list of all the Books - """ - return self.session.query(Book).order_by(Book.name).all() - - def get_book(self, id): - """ - Details of the Books - """ - return self.session.query(Book).get(id) - def get_book_by_name(self, name): """ Get book by name """ return self.session.query(Book).filter_by(name=name).first() - def save_book(self, book): - """ - Save the Book - """ - try: - self.session.add(book) - self.session.commit() - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'Could not save book to song database') - return False - - def delete_book(self, bookid): - """ - Delete the Book - """ - book = self.get_book(bookid) - try: - self.session.delete(book) - self.session.commit() - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'Could not delete book from song database') - return False - def get_songs_for_theme(self, theme): return self.session.query(Song).filter(Song.theme_name == theme).all() - diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index 67133f9c6..f0a4afc88 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -31,6 +31,7 @@ from openlp.core.lib import MediaManagerItem, SongXMLParser, \ BaseListWithDnD, Receiver, ItemCapabilities, translate from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \ ImportWizardForm +from openlp.plugins.songs.lib.db import Song log = logging.getLogger(__name__) @@ -267,7 +268,7 @@ class SongMediaItem(MediaManagerItem): type of display is required. """ fields = songid.split(u':') - valid = self.parent.manager.get_song(fields[1]) + valid = self.parent.manager.get_object(Song, fields[1]) if valid: self.remoteSong = fields[1] self.remoteTriggered = fields[0] @@ -301,7 +302,7 @@ class SongMediaItem(MediaManagerItem): return for item in items: item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] - self.parent.manager.delete_song(item_id) + self.parent.manager.delete_object(Song, item_id) self.onSearchTextButtonClick() def generateSlideData(self, service_item, item=None): @@ -322,7 +323,7 @@ class SongMediaItem(MediaManagerItem): service_item.add_capability(ItemCapabilities.AllowsEdit) service_item.add_capability(ItemCapabilities.AllowsPreview) service_item.add_capability(ItemCapabilities.AllowsLoop) - song = self.parent.manager.get_song(item_id) + song = self.parent.manager.get_object(Song, item_id) service_item.theme = song.theme_name service_item.editId = item_id if song.lyrics.startswith(u' Date: Tue, 15 Jun 2010 01:44:06 +0100 Subject: [PATCH 04/49] RFC PT3: Bibles --- openlp/core/lib/db.py | 42 ++++- .../plugins/bibles/forms/importwizardform.py | 12 +- openlp/plugins/bibles/lib/csvbible.py | 6 +- openlp/plugins/bibles/lib/db.py | 168 ++++++++++-------- openlp/plugins/bibles/lib/http.py | 3 +- openlp/plugins/bibles/lib/manager.py | 16 +- openlp/plugins/bibles/lib/models.py | 94 ---------- openlp/plugins/bibles/lib/opensong.py | 2 +- openlp/plugins/bibles/lib/osis.py | 4 +- openlp/plugins/songs/lib/songimport.py | 2 +- 10 files changed, 151 insertions(+), 198 deletions(-) delete mode 100644 openlp/plugins/bibles/lib/models.py diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index 323b48e39..7517998f0 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -74,13 +74,20 @@ class Manager(object): """ Provide generic object persistence management """ - def __init__(self, plugin_name, init_schema): + def __init__(self, plugin_name, init_schema, db_file_name=None): """ Runs the initialisation process that includes creating the connection to the database and the tables if they don't exist. ``plugin_name`` The name to setup paths and settings section names + + ``init_schema`` + The init_schema function for this database + + ``db_file_name`` + The file name to use for this database. Defaults to None resulting + in the plugin_name being used. """ settings = QtCore.QSettings() settings.beginGroup(plugin_name) @@ -88,8 +95,13 @@ class Manager(object): db_type = unicode( settings.value(u'db type', QtCore.QVariant(u'sqlite')).toString()) if db_type == u'sqlite': - self.db_url = u'sqlite:///%s/%s.sqlite' % ( - AppLocation.get_section_data_path(plugin_name), plugin_name) + if db_file_name: + self.db_url = u'sqlite:///%s/%s' % ( + AppLocation.get_section_data_path(plugin_name), + db_file_name) + else: + self.db_url = u'sqlite:///%s/%s.sqlite' % ( + AppLocation.get_section_data_path(plugin_name), plugin_name) else: self.db_url = u'%s://%s:%s@%s/%s' % (db_type, unicode(settings.value(u'db username').toString()), @@ -99,6 +111,30 @@ class Manager(object): settings.endGroup() self.session = init_schema(self.db_url) + def delete_database(self, plugin_name, db_file_name=None): + """ + Remove a database file from the system. + + ``plugin_name`` + The name of the plugin to remove the database for + + ``db_file_name`` + The database file name. Defaults to None resulting in the + plugin_name being used. + """ + db_file_path = None + if db_file_name: + db_file_path = os.path.join( + AppLocation.get_section_data_path(plugin_name), db_file_name) + else: + db_file_path = os.path.join( + AppLocation.get_section_data_path(plugin_name), plugin_name) + try: + os.remove(db_file_path) + return True + except OSError: + return False + def insert_object(self, object_instance): """ Save an object to the database diff --git a/openlp/plugins/bibles/forms/importwizardform.py b/openlp/plugins/bibles/forms/importwizardform.py index b1eafcd61..023391615 100644 --- a/openlp/plugins/bibles/forms/importwizardform.py +++ b/openlp/plugins/bibles/forms/importwizardform.py @@ -224,7 +224,7 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): Show the file open dialog for the OSIS file. """ self.getFileName( - translate(u'BiblesPlugin.ImportWizardForm', u'Open OSIS File'), + translate(u'BiblesPlugin.ImportWizardForm', u'Open OSIS File'), self.OSISLocationEdit) def onBooksFileButtonClicked(self): @@ -239,10 +239,8 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): """ Show the file open dialog for the verses CSV file. """ - self.getFileName( - translate(u'BiblesPlugin.ImportWizardForm', - u'Open Verses CSV File'), - self.CsvVerseLocationEdit) + self.getFileName(translate(u'BiblesPlugin.ImportWizardForm', + u'Open Verses CSV File'), self.CsvVerseLocationEdit) def onOpenSongBrowseButtonClicked(self): """ @@ -450,11 +448,11 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): self.ImportProgressLabel.setText( translate(u'BiblesPlugin.ImportWizardForm', u'Your Bible import failed.')) - importer.delete() + importer.delete_database(self.bibleplugin.settingsSection, + importer.file) def postImport(self): self.ImportProgressBar.setValue(self.ImportProgressBar.maximum()) self.finishButton.setVisible(True) self.cancelButton.setVisible(False) Receiver.send_message(u'openlp_process_events') - diff --git a/openlp/plugins/bibles/lib/csvbible.py b/openlp/plugins/bibles/lib/csvbible.py index 3cfe9dea5..9a504f48f 100644 --- a/openlp/plugins/bibles/lib/csvbible.py +++ b/openlp/plugins/bibles/lib/csvbible.py @@ -97,11 +97,11 @@ class CSVBible(BibleDB): book_ptr = book.name self.wizard.incrementProgressBar( u'Importing %s %s' % (book.name, line[1])) - self.commit() + self.session.commit() self.create_verse(book.id, line[1], line[2], unicode(line[3], details['encoding'])) Receiver.send_message(u'openlp_process_events') - self.commit() + self.session.commit() except IOError: log.exception(u'Loading verses from file failed') success = False @@ -113,5 +113,3 @@ class CSVBible(BibleDB): return False else: return success - - diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py index 97983e72c..7733261db 100644 --- a/openlp/plugins/bibles/lib/db.py +++ b/openlp/plugins/bibles/lib/db.py @@ -23,19 +23,98 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -import os import logging import chardet import re -from sqlalchemy import or_ from PyQt4 import QtCore +from sqlalchemy import Column, ForeignKey, or_, Table, types +from sqlalchemy.orm import class_mapper, mapper, relation +from sqlalchemy.orm.exc import UnmappedClassError -from openlp.plugins.bibles.lib.models import * +from openlp.core.lib.db import BaseModel, init_db, Manager log = logging.getLogger(__name__) -class BibleDB(QtCore.QObject): +class BibleMeta(BaseModel): + """ + Bible Meta Data + """ + pass + +class Testament(BaseModel): + """ + Bible Testaments + """ + pass + +class Book(BaseModel): + """ + Song model + """ + pass + +class Verse(BaseModel): + """ + Topic model + """ + pass + +def init_schema(url): + """ + Setup a bible database connection and initialise the database schema + + ``url`` + The database to setup + """ + session, metadata = init_db(url) + + meta_table = Table(u'metadata', metadata, + Column(u'key', types.Unicode(255), primary_key=True, index=True), + Column(u'value', types.Unicode(255)), + ) + testament_table = Table(u'testament', metadata, + Column(u'id', types.Integer, primary_key=True), + Column(u'name', types.Unicode(50)), + ) + book_table = Table(u'book', metadata, + Column(u'id', types.Integer, primary_key=True), + Column(u'testament_id', types.Integer, ForeignKey(u'testament.id')), + Column(u'name', types.Unicode(50), index=True), + Column(u'abbreviation', types.Unicode(5), index=True), + ) + verse_table = Table(u'verse', metadata, + Column(u'id', types.Integer, primary_key=True, index=True), + Column(u'book_id', types.Integer, ForeignKey(u'book.id'), index=True), + Column(u'chapter', types.Integer, index=True), + Column(u'verse', types.Integer, index=True), + Column(u'text', types.UnicodeText, index=True), + ) + + try: + class_mapper(BibleMeta) + except UnmappedClassError: + mapper(BibleMeta, meta_table) + try: + class_mapper(Testament) + except UnmappedClassError: + mapper(Testament, testament_table, + properties={'books': relation(Book, backref='testament')}) + try: + class_mapper(Book) + except UnmappedClassError: + mapper(Book, book_table, + properties={'verses': relation(Verse, backref='book')}) + try: + class_mapper(Verse) + except UnmappedClassError: + mapper(Verse, verse_table) + + metadata.create_all(checkfirst=True) + return session + + +class BibleDB(QtCore.QObject, Manager): """ This class represents a database-bound Bible. It is used as a base class for all the custom importers, so that the can implement their own import @@ -72,24 +151,7 @@ class BibleDB(QtCore.QObject): self.file = self.clean_filename(self.name) if u'file' in kwargs: self.file = kwargs[u'file'] - self.db_file = os.path.join(kwargs[u'path'], self.file) - log.debug(u'Load bible %s on path %s', self.file, self.db_file) - settings = QtCore.QSettings() - settings.beginGroup(u'bibles') - db_type = unicode( - settings.value(u'db type', QtCore.QVariant(u'sqlite')).toString()) - db_url = u'' - if db_type == u'sqlite': - db_url = u'sqlite:///' + self.db_file - else: - db_url = u'%s://%s:%s@%s/%s' % (db_type, - unicode(settings.value(u'db username').toString()), - unicode(settings.value(u'db password').toString()), - unicode(settings.value(u'db hostname').toString()), - unicode(settings.value(u'db database').toString())) - settings.endGroup() - self.session = init_models(db_url) - metadata.create_all(checkfirst=True) + Manager.__init__(self, u'bibles', init_schema, self.file) if u'file' in kwargs: self.get_name() @@ -104,7 +166,7 @@ class BibleDB(QtCore.QObject): """ Returns the version name of the Bible. """ - version_name = self.get_meta(u'Version') + version_name = self.get_object(BibleMeta, u'Version') if version_name: self.name = version_name.value else: @@ -124,16 +186,6 @@ class BibleDB(QtCore.QObject): old_filename = re.sub(r'[^\w]+', u'_', old_filename).strip(u'_') return old_filename + u'.sqlite' - def delete(self): - """ - Remove the Bible database file. Used when a Bible import fails. - """ - try: - os.remove(self.db_file) - return True - except OSError: - return False - def register(self, wizard): """ This method basically just initialialises the database. It is called @@ -148,33 +200,15 @@ class BibleDB(QtCore.QObject): self.create_tables() return self.name - def commit(self): - """ - Perform a database commit. - """ - log.debug('Committing...') - self.session.commit() - def create_tables(self): """ Create some initial metadata. """ log.debug(u'createTables') self.create_meta(u'dbversion', u'2') - self.create_testament(u'Old Testament') - self.create_testament(u'New Testament') - self.create_testament(u'Apocrypha') - - def create_testament(self, testament): - """ - Add a testament to the database. - - ``testament`` - The testament name. - """ - log.debug(u'BibleDB.create_testament("%s")', testament) - self.session.add(Testament.populate(name=testament)) - self.commit() + self.insert_object(Testament.populate(name=u'Old Testament')) + self.insert_object(Testament.populate(name=u'New Testament')) + self.insert_object(Testament.populate(name=u'Apocrypha')) def create_book(self, name, abbrev, testament=1): """ @@ -192,8 +226,7 @@ class BibleDB(QtCore.QObject): log.debug(u'create_book %s,%s', name, abbrev) book = Book.populate(name=name, abbreviation=abbrev, testament_id=testament) - self.session.add(book) - self.commit() + self.insert_object(book) return book def create_chapter(self, book_id, chapter, textlist): @@ -220,7 +253,7 @@ class BibleDB(QtCore.QObject): text = verse_text ) self.session.add(verse) - self.commit() + self.session.commit() def create_verse(self, book_id, chapter, verse, text): """ @@ -252,12 +285,7 @@ class BibleDB(QtCore.QObject): def create_meta(self, key, value): log.debug(u'save_meta %s/%s', key, value) - self.session.add(BibleMeta.populate(key=key, value=value)) - self.commit() - - def get_books(self): - log.debug(u'BibleDB.get_books()') - return self.session.query(Book).order_by(Book.id).all() + self.insert_object(BibleMeta.populate(key=key, value=value)) def get_book(self, book): log.debug(u'BibleDb.get_book("%s")', book) @@ -362,19 +390,6 @@ class BibleDB(QtCore.QObject): else: return count - def get_meta(self, key): - log.debug(u'get meta %s', key) - return self.session.query(BibleMeta).get(key) - - def delete_meta(self, metakey): - biblemeta = self.get_meta(metakey) - try: - self.session.delete(biblemeta) - self.commit() - return True - except: - return False - def dump_bible(self): log.debug(u'.........Dumping Bible Database') log.debug('...............................Books ') @@ -383,4 +398,3 @@ class BibleDB(QtCore.QObject): log.debug(u'...............................Verses ') verses = self.session.query(Verse).all() log.debug(verses) - diff --git a/openlp/plugins/bibles/lib/http.py b/openlp/plugins/bibles/lib/http.py index d3d6ca5f6..0b613b4b6 100644 --- a/openlp/plugins/bibles/lib/http.py +++ b/openlp/plugins/bibles/lib/http.py @@ -35,8 +35,7 @@ from openlp.core.lib import Receiver from openlp.core.utils import AppLocation from openlp.plugins.bibles.lib.common import BibleCommon, SearchResults, \ unescape -from openlp.plugins.bibles.lib.db import BibleDB -from openlp.plugins.bibles.lib.models import Book +from openlp.plugins.bibles.lib.db import BibleDB, Book log = logging.getLogger(__name__) diff --git a/openlp/plugins/bibles/lib/manager.py b/openlp/plugins/bibles/lib/manager.py index 7ef18a604..39f3c255b 100644 --- a/openlp/plugins/bibles/lib/manager.py +++ b/openlp/plugins/bibles/lib/manager.py @@ -29,12 +29,12 @@ from PyQt4 import QtCore from openlp.core.lib import SettingsManager from openlp.core.utils import AppLocation +from openlp.plugins.bibles.lib.db import BibleDB, Book, BibleMeta from common import parse_reference from opensong import OpenSongBible from osis import OSISBible from csvbible import CSVBible -from db import BibleDB from http import HTTPBible log = logging.getLogger(__name__) @@ -137,11 +137,13 @@ class BibleManager(object): log.debug(u'Bible Name: "%s"', name) self.db_cache[name] = bible # look to see if lazy load bible exists and get create getter. - source = self.db_cache[name].get_meta(u'download source') + source = self.db_cache[name].get_object(BibleMeta, + u'download source') if source: - download_name = \ - self.db_cache[name].get_meta(u'download name').value - meta_proxy = self.db_cache[name].get_meta(u'proxy url') + download_name = self.db_cache[name].get_object(BibleMeta, + u'download name').value + meta_proxy = self.db_cache[name].get_object(BibleMeta, + u'proxy url') web_bible = HTTPBible(self.parent, path=self.path, file=filename, download_source=source.value, download_name=download_name) @@ -196,7 +198,7 @@ class BibleManager(object): u'name': book.name, u'chapters': self.db_cache[bible].get_chapter_count(book.name) } - for book in self.db_cache[bible].get_books() + for book in self.db_cache[bible].get_all_objects(Book, Book.id) ] def get_chapter_count(self, bible, book): @@ -249,7 +251,7 @@ class BibleManager(object): Returns the meta data for a given key """ log.debug(u'get_meta %s,%s', bible, key) - return self.db_cache[bible].get_meta(key) + return self.db_cache[bible].get_object(BibleMeta, key) def exists(self, name): """ diff --git a/openlp/plugins/bibles/lib/models.py b/openlp/plugins/bibles/lib/models.py deleted file mode 100644 index 2cd52fb0b..000000000 --- a/openlp/plugins/bibles/lib/models.py +++ /dev/null @@ -1,94 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin # -# Thompson, Jon Tibble, Carsten Tinggaard # -# --------------------------------------------------------------------------- # -# This program is free software; you can redistribute it and/or modify it # -# under the terms of the GNU General Public License as published by the Free # -# Software Foundation; version 2 of the License. # -# # -# This program is distributed in the hope that it will be useful, but WITHOUT # -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # -# more details. # -# # -# You should have received a copy of the GNU General Public License along # -# with this program; if not, write to the Free Software Foundation, Inc., 59 # -# Temple Place, Suite 330, Boston, MA 02111-1307 USA # -############################################################################### - -from sqlalchemy import Column, Table, MetaData, ForeignKey, types, \ - create_engine -from sqlalchemy.orm import mapper, relation, sessionmaker, scoped_session - -from openlp.core.lib.db import BaseModel - - -class BibleMeta(BaseModel): - """ - Bible Meta Data - """ - pass - - -class Testament(BaseModel): - """ - Bible Testaments - """ - pass - - -class Book(BaseModel): - """ - Song model - """ - pass - - -class Verse(BaseModel): - """ - Topic model - """ - pass - -def init_models(db_url): - engine = create_engine(db_url) - metadata.bind = engine - session = scoped_session(sessionmaker(autoflush=True, autocommit=False, - bind=engine)) - return session - -metadata = MetaData() -meta_table = Table(u'metadata', metadata, - Column(u'key', types.Unicode(255), primary_key=True, index=True), - Column(u'value', types.Unicode(255)), -) -testament_table = Table(u'testament', metadata, - Column(u'id', types.Integer, primary_key=True), - Column(u'name', types.Unicode(50)), -) -book_table = Table(u'book', metadata, - Column(u'id', types.Integer, primary_key=True), - Column(u'testament_id', types.Integer, ForeignKey(u'testament.id')), - Column(u'name', types.Unicode(50), index=True), - Column(u'abbreviation', types.Unicode(5), index=True), -) -verse_table = Table(u'verse', metadata, - Column(u'id', types.Integer, primary_key=True, index=True), - Column(u'book_id', types.Integer, ForeignKey(u'book.id'), index=True), - Column(u'chapter', types.Integer, index=True), - Column(u'verse', types.Integer, index=True), - Column(u'text', types.UnicodeText, index=True), -) -mapper(BibleMeta, meta_table) -mapper(Testament, testament_table, - properties={'books': relation(Book, backref='testament')}) -mapper(Book, book_table, - properties={'verses': relation(Verse, backref='book')}) -mapper(Verse, verse_table) diff --git a/openlp/plugins/bibles/lib/opensong.py b/openlp/plugins/bibles/lib/opensong.py index b2df50257..dfdc542ef 100644 --- a/openlp/plugins/bibles/lib/opensong.py +++ b/openlp/plugins/bibles/lib/opensong.py @@ -90,7 +90,7 @@ class OpenSongBible(BibleDB): QtCore.QString('%s %s %s' % ( translate(u'BiblesPlugin.Opensong', u'Importing'), \ db_book.name, chapter.attrib[u'n']))) - self.commit() + self.session.commit() except IOError: log.exception(u'Loading bible from OpenSong file failed') success = False diff --git a/openlp/plugins/bibles/lib/osis.py b/openlp/plugins/bibles/lib/osis.py index b4a2a2aa1..2f30cf63c 100644 --- a/openlp/plugins/bibles/lib/osis.py +++ b/openlp/plugins/bibles/lib/osis.py @@ -136,7 +136,7 @@ class OSISBible(BibleDB): self.wizard.ImportProgressBar.setMaximum(260) if last_chapter != chapter: if last_chapter != 0: - self.commit() + self.session.commit() self.wizard.incrementProgressBar( u'Importing %s %s...' % \ (self.books[match.group(1)][0], chapter)) @@ -162,7 +162,7 @@ class OSISBible(BibleDB): verse_text = self.spaces_regex.sub(u' ', verse_text) self.create_verse(db_book.id, chapter, verse, verse_text) Receiver.send_message(u'openlp_process_events') - self.commit() + self.session.commit() self.wizard.incrementProgressBar(u'Finishing import...') if match_count == 0: success = False diff --git a/openlp/plugins/songs/lib/songimport.py b/openlp/plugins/songs/lib/songimport.py index 2d6a4cd21..36a9b9953 100644 --- a/openlp/plugins/songs/lib/songimport.py +++ b/openlp/plugins/songs/lib/songimport.py @@ -28,8 +28,8 @@ import string from PyQt4 import QtGui from openlp.core.lib import SongXMLBuilder +from openlp.plugins.songs.lib import VerseType from openlp.plugins.songs.lib.db import Song, Author, Topic, Book -from openlp.plugins.songs.forms import VerseType class SongImport(object): """ From e92b0173480852c2e3e374eafdf8c2b8de1cd525 Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Tue, 15 Jun 2010 03:08:22 +0100 Subject: [PATCH 05/49] RFC PT4: The other DB plugins --- openlp/core/lib/db.py | 14 ++- openlp/plugins/custom/customplugin.py | 9 +- openlp/plugins/custom/forms/editcustomform.py | 6 +- openlp/plugins/custom/lib/__init__.py | 1 - .../plugins/custom/lib/{classes.py => db.py} | 31 ++++- openlp/plugins/custom/lib/manager.py | 117 ------------------ openlp/plugins/custom/lib/mediaitem.py | 10 +- openlp/plugins/custom/lib/meta.py | 38 ------ openlp/plugins/custom/lib/models.py | 39 ------ openlp/plugins/custom/lib/tables.py | 37 ------ openlp/plugins/songs/lib/manager.py | 3 - openlp/plugins/songs/songsplugin.py | 4 +- .../songusage/forms/songusagedetailform.py | 17 ++- openlp/plugins/songusage/lib/classes.py | 32 ----- .../songusage/lib/{models.py => db.py} | 44 +++++-- openlp/plugins/songusage/lib/manager.py | 100 +++------------ openlp/plugins/songusage/lib/meta.py | 38 ------ openlp/plugins/songusage/lib/tables.py | 39 ------ openlp/plugins/songusage/songusageplugin.py | 6 +- 19 files changed, 120 insertions(+), 465 deletions(-) rename openlp/plugins/custom/lib/{classes.py => db.py} (68%) delete mode 100644 openlp/plugins/custom/lib/manager.py delete mode 100644 openlp/plugins/custom/lib/meta.py delete mode 100644 openlp/plugins/custom/lib/models.py delete mode 100644 openlp/plugins/custom/lib/tables.py delete mode 100644 openlp/plugins/songusage/lib/classes.py rename openlp/plugins/songusage/lib/{models.py => db.py} (63%) delete mode 100644 openlp/plugins/songusage/lib/meta.py delete mode 100644 openlp/plugins/songusage/lib/tables.py diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index 7517998f0..4c7b1ca23 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -171,7 +171,7 @@ class Manager(object): Returns all the objects from the database ``object_class`` - The type of object to return + The type of objects to return ``order_by_ref`` Any parameters to order the returned objects by. Defaults to None. @@ -180,6 +180,18 @@ class Manager(object): return self.session.query(object_class).order_by(order_by_ref).all() return self.session.query(object_class).all() + def get_all_objects_filtered(self, object_class, filter_string): + """ + Returns a selection of objects from the database + + ``object_class`` + The type of objects to return + + ``filter_string`` + The filter governing selection of objects to return + """ + return self.session.query(object_class).filter(filter_string).all() + def delete_object(self, object_class, id): """ Delete an object from the database diff --git a/openlp/plugins/custom/customplugin.py b/openlp/plugins/custom/customplugin.py index 9ae208a28..92bfdadfc 100644 --- a/openlp/plugins/custom/customplugin.py +++ b/openlp/plugins/custom/customplugin.py @@ -27,7 +27,9 @@ import logging from forms import EditCustomForm from openlp.core.lib import Plugin, build_icon, PluginStatus, translate -from openlp.plugins.custom.lib import CustomManager, CustomMediaItem, CustomTab +from openlp.core.lib.db import Manager +from openlp.plugins.custom.lib import CustomMediaItem, CustomTab +from openlp.plugins.custom.lib.db import CustomSlide, init_schema log = logging.getLogger(__name__) @@ -45,7 +47,7 @@ class CustomPlugin(Plugin): def __init__(self, plugin_helpers): Plugin.__init__(self, u'Custom', u'1.9.1', plugin_helpers) self.weight = -5 - self.custommanager = CustomManager() + self.custommanager = Manager(u'custom', init_schema) self.edit_custom_form = EditCustomForm(self.custommanager) self.icon = build_icon(u':/media/media_custom.png') self.status = PluginStatus.Active @@ -75,6 +77,7 @@ class CustomPlugin(Plugin): return about_text def can_delete_theme(self, theme): - if len(self.custommanager.get_customs_for_theme(theme)) == 0: + filter = u'theme_name=%s' % theme + if not self.custommanager.get_all_objects_filtered(CustomSlide, filter): return True return False diff --git a/openlp/plugins/custom/forms/editcustomform.py b/openlp/plugins/custom/forms/editcustomform.py index 4e8b5957a..2b8a5bc03 100644 --- a/openlp/plugins/custom/forms/editcustomform.py +++ b/openlp/plugins/custom/forms/editcustomform.py @@ -29,7 +29,7 @@ from PyQt4 import QtCore, QtGui from editcustomdialog import Ui_customEditDialog from openlp.core.lib import SongXMLBuilder, SongXMLParser, Receiver, translate -from openlp.plugins.custom.lib.models import CustomSlide +from openlp.plugins.custom.lib.db import CustomSlide log = logging.getLogger(__name__) @@ -117,7 +117,7 @@ class EditCustomForm(QtGui.QDialog, Ui_customEditDialog): self.customSlide = CustomSlide() self.initialise() if id != 0: - self.customSlide = self.custommanager.get_custom(id) + self.customSlide = self.custommanager.get_object(CustomSlide, id) self.TitleEdit.setText(self.customSlide.title) self.CreditEdit.setText(self.customSlide.credits) songXML = SongXMLParser(self.customSlide.text) @@ -167,7 +167,7 @@ class EditCustomForm(QtGui.QDialog, Ui_customEditDialog): u'utf-8') self.customSlide.theme_name = unicode(self.ThemeComboBox.currentText(), u'utf-8') - self.custommanager.save_slide(self.customSlide) + self.custommanager.insert_object(self.customSlide) return True def onUpButtonPressed(self): diff --git a/openlp/plugins/custom/lib/__init__.py b/openlp/plugins/custom/lib/__init__.py index e62669ad3..0d9de3173 100644 --- a/openlp/plugins/custom/lib/__init__.py +++ b/openlp/plugins/custom/lib/__init__.py @@ -23,6 +23,5 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from manager import CustomManager from mediaitem import CustomMediaItem from customtab import CustomTab diff --git a/openlp/plugins/custom/lib/classes.py b/openlp/plugins/custom/lib/db.py similarity index 68% rename from openlp/plugins/custom/lib/classes.py rename to openlp/plugins/custom/lib/db.py index 6d8c623d1..277f3a7e8 100644 --- a/openlp/plugins/custom/lib/classes.py +++ b/openlp/plugins/custom/lib/db.py @@ -22,11 +22,40 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### +""" +The :mod:`db` module provides the database and schema that is the backend for +the Custom plugin +""" -from openlp.core.lib.db import BaseModel +from sqlalchemy import Column, Table, types +from sqlalchemy.orm import mapper + +from openlp.core.lib.db import BaseModel, init_db class CustomSlide(BaseModel): """ Custom Slide model """ pass + +def init_schema(url): + """ + Setup the custom database connection and initialise the database schema + + ``url`` + The database to setup + """ + session, metadata = init_db(url) + + custom_slide_table = Table(u'custom_slide', metadata, + Column(u'id', types.Integer(), primary_key=True), + Column(u'title', types.Unicode(255), nullable=False), + Column(u'text', types.UnicodeText, nullable=False), + Column(u'credits', types.UnicodeText), + Column(u'theme_name', types.Unicode(128)) + ) + + mapper(CustomSlide, custom_slide_table) + + metadata.create_all(checkfirst=True) + return session diff --git a/openlp/plugins/custom/lib/manager.py b/openlp/plugins/custom/lib/manager.py deleted file mode 100644 index 793cd8699..000000000 --- a/openlp/plugins/custom/lib/manager.py +++ /dev/null @@ -1,117 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin # -# Thompson, Jon Tibble, Carsten Tinggaard # -# --------------------------------------------------------------------------- # -# This program is free software; you can redistribute it and/or modify it # -# under the terms of the GNU General Public License as published by the Free # -# Software Foundation; version 2 of the License. # -# # -# This program is distributed in the hope that it will be useful, but WITHOUT # -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # -# more details. # -# # -# You should have received a copy of the GNU General Public License along # -# with this program; if not, write to the Free Software Foundation, Inc., 59 # -# Temple Place, Suite 330, Boston, MA 02111-1307 USA # -############################################################################### - -import logging - -from PyQt4 import QtCore -from sqlalchemy.exceptions import InvalidRequestError - -from openlp.core.utils import AppLocation -from openlp.plugins.custom.lib.models import init_models, metadata, CustomSlide - -log = logging.getLogger(__name__) - -class CustomManager(object): - """ - The Song Manager provides a central location for all database code. This - class takes care of connecting to the database and running all the queries. - """ - log.info(u'Custom manager loaded') - - def __init__(self): - """ - Creates the connection to the database, and creates the tables if they - don't exist. - """ - log.debug(u'Custom Initialising') - settings = QtCore.QSettings() - settings.beginGroup(u'custom') - self.db_url = u'' - db_type = unicode( - settings.value(u'db type', QtCore.QVariant(u'sqlite')).toString()) - if db_type == u'sqlite': - self.db_url = u'sqlite:///%s/custom.sqlite' % \ - AppLocation.get_section_data_path(u'custom') - else: - self.db_url = u'%s://%s:%s@%s/%s' % (db_type, - unicode(settings.value(u'db username').toString()), - unicode(settings.value(u'db password').toString()), - unicode(settings.value(u'db hostname').toString()), - unicode(settings.value(u'db database').toString())) - self.session = init_models(self.db_url) - metadata.create_all(checkfirst=True) - settings.endGroup() - log.debug(u'Custom Initialised') - - def get_all_slides(self): - """ - Returns the details of a Custom Slide Show - """ - return self.session.query(CustomSlide).order_by(CustomSlide.title).all() - - def save_slide(self, customslide): - """ - Saves a Custom slide show to the database - """ - log.debug(u'Custom Slide added') - try: - self.session.add(customslide) - self.session.commit() - log.debug(u'Custom Slide saved') - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'Custom Slide save failed') - return False - - def get_custom(self, id=None): - """ - Returns the details of a Custom Slide - """ - if id is None: - return CustomSlide() - else: - return self.session.query(CustomSlide).get(id) - - def delete_custom(self, id): - """ - Delete a Custom slide show - """ - if id != 0: - customslide = self.get_custom(id) - try: - self.session.delete(customslide) - self.session.commit() - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'Custom Slide deleton failed') - return False - else: - return True - - def get_customs_for_theme(self, theme): - return self.session.query( - CustomSlide).filter(CustomSlide.theme_name == theme).all() diff --git a/openlp/plugins/custom/lib/mediaitem.py b/openlp/plugins/custom/lib/mediaitem.py index 581334410..18f681489 100644 --- a/openlp/plugins/custom/lib/mediaitem.py +++ b/openlp/plugins/custom/lib/mediaitem.py @@ -29,6 +29,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import MediaManagerItem, SongXMLParser, BaseListWithDnD, \ Receiver, ItemCapabilities, translate +from openlp.plugins.custom.lib.db import CustomSlide log = logging.getLogger(__name__) @@ -72,7 +73,8 @@ class CustomMediaItem(MediaManagerItem): MediaManagerItem.requiredIcons(self) def initialise(self): - self.loadCustomListView(self.parent.custommanager.get_all_slides()) + self.loadCustomListView(self.parent.custommanager.get_all_objects( + CustomSlide, CustomSlide.title)) #Called to redisplay the song list screen edith from a search #or from the exit of the Song edit dialog. If remote editing is active #Trigger it and clean up so it will not update again. @@ -106,7 +108,7 @@ class CustomMediaItem(MediaManagerItem): type of display is required. """ fields = customid.split(u':') - valid = self.parent.custommanager.get_custom(fields[1]) + valid = self.parent.custommanager.get_object(CustomSlide, fields[1]) if valid: self.remoteCustom = fields[1] self.remoteTriggered = fields[0] @@ -126,7 +128,7 @@ class CustomMediaItem(MediaManagerItem): item = self.ListView.currentItem() if item: item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] - self.parent.custommanager.delete_custom(item_id) + self.parent.custommanager.delete_object(CustomSlide, item_id) row = self.ListView.row(item) self.ListView.takeItem(row) @@ -148,7 +150,7 @@ class CustomMediaItem(MediaManagerItem): service_item.add_capability(ItemCapabilities.AllowsEdit) service_item.add_capability(ItemCapabilities.AllowsPreview) service_item.add_capability(ItemCapabilities.AllowsLoop) - customSlide = self.parent.custommanager.get_custom(item_id) + customSlide = self.parent.custommanager.get_object(CustomSlide, item_id) title = customSlide.title credit = customSlide.credits service_item.editId = item_id diff --git a/openlp/plugins/custom/lib/meta.py b/openlp/plugins/custom/lib/meta.py deleted file mode 100644 index affa31969..000000000 --- a/openlp/plugins/custom/lib/meta.py +++ /dev/null @@ -1,38 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin # -# Thompson, Jon Tibble, Carsten Tinggaard # -# --------------------------------------------------------------------------- # -# This program is free software; you can redistribute it and/or modify it # -# under the terms of the GNU General Public License as published by the Free # -# Software Foundation; version 2 of the License. # -# # -# This program is distributed in the hope that it will be useful, but WITHOUT # -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # -# more details. # -# # -# You should have received a copy of the GNU General Public License along # -# with this program; if not, write to the Free Software Foundation, Inc., 59 # -# Temple Place, Suite 330, Boston, MA 02111-1307 USA # -############################################################################### - -from sqlalchemy import MetaData - -__all__ = ['session', 'metadata', 'engine'] - -# SQLAlchemy database engine. Updated by model.init_model() -engine = None - -# SQLAlchemy session manager. Updated by model.init_model() -session = None - -# Global metadata. If you have multiple databases with overlapping table -# names, you'll need a metadata for each database -metadata = MetaData() diff --git a/openlp/plugins/custom/lib/models.py b/openlp/plugins/custom/lib/models.py deleted file mode 100644 index 3bd2886bd..000000000 --- a/openlp/plugins/custom/lib/models.py +++ /dev/null @@ -1,39 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin # -# Thompson, Jon Tibble, Carsten Tinggaard # -# --------------------------------------------------------------------------- # -# This program is free software; you can redistribute it and/or modify it # -# under the terms of the GNU General Public License as published by the Free # -# Software Foundation; version 2 of the License. # -# # -# This program is distributed in the hope that it will be useful, but WITHOUT # -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # -# more details. # -# # -# You should have received a copy of the GNU General Public License along # -# with this program; if not, write to the Free Software Foundation, Inc., 59 # -# Temple Place, Suite 330, Boston, MA 02111-1307 USA # -############################################################################### - -from sqlalchemy import create_engine -from sqlalchemy.orm import scoped_session, sessionmaker, mapper - -from openlp.plugins.custom.lib.meta import metadata -from openlp.plugins.custom.lib.tables import * -from openlp.plugins.custom.lib.classes import * - -def init_models(url): - engine = create_engine(url) - metadata.bind = engine - session = scoped_session(sessionmaker(autoflush=True, autocommit=False, - bind=engine)) - mapper(CustomSlide, custom_slide_table) - return session diff --git a/openlp/plugins/custom/lib/tables.py b/openlp/plugins/custom/lib/tables.py deleted file mode 100644 index bb86d9d6d..000000000 --- a/openlp/plugins/custom/lib/tables.py +++ /dev/null @@ -1,37 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin # -# Thompson, Jon Tibble, Carsten Tinggaard # -# --------------------------------------------------------------------------- # -# This program is free software; you can redistribute it and/or modify it # -# under the terms of the GNU General Public License as published by the Free # -# Software Foundation; version 2 of the License. # -# # -# This program is distributed in the hope that it will be useful, but WITHOUT # -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # -# more details. # -# # -# You should have received a copy of the GNU General Public License along # -# with this program; if not, write to the Free Software Foundation, Inc., 59 # -# Temple Place, Suite 330, Boston, MA 02111-1307 USA # -############################################################################### - -from sqlalchemy import Column, Table, types - -from openlp.plugins.custom.lib.meta import metadata - -# Definition of the "custom slide" table -custom_slide_table = Table(u'custom_slide', metadata, - Column(u'id', types.Integer(), primary_key=True), - Column(u'title', types.Unicode(255), nullable=False), - Column(u'text', types.UnicodeText, nullable=False), - Column(u'credits', types.UnicodeText), - Column(u'theme_name', types.Unicode(128)) -) diff --git a/openlp/plugins/songs/lib/manager.py b/openlp/plugins/songs/lib/manager.py index 6cd9a90ad..f2edf6e75 100644 --- a/openlp/plugins/songs/lib/manager.py +++ b/openlp/plugins/songs/lib/manager.py @@ -132,6 +132,3 @@ class SongManager(Manager): Get book by name """ return self.session.query(Book).filter_by(name=name).first() - - def get_songs_for_theme(self, theme): - return self.session.query(Song).filter(Song.theme_name == theme).all() diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py index b7ddd473e..45ee4fe46 100644 --- a/openlp/plugins/songs/songsplugin.py +++ b/openlp/plugins/songs/songsplugin.py @@ -187,7 +187,7 @@ class SongsPlugin(Plugin): return about_text def can_delete_theme(self, theme): - if len(self.manager.get_songs_for_theme(theme)) == 0: + filter = u'theme_name=%s' % theme + if not self.manager.get_all_objects_filtered(Song, filter): return True return False - diff --git a/openlp/plugins/songusage/forms/songusagedetailform.py b/openlp/plugins/songusage/forms/songusagedetailform.py index fb1d1c73d..bb19bc2e6 100644 --- a/openlp/plugins/songusage/forms/songusagedetailform.py +++ b/openlp/plugins/songusage/forms/songusagedetailform.py @@ -71,20 +71,19 @@ class SongUsageDetailForm(QtGui.QDialog, Ui_SongUsageDetailDialog): def accept(self): log.debug(u'Detailed report generated') - filename = u'usage_detail_%s_%s.txt' % \ - (self.FromDate.selectedDate().toString(u'ddMMyyyy'), - self.ToDate.selectedDate().toString(u'ddMMyyyy')) - usage = self.parent.songusagemanager.get_all_songusage(\ - self.FromDate.selectedDate(), \ - self.ToDate.selectedDate()) + filename = u'usage_detail_%s_%s.txt' % ( + self.FromDate.selectedDate().toString(u'ddMMyyyy'), + self.ToDate.selectedDate().toString(u'ddMMyyyy')) + usage = self.parent.songusagemanager.get_songusage_for_period( + self.FromDate.selectedDate(), self.ToDate.selectedDate()) outname = os.path.join(unicode(self.FileLineEdit.text()), filename) file = None try: file = open(outname, u'w') for instance in usage: - record = u'\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"\n' % \ - (instance.usagedate,instance.usagetime, instance.title, - instance.copyright, instance.ccl_number , instance.authors) + record = u'\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"\n' % ( + instance.usagedate, instance.usagetime, instance.title, + instance.copyright, instance.ccl_number, instance.authors) file.write(record) except IOError: log.exception(u'Failed to write out song usage records') diff --git a/openlp/plugins/songusage/lib/classes.py b/openlp/plugins/songusage/lib/classes.py deleted file mode 100644 index 885d87faf..000000000 --- a/openlp/plugins/songusage/lib/classes.py +++ /dev/null @@ -1,32 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin # -# Thompson, Jon Tibble, Carsten Tinggaard # -# --------------------------------------------------------------------------- # -# This program is free software; you can redistribute it and/or modify it # -# under the terms of the GNU General Public License as published by the Free # -# Software Foundation; version 2 of the License. # -# # -# This program is distributed in the hope that it will be useful, but WITHOUT # -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # -# more details. # -# # -# You should have received a copy of the GNU General Public License along # -# with this program; if not, write to the Free Software Foundation, Inc., 59 # -# Temple Place, Suite 330, Boston, MA 02111-1307 USA # -############################################################################### - -from openlp.core.lib.db import BaseModel - -class SongUsageItem(BaseModel): - """ - Audit model - """ - pass diff --git a/openlp/plugins/songusage/lib/models.py b/openlp/plugins/songusage/lib/db.py similarity index 63% rename from openlp/plugins/songusage/lib/models.py rename to openlp/plugins/songusage/lib/db.py index a7babbaed..ffb720a58 100644 --- a/openlp/plugins/songusage/lib/models.py +++ b/openlp/plugins/songusage/lib/db.py @@ -22,18 +22,42 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### +""" +The :mod:`db` module provides the database and schema that is the backend for +the SongUsage plugin +""" -from sqlalchemy import create_engine -from sqlalchemy.orm import scoped_session, sessionmaker, mapper +from sqlalchemy import Column, Table, types +from sqlalchemy.orm import mapper -from openlp.plugins.songusage.lib.meta import metadata -from openlp.plugins.songusage.lib.tables import * -from openlp.plugins.songusage.lib.classes import * +from openlp.core.lib.db import BaseModel, init_db + +class SongUsageItem(BaseModel): + """ + SongUsageItem model + """ + pass + +def init_schema(url): + """ + Setup the songusage database connection and initialise the database schema + + ``url`` + The database to setup + """ + session, metadata = init_db(url) + + songusage_table = Table(u'songusage_data', metadata, + Column(u'id', types.Integer(), primary_key=True), + Column(u'usagedate', types.Date, index=True, nullable=False), + Column(u'usagetime', types.Time, index=True, nullable=False), + Column(u'title', types.Unicode(255), nullable=False), + Column(u'authors', types.Unicode(255), nullable=False), + Column(u'copyright', types.Unicode(255)), + Column(u'ccl_number', types.Unicode(65)) + ) -def init_models(url): - engine = create_engine(url) - metadata.bind = engine - session = scoped_session(sessionmaker(autoflush=True, autocommit=False, - bind=engine)) mapper(SongUsageItem, songusage_table) + + metadata.create_all(checkfirst=True) return session diff --git a/openlp/plugins/songusage/lib/manager.py b/openlp/plugins/songusage/lib/manager.py index b830fdafd..363f06fb8 100644 --- a/openlp/plugins/songusage/lib/manager.py +++ b/openlp/plugins/songusage/lib/manager.py @@ -25,16 +25,14 @@ import logging -from PyQt4 import QtCore from sqlalchemy.exceptions import InvalidRequestError -from openlp.core.utils import AppLocation -from openlp.plugins.songusage.lib.models import init_models, metadata, \ - SongUsageItem +from openlp.core.lib.db import Manager +from openlp.plugins.songusage.lib.db import init_schema, SongUsageItem log = logging.getLogger(__name__) -class SongUsageManager(object): +class SongUsageManager(Manager): """ The Song Manager provides a central location for all database code. This class takes care of connecting to the database and running all the queries. @@ -47,98 +45,31 @@ class SongUsageManager(object): don't exist. """ log.debug(u'SongUsage Initialising') - settings = QtCore.QSettings() - settings.beginGroup(u'songusage') - self.db_url = u'' - db_type = unicode( - settings.value(u'db type', QtCore.QVariant(u'sqlite')).toString()) - if db_type == u'sqlite': - self.db_url = u'sqlite:///%s/songusage.sqlite' % \ - AppLocation.get_section_data_path(u'songusage') - else: - self.db_url = u'%s://%s:%s@%s/%s' % (db_type, - unicode(settings.value(u'db username', - QtCore.QVariant(u'')).toString()), - unicode(settings.value(u'db password', - QtCore.QVariant(u'')).toString()), - unicode(settings.value(u'db hostname', - QtCore.QVariant(u'')).toString()), - unicode(settings.value(u'db database', - QtCore.QVariant(u'')).toString())) - self.session = init_models(self.db_url) - metadata.create_all(checkfirst=True) - settings.endGroup() + Manager.__init__(self, u'songusage', init_schema) log.debug(u'SongUsage Initialised') - def get_all_songusage(self, start_date, end_date): + def get_songusage_for_period(self, start_date, end_date): """ - Returns the details of SongUsage + Returns the details of SongUsage for a designated time period + + ``start_date`` + The start of the period to return + + ``end_date`` + The end of the period to return """ return self.session.query(SongUsageItem) \ .filter(SongUsageItem.usagedate >= start_date.toPyDate()) \ .filter(SongUsageItem.usagedate < end_date.toPyDate()) \ - .order_by(SongUsageItem.usagedate, SongUsageItem.usagetime ).all() - - def insert_songusage(self, songusageitem): - """ - Saves an SongUsage to the database - """ - log.debug(u'SongUsage added') - try: - self.session.add(songusageitem) - self.session.commit() - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'SongUsage item failed to save') - return False - - def get_songusage(self, id=None): - """ - Returns the details of a SongUsage - """ - if id is None: - return SongUsageItem() - else: - return self.session.query(SongUsageItem).get(id) - - def delete_songusage(self, id): - """ - Delete a SongUsage record - """ - if id != 0: - songusageitem = self.get_songusage(id) - try: - self.session.delete(songusageitem) - self.session.commit() - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'SongUsage Item failed to delete') - return False - else: - return True - - def delete_all(self): - """ - Delete all Song Usage records - """ - try: - self.session.query(SongUsageItem).delete(synchronize_session=False) - self.session.commit() - return True - except InvalidRequestError: - self.session.rollback() - log.exception(u'Failed to delete all Song Usage items') - return False + .order_by(SongUsageItem.usagedate, SongUsageItem.usagetime).all() def delete_to_date(self, date): """ Delete SongUsage records before given date """ try: - self.session.query(SongUsageItem)\ - .filter(SongUsageItem.usagedate <= date)\ + self.session.query(SongUsageItem) \ + .filter(SongUsageItem.usagedate <= date) \ .delete(synchronize_session=False) self.session.commit() return True @@ -146,4 +77,3 @@ class SongUsageManager(object): self.session.rollback() log.exception(u'Failed to delete all Song Usage items to %s' % date) return False - diff --git a/openlp/plugins/songusage/lib/meta.py b/openlp/plugins/songusage/lib/meta.py deleted file mode 100644 index affa31969..000000000 --- a/openlp/plugins/songusage/lib/meta.py +++ /dev/null @@ -1,38 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin # -# Thompson, Jon Tibble, Carsten Tinggaard # -# --------------------------------------------------------------------------- # -# This program is free software; you can redistribute it and/or modify it # -# under the terms of the GNU General Public License as published by the Free # -# Software Foundation; version 2 of the License. # -# # -# This program is distributed in the hope that it will be useful, but WITHOUT # -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # -# more details. # -# # -# You should have received a copy of the GNU General Public License along # -# with this program; if not, write to the Free Software Foundation, Inc., 59 # -# Temple Place, Suite 330, Boston, MA 02111-1307 USA # -############################################################################### - -from sqlalchemy import MetaData - -__all__ = ['session', 'metadata', 'engine'] - -# SQLAlchemy database engine. Updated by model.init_model() -engine = None - -# SQLAlchemy session manager. Updated by model.init_model() -session = None - -# Global metadata. If you have multiple databases with overlapping table -# names, you'll need a metadata for each database -metadata = MetaData() diff --git a/openlp/plugins/songusage/lib/tables.py b/openlp/plugins/songusage/lib/tables.py deleted file mode 100644 index 008c722b1..000000000 --- a/openlp/plugins/songusage/lib/tables.py +++ /dev/null @@ -1,39 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin # -# Thompson, Jon Tibble, Carsten Tinggaard # -# --------------------------------------------------------------------------- # -# This program is free software; you can redistribute it and/or modify it # -# under the terms of the GNU General Public License as published by the Free # -# Software Foundation; version 2 of the License. # -# # -# This program is distributed in the hope that it will be useful, but WITHOUT # -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # -# more details. # -# # -# You should have received a copy of the GNU General Public License along # -# with this program; if not, write to the Free Software Foundation, Inc., 59 # -# Temple Place, Suite 330, Boston, MA 02111-1307 USA # -############################################################################### - -from sqlalchemy import Column, Table, types - -from openlp.plugins.songusage.lib.meta import metadata - -# Definition of the "songusage" table -songusage_table = Table(u'songusage_data', metadata, - Column(u'id', types.Integer(), primary_key=True), - Column(u'usagedate', types.Date, index=True, nullable=False), - Column(u'usagetime', types.Time, index=True, nullable=False), - Column(u'title', types.Unicode(255), nullable=False), - Column(u'authors', types.Unicode(255), nullable=False), - Column(u'copyright', types.Unicode(255)), - Column(u'ccl_number', types.Unicode(65)) -) diff --git a/openlp/plugins/songusage/songusageplugin.py b/openlp/plugins/songusage/songusageplugin.py index 6cbb08e1a..04292e069 100644 --- a/openlp/plugins/songusage/songusageplugin.py +++ b/openlp/plugins/songusage/songusageplugin.py @@ -23,16 +23,16 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from datetime import datetime import logging +from datetime import datetime from PyQt4 import QtCore, QtGui from openlp.core.lib import Plugin, Receiver, build_icon, translate from openlp.plugins.songusage.lib import SongUsageManager from openlp.plugins.songusage.forms import SongUsageDetailForm, \ SongUsageDeleteForm -from openlp.plugins.songusage.lib.models import SongUsageItem +from openlp.plugins.songusage.lib.db import SongUsageItem log = logging.getLogger(__name__) @@ -146,7 +146,7 @@ class SongUsagePlugin(Plugin): song_usage_item.authors = u'' for author in audit[1]: song_usage_item.authors += author + u' ' - self.songusagemanager.insert_songusage(song_usage_item) + self.songusagemanager.insert_object(song_usage_item) def onSongUsageDelete(self): self.SongUsagedeleteform.exec_() From 85661fe6e468f657552174785ace5d1fe5accad8 Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Tue, 15 Jun 2010 16:42:52 +0100 Subject: [PATCH 06/49] RFC: Tweaks --- openlp/core/lib/__init__.py | 29 +++++++++++- openlp/migration/migratebibles.py | 3 +- openlp/migration/migratesongs.py | 5 +-- openlp/plugins/alerts/alertsplugin.py | 3 ++ openlp/plugins/bibles/lib/db.py | 63 +++++++++++++++++---------- openlp/plugins/custom/lib/db.py | 2 +- 6 files changed, 74 insertions(+), 31 deletions(-) diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py index ffc61cdcc..5e6547906 100644 --- a/openlp/core/lib/__init__.py +++ b/openlp/core/lib/__init__.py @@ -22,7 +22,6 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### - """ The :mod:`lib` module contains most of the components and libraries that make OpenLP work. @@ -47,6 +46,10 @@ def translate(context, text, comment=None): ``text`` The text to put into the translation tables for translation. + + ``comment`` + An identifying string for when the same text is used in different roles + within the same context. """ return QtCore.QCoreApplication.translate(context, text, comment) @@ -115,6 +118,18 @@ def build_icon(icon): def context_menu_action(base, icon, text, slot): """ Utility method to help build context menus for plugins + + ``base`` + The parent menu to add this menu item to + + ``icon`` + An icon for this action + + ``text`` + The text to display for this action + + ``slot`` + The code to run when this action is triggered """ action = QtGui.QAction(text, base) if icon: @@ -125,6 +140,15 @@ def context_menu_action(base, icon, text, slot): def context_menu(base, icon, text): """ Utility method to help build context menus for plugins + + ``base`` + The parent object to add this menu to + + ``icon`` + An icon for this menu + + ``text`` + The text to display for this menu """ action = QtGui.QMenu(text, base) action.setIcon(build_icon(icon)) @@ -133,6 +157,9 @@ def context_menu(base, icon, text): def context_menu_separator(base): """ Add a separator to a context menu + + ``base`` + The menu object to add the separator to """ action = QtGui.QAction(u'', base) action.setSeparator(True) diff --git a/openlp/migration/migratebibles.py b/openlp/migration/migratebibles.py index b024343a4..411da0ce6 100644 --- a/openlp/migration/migratebibles.py +++ b/openlp/migration/migratebibles.py @@ -33,7 +33,7 @@ from sqlalchemy.orm import mapper from openlp.core.lib import SettingsManager from openlp.core.lib.db import BaseModel from openlp.core.utils import AppLocation -from openlp.plugins.bibles.lib.models import * +from openlp.plugins.bibles.lib.db import BibleMeta, Book, Testament, Verse class TBibleMeta(BaseModel): """ @@ -196,4 +196,3 @@ class MigrateBibles(object): conn.commit() conn.execute(u'vacuum;') conn.commit() - diff --git a/openlp/migration/migratesongs.py b/openlp/migration/migratesongs.py index c4cab00bc..0ede63387 100644 --- a/openlp/migration/migratesongs.py +++ b/openlp/migration/migratesongs.py @@ -34,10 +34,7 @@ from sqlalchemy.orm import scoped_session, sessionmaker, mapper, relation from openlp.core.lib import SettingsManager from openlp.core.lib.db import BaseModel from openlp.core.utils import AppLocation -from openlp.plugins.songs.lib.models import metadata, songs_table, Song, \ - Author, Topic, Book -from openlp.plugins.songs.lib.tables import * -from openlp.plugins.songs.lib.classes import * +from openlp.plugins.songs.lib.db import songs_table, Song, Author, Topic, Book def init_models(url): engine = create_engine(url) diff --git a/openlp/plugins/alerts/alertsplugin.py b/openlp/plugins/alerts/alertsplugin.py index 3c14e23b1..bd783a7cb 100644 --- a/openlp/plugins/alerts/alertsplugin.py +++ b/openlp/plugins/alerts/alertsplugin.py @@ -48,6 +48,9 @@ class alertsPlugin(Plugin): self.status = PluginStatus.Active def get_settings_tab(self): + """ + Return the settings tab for the Alerts plugin + """ self.alertsTab = AlertsTab(self) return self.alertsTab diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py index 7733261db..eee149320 100644 --- a/openlp/plugins/bibles/lib/db.py +++ b/openlp/plugins/bibles/lib/db.py @@ -197,18 +197,11 @@ class BibleDB(QtCore.QObject, Manager): The actual Qt wizard form. """ self.wizard = wizard - self.create_tables() - return self.name - - def create_tables(self): - """ - Create some initial metadata. - """ - log.debug(u'createTables') self.create_meta(u'dbversion', u'2') self.insert_object(Testament.populate(name=u'Old Testament')) self.insert_object(Testament.populate(name=u'New Testament')) self.insert_object(Testament.populate(name=u'Apocrypha')) + return self.name def create_book(self, name, abbrev, testament=1): """ @@ -284,26 +277,32 @@ class BibleDB(QtCore.QObject, Manager): return verse def create_meta(self, key, value): + """ + Utility method to save BibleMeta objects in a Bible database + + ``key`` + The key for this instance + + ``value`` + The value for this instance + """ log.debug(u'save_meta %s/%s', key, value) self.insert_object(BibleMeta.populate(key=key, value=value)) def get_book(self, book): - log.debug(u'BibleDb.get_book("%s")', book) - db_book = self.session.query(Book)\ - .filter(Book.name.like(book + u'%'))\ - .first() - if db_book is None: - db_book = self.session.query(Book)\ - .filter(Book.abbreviation.like(book + u'%'))\ - .first() - return db_book + """ + Return a book object from the database - def get_chapter(self, id, chapter): - log.debug(u'BibleDB.get_chapter("%s", %s)', id, chapter) - return self.session.query(Verse)\ - .filter_by(chapter=chapter)\ - .filter_by(book_id=id)\ - .first() + ``book`` + The name of the book to return + """ + log.debug(u'BibleDb.get_book("%s")', book) + db_book = self.session.query(Book).filter( + Book.name.like(book + u'%')).first() + if db_book is None: + db_book = self.session.query(Book).filter( + Book.abbreviation.like(book + u'%')).first() + return db_book def get_verses(self, reference_list): """ @@ -370,6 +369,12 @@ class BibleDB(QtCore.QObject, Manager): return verses def get_chapter_count(self, book): + """ + Return the number of chapters in a book + + ``book`` + The book to get the chapter count for + """ log.debug(u'BibleDB.get_chapter_count("%s")', book) count = self.session.query(Verse.chapter).join(Book)\ .filter(Book.name==book)\ @@ -380,6 +385,15 @@ class BibleDB(QtCore.QObject, Manager): return count def get_verse_count(self, book, chapter): + """ + Return the number of verses in a chapter + + ``book`` + The book containing the chapter + + ``chapter`` + The chapter to get the verse count for + """ log.debug(u'BibleDB.get_verse_count("%s", %s)', book, chapter) count = self.session.query(Verse).join(Book)\ .filter(Book.name==book)\ @@ -391,6 +405,9 @@ class BibleDB(QtCore.QObject, Manager): return count def dump_bible(self): + """ + Utility debugging method to dump the contents of a bible + """ log.debug(u'.........Dumping Bible Database') log.debug('...............................Books ') books = self.session.query(Book).all() diff --git a/openlp/plugins/custom/lib/db.py b/openlp/plugins/custom/lib/db.py index 277f3a7e8..39d935d9a 100644 --- a/openlp/plugins/custom/lib/db.py +++ b/openlp/plugins/custom/lib/db.py @@ -34,7 +34,7 @@ from openlp.core.lib.db import BaseModel, init_db class CustomSlide(BaseModel): """ - Custom Slide model + CustomSlide model """ pass From b7e3ec4441bc386ed2a93317fe966a655e4c27ee Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Tue, 15 Jun 2010 19:08:02 +0100 Subject: [PATCH 07/49] RFC: Refactor a filter method --- openlp/core/lib/db.py | 12 ++++++++++++ openlp/plugins/songs/lib/manager.py | 20 +------------------- openlp/plugins/songs/lib/songimport.py | 12 ++++++------ 3 files changed, 19 insertions(+), 25 deletions(-) diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index 4c7b1ca23..87200faee 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -166,6 +166,18 @@ class Manager(object): else: return self.session.query(object_class).get(id) + def get_object_filtered(self, object_class, filter_string): + """ + Returns an object matching specified criteria + + ``object_class`` + The type of object to return + + ``filter_string`` + The criteria to select the object by + """ + return self.session.query(object_class).filter(filter_string).first() + def get_all_objects(self, object_class, order_by_ref=None): """ Returns all the objects from the database diff --git a/openlp/plugins/songs/lib/manager.py b/openlp/plugins/songs/lib/manager.py index f2edf6e75..10ec5aa34 100644 --- a/openlp/plugins/songs/lib/manager.py +++ b/openlp/plugins/songs/lib/manager.py @@ -26,7 +26,7 @@ import logging from openlp.core.lib.db import Manager -from openlp.plugins.songs.lib.db import init_schema, Song, Author, Topic, Book +from openlp.plugins.songs.lib.db import init_schema, Song, Author #from openlp.plugins.songs.lib import OpenLyricsSong, OpenSongSong, CCLISong, \ # CSVSong @@ -114,21 +114,3 @@ class SongManager(Manager): """ return self.session.query(Author).filter(Author.display_name.like( u'%' + keywords + u'%')).order_by(Author.display_name.asc()).all() - - def get_author_by_name(self, name): - """ - Get author by display name - """ - return self.session.query(Author).filter_by(display_name=name).first() - - def get_topic_by_name(self, name): - """ - Get topic by name - """ - return self.session.query(Topic).filter_by(name=name).first() - - def get_book_by_name(self, name): - """ - Get book by name - """ - return self.session.query(Book).filter_by(name=name).first() diff --git a/openlp/plugins/songs/lib/songimport.py b/openlp/plugins/songs/lib/songimport.py index 9b47a7501..814d13d5e 100644 --- a/openlp/plugins/songs/lib/songimport.py +++ b/openlp/plugins/songs/lib/songimport.py @@ -277,7 +277,6 @@ class SongImport(object): if len(self.authors) == 0: self.authors.append(u'Author unknown') self.commit_song() - #self.print_song() def commit_song(self): """ @@ -316,7 +315,8 @@ class SongImport(object): song.theme_name = self.theme_name song.ccli_number = self.ccli_number for authortext in self.authors: - author = self.manager.get_author_by_name(authortext) + filter_string = u'display_name=%s' % authortext + author = self.manager.get_object_filtered(Author, filter_string) if author is None: author = Author() author.display_name = authortext @@ -325,7 +325,8 @@ class SongImport(object): self.manager.insert_object(author) song.authors.append(author) if self.song_book_name: - song_book = self.manager.get_book_by_name(self.song_book_name) + filter_string = u'name=%s' % self.song_book_name + song_book = self.manager.get_object_filtered(Book, filter_string) if song_book is None: song_book = Book() song_book.name = self.song_book_name @@ -333,7 +334,8 @@ class SongImport(object): self.manager.insert_object(song_book) song.song_book_id = song_book.id for topictext in self.topics: - topic = self.manager.get_topic_by_name(topictext) + filter_string = u'name=%s' % topictext + topic = self.manager.get_object_filtered(Topic, filter_string) if topic is None: topic = Topic() topic.name = topictext @@ -370,5 +372,3 @@ class SongImport(object): print u'THEME: ' + self.theme_name if self.ccli_number: print u'CCLI: ' + self.ccli_number - - From 7f88043177999e3538e610515961568a8c29e80b Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Fri, 18 Jun 2010 02:26:01 +0100 Subject: [PATCH 08/49] RFC: Cleanups --- openlp/core/lib/db.py | 72 +++++++++---------- openlp/migration/migratebibles.py | 5 +- openlp/migration/migratesongs.py | 16 +++-- .../plugins/bibles/forms/importwizardform.py | 4 +- openlp/plugins/bibles/lib/db.py | 1 + openlp/plugins/custom/customplugin.py | 6 +- openlp/plugins/custom/forms/editcustomform.py | 3 +- openlp/plugins/songs/songsplugin.py | 4 +- openlp/plugins/songusage/lib/__init__.py | 6 +- 9 files changed, 63 insertions(+), 54 deletions(-) diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index 87200faee..19cd3eadf 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -26,6 +26,7 @@ The :mod:`db` module provides the core database functionality for OpenLP """ import logging +import os from PyQt4 import QtCore from sqlalchemy import create_engine, MetaData @@ -55,11 +56,34 @@ def init_db(url, auto_flush=True, auto_commit=False): autocommit=auto_commit, bind=engine)) return session, metadata +def delete_database(plugin_name, db_file_name=None): + """ + Remove a database file from the system. + + ``plugin_name`` + The name of the plugin to remove the database for + + ``db_file_name`` + The database file name. Defaults to None resulting in the + plugin_name being used. + """ + db_file_path = None + if db_file_name: + db_file_path = os.path.join( + AppLocation.get_section_data_path(plugin_name), db_file_name) + else: + db_file_path = os.path.join( + AppLocation.get_section_data_path(plugin_name), plugin_name) + try: + os.remove(db_file_path) + return True + except OSError: + return False + class BaseModel(object): """ BaseModel provides a base object with a set of generic functions """ - @classmethod def populate(cls, **kwargs): """ @@ -111,30 +135,6 @@ class Manager(object): settings.endGroup() self.session = init_schema(self.db_url) - def delete_database(self, plugin_name, db_file_name=None): - """ - Remove a database file from the system. - - ``plugin_name`` - The name of the plugin to remove the database for - - ``db_file_name`` - The database file name. Defaults to None resulting in the - plugin_name being used. - """ - db_file_path = None - if db_file_name: - db_file_path = os.path.join( - AppLocation.get_section_data_path(plugin_name), db_file_name) - else: - db_file_path = os.path.join( - AppLocation.get_section_data_path(plugin_name), plugin_name) - try: - os.remove(db_file_path) - return True - except OSError: - return False - def insert_object(self, object_instance): """ Save an object to the database @@ -151,20 +151,20 @@ class Manager(object): log.exception(u'Object save failed') return False - def get_object(self, object_class, id=None): + def get_object(self, object_class, key=None): """ Return the details of an object ``object_class`` The type of object to return - ``id`` - The unique reference for the class instance to return + ``key`` + The unique reference or primary key for the instance to return """ - if not id: + if not key: return object_class() else: - return self.session.query(object_class).get(id) + return self.session.query(object_class).get(key) def get_object_filtered(self, object_class, filter_string): """ @@ -204,20 +204,20 @@ class Manager(object): """ return self.session.query(object_class).filter(filter_string).all() - def delete_object(self, object_class, id): + def delete_object(self, object_class, key): """ Delete an object from the database ``object_class`` The type of object to delete - ``id`` - The unique reference for the class instance to be deleted + ``key`` + The unique reference or primary key for the instance to be deleted """ - if id != 0: - object = self.get_object(object_class, id) + if key != 0: + object_instance = self.get_object(object_class, key) try: - self.session.delete(object) + self.session.delete(object_instance) self.session.commit() return True except InvalidRequestError: diff --git a/openlp/migration/migratebibles.py b/openlp/migration/migratebibles.py index 411da0ce6..37a0df933 100644 --- a/openlp/migration/migratebibles.py +++ b/openlp/migration/migratebibles.py @@ -27,6 +27,7 @@ import os import sys import sqlite3 +from sqlalchemy import Column, MetaData, Table, types from sqlalchemy.exceptions import InvalidRequestError from sqlalchemy.orm import mapper @@ -34,7 +35,9 @@ from openlp.core.lib import SettingsManager from openlp.core.lib.db import BaseModel from openlp.core.utils import AppLocation from openlp.plugins.bibles.lib.db import BibleMeta, Book, Testament, Verse - + +metadata = MetaData() + class TBibleMeta(BaseModel): """ Bible Meta Data diff --git a/openlp/migration/migratesongs.py b/openlp/migration/migratesongs.py index 0ede63387..0a6912c78 100644 --- a/openlp/migration/migratesongs.py +++ b/openlp/migration/migratesongs.py @@ -27,14 +27,16 @@ import os import sys import sqlite3 -from sqlalchemy import create_engine +from sqlalchemy import Column, create_engine, MetaData, Table, types from sqlalchemy.exceptions import InvalidRequestError from sqlalchemy.orm import scoped_session, sessionmaker, mapper, relation from openlp.core.lib import SettingsManager from openlp.core.lib.db import BaseModel from openlp.core.utils import AppLocation -from openlp.plugins.songs.lib.db import songs_table, Song, Author, Topic, Book +from openlp.plugins.songs.lib.db import Author, Book, Song, Topic + +metadata = MetaData() def init_models(url): engine = create_engine(url) @@ -57,14 +59,14 @@ def init_models(url): temp_authors_table = Table(u'authors_temp', metadata, Column(u'authorid', types.Integer, primary_key=True), - Column(u'authorname', String(40)) + Column(u'authorname', types.Unicode(40)) ) temp_songs_table = Table(u'songs_temp', metadata, Column(u'songid', types.Integer, primary_key=True), - Column(u'songtitle', String(60)), + Column(u'songtitle', types.Unicode(60)), Column(u'lyrics', types.UnicodeText), - Column(u'copyrightinfo', String(255)), + Column(u'copyrightinfo', types.Unicode(255)), Column(u'settingsid', types.Integer) ) @@ -101,8 +103,8 @@ class MigrateSongs(object): def process(self): self.display.output(u'Songs processing started') - for f in self.database_files: - self.v_1_9_0(f) + for data_file in self.database_files: + self.v_1_9_0(data_file) self.display.output(u'Songs processing finished') def v_1_9_0(self, database): diff --git a/openlp/plugins/bibles/forms/importwizardform.py b/openlp/plugins/bibles/forms/importwizardform.py index ac6c0995e..bb6398bb1 100644 --- a/openlp/plugins/bibles/forms/importwizardform.py +++ b/openlp/plugins/bibles/forms/importwizardform.py @@ -32,6 +32,7 @@ from PyQt4 import QtCore, QtGui from bibleimportwizard import Ui_BibleImportWizard from openlp.core.lib import Receiver, SettingsManager, translate +from openlp.core.lib.db import delete_database from openlp.core.utils import AppLocation from openlp.plugins.bibles.lib.manager import BibleFormat @@ -449,8 +450,7 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): self.ImportProgressLabel.setText( translate(u'BiblesPlugin.ImportWizardForm', u'Your Bible import failed.')) - importer.delete_database(self.bibleplugin.settingsSection, - importer.file) + delete_database(self.bibleplugin.settingsSection, importer.file) def postImport(self): self.ImportProgressBar.setValue(self.ImportProgressBar.maximum()) diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py index e6178a098..16c3d918d 100644 --- a/openlp/plugins/bibles/lib/db.py +++ b/openlp/plugins/bibles/lib/db.py @@ -154,6 +154,7 @@ class BibleDB(QtCore.QObject, Manager): Manager.__init__(self, u'bibles', init_schema, self.file) if u'file' in kwargs: self.get_name() + self.wizard = None def stop_import(self): """ diff --git a/openlp/plugins/custom/customplugin.py b/openlp/plugins/custom/customplugin.py index a63bbdf47..9de676bf6 100644 --- a/openlp/plugins/custom/customplugin.py +++ b/openlp/plugins/custom/customplugin.py @@ -26,6 +26,7 @@ import logging from forms import EditCustomForm + from openlp.core.lib import Plugin, build_icon, PluginStatus, translate from openlp.core.lib.db import Manager from openlp.plugins.custom.lib import CustomMediaItem, CustomTab @@ -77,7 +78,8 @@ class CustomPlugin(Plugin): return about_text def can_delete_theme(self, theme): - filter = u'theme_name=%s' % theme - if not self.custommanager.get_all_objects_filtered(CustomSlide, filter): + filter_string = u'theme_name=%s' % theme + if not self.custommanager.get_all_objects_filtered(CustomSlide, + filter_string): return True return False diff --git a/openlp/plugins/custom/forms/editcustomform.py b/openlp/plugins/custom/forms/editcustomform.py index 2b8a5bc03..01296a329 100644 --- a/openlp/plugins/custom/forms/editcustomform.py +++ b/openlp/plugins/custom/forms/editcustomform.py @@ -167,8 +167,7 @@ class EditCustomForm(QtGui.QDialog, Ui_customEditDialog): u'utf-8') self.customSlide.theme_name = unicode(self.ThemeComboBox.currentText(), u'utf-8') - self.custommanager.insert_object(self.customSlide) - return True + return self.custommanager.insert_object(self.customSlide) def onUpButtonPressed(self): selectedRow = self.VerseListView.currentRow() diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py index 2462502b9..3dd467ad6 100644 --- a/openlp/plugins/songs/songsplugin.py +++ b/openlp/plugins/songs/songsplugin.py @@ -197,7 +197,7 @@ class SongsPlugin(Plugin): return about_text def can_delete_theme(self, theme): - filter = u'theme_name=%s' % theme - if not self.manager.get_all_objects_filtered(Song, filter): + filter_string = u'theme_name=%s' % theme + if not self.manager.get_all_objects_filtered(Song, filter_string): return True return False diff --git a/openlp/plugins/songusage/lib/__init__.py b/openlp/plugins/songusage/lib/__init__.py index 50bba3ddc..ae8425317 100644 --- a/openlp/plugins/songusage/lib/__init__.py +++ b/openlp/plugins/songusage/lib/__init__.py @@ -22,5 +22,7 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### - -from manager import SongUsageManager +""" +The :mod:`lib` module contains the library functions for the songusage plugin. +""" +from openlp.plugins.songusage.lib.manager import SongUsageManager From d9d976d64bfd05d6417d31197c509e5306a70743 Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Tue, 22 Jun 2010 16:09:49 +0100 Subject: [PATCH 09/49] Cleanup and import fix --- openlp/plugins/bibles/lib/db.py | 3 ++- openlp/plugins/custom/lib/mediaitem.py | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py index d7f59307e..d2a62ec59 100644 --- a/openlp/plugins/bibles/lib/db.py +++ b/openlp/plugins/bibles/lib/db.py @@ -32,7 +32,8 @@ from sqlalchemy import Column, ForeignKey, or_, Table, types from sqlalchemy.orm import class_mapper, mapper, relation from sqlalchemy.orm.exc import UnmappedClassError -from openlp.core.lib.db import BaseModel, init_db, Manager, translate +from openlp.core.lib import translate +from openlp.core.lib.db import BaseModel, init_db, Manager log = logging.getLogger(__name__) diff --git a/openlp/plugins/custom/lib/mediaitem.py b/openlp/plugins/custom/lib/mediaitem.py index 00ba3561c..b94da35d5 100644 --- a/openlp/plugins/custom/lib/mediaitem.py +++ b/openlp/plugins/custom/lib/mediaitem.py @@ -86,10 +86,10 @@ class CustomMediaItem(MediaManagerItem): def loadCustomListView(self, list): self.ListView.clear() - for CustomSlide in list: - custom_name = QtGui.QListWidgetItem(CustomSlide.title) + for customSlide in list: + custom_name = QtGui.QListWidgetItem(customSlide.title) custom_name.setData( - QtCore.Qt.UserRole, QtCore.QVariant(CustomSlide.id)) + QtCore.Qt.UserRole, QtCore.QVariant(customSlide.id)) self.ListView.addItem(custom_name) def onNewClick(self): From d2af535c709a35967a6951ce9084cca0d9d63b3d Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Wed, 23 Jun 2010 06:13:32 +0100 Subject: [PATCH 10/49] Start to clean up display code. Make Video Hide / Reappear Add Audio player to play audio with no display Replace Labels with QGraphicXXXXItems --- openlp/core/ui/maindisplay.py | 210 +++++++++++++++++++++++++++------- 1 file changed, 169 insertions(+), 41 deletions(-) diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index a3c444097..8e996a147 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -45,6 +45,7 @@ class DisplayManager(QtGui.QWidget): QtGui.QWidget.__init__(self) self.screens = screens self.videoDisplay = VideoDisplay(self, screens) + self.audioPlayer = AudioPlayer(self) self.mainDisplay = MainDisplay(self, screens) def setup(self): @@ -53,10 +54,11 @@ class DisplayManager(QtGui.QWidget): def close(self): self.videoDisplay.close() + self.audioPlayer.close() self.mainDisplay.close() -class DisplayWidget(QtGui.QWidget): +class DisplayWidget(QtGui.QGraphicsView): """ Customised version of QTableWidget which can respond to keyboard events. @@ -116,22 +118,23 @@ class MainDisplay(DisplayWidget): """ log.debug(u'Initialisation started') DisplayWidget.__init__(self, parent) - self.setWindowFlags(QtCore.Qt.Window | QtCore.Qt.FramelessWindowHint) - self.setWindowState(QtCore.Qt.WindowFullScreen) +# self.setWindowFlags(QtCore.Qt.Window | QtCore.Qt.FramelessWindowHint) +# self.setWindowState(QtCore.Qt.WindowFullScreen) + self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) + self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self.parent = parent - self.setWindowTitle(u'OpenLP Display') + #self.setWindowTitle(u'OpenLP Display') # WA_TranslucentBackground is not available in QT4.4 try: self.setAttribute(QtCore.Qt.WA_TranslucentBackground) except AttributeError: pass self.screens = screens - self.display_image = QtGui.QLabel(self) - self.display_image.setScaledContents(True) - self.display_text = QtGui.QLabel(self) - self.display_text.setScaledContents(True) - self.display_alert = QtGui.QLabel(self) - self.display_alert.setScaledContents(True) + self.setupScene() + self.setupImage() + self.setupText() + self.setupAlert() + self.setupBlank() self.primary = True self.blankFrame = None self.frame = None @@ -153,11 +156,11 @@ class MainDisplay(DisplayWidget): self.setVisible(False) self.screen = self.screens.current #Sort out screen locations and sizes - self.display_alert.setGeometry(self.screen[u'size']) - self.display_image.resize( - self.screen[u'size'].width(), self.screen[u'size'].height()) - self.display_text.resize( - self.screen[u'size'].width(), self.screen[u'size'].height()) +# self.display_alert.setGeometry(self.screen[u'size']) +# self.display_image.resize( +# self.screen[u'size'].width(), self.screen[u'size'].height()) +# self.display_text.resize( +# self.screen[u'size'].width(), self.screen[u'size'].height()) self.setGeometry(self.screen[u'size']) #Build a custom splash screen self.InitialFrame = QtGui.QImage( @@ -186,8 +189,8 @@ class MainDisplay(DisplayWidget): self.transparent = QtGui.QPixmap( self.screen[u'size'].width(), self.screen[u'size'].height()) self.transparent.fill(QtCore.Qt.transparent) - self.display_alert.setPixmap(self.transparent) - self.display_text.setPixmap(self.transparent) +# self.display_alert.setPixmap(self.transparent) +# self.display_text.setPixmap(self.transparent) self.frameView(self.transparent) # To display or not to display? if not self.screen[u'primary']: @@ -197,6 +200,37 @@ class MainDisplay(DisplayWidget): self.setVisible(False) self.primary = True + def setupScene(self): + self.scene = QtGui.QGraphicsScene(self) + self.scene.setSceneRect(0,0,self.size().width()-2, self.size().height()-2) + self.setScene(self.scene) + + def setupImage(self): + self.display_image = QtGui.QGraphicsPixmapItem() + self.display_image.setZValue(2) + self.scene.addItem(self.display_image) + + def setupText(self): + #self.display_text = QtGui.QGraphicsTextItem() + self.display_text = QtGui.QGraphicsPixmapItem() + self.display_text.setPos(0,self.size().height()/2) + #self.display_text.setTextWidth(self.size().width()) + self.display_text.setZValue(4) + self.scene.addItem(self.display_text) + + def setupAlert(self): + self.alertText = QtGui.QGraphicsTextItem() + self.alertText.setPos(0,self.size().height()/2) + self.alertText.setPos(0,self.size().height() - 76) + self.alertText.setTextWidth(self.size().width()) + self.alertText.setZValue(8) + self.scene.addItem(self.alertText) + + def setupBlank(self): + self.display_blank = QtGui.QGraphicsPixmapItem() + self.display_blank.setZValue(10) + self.scene.addItem(self.display_blank) + def resetDisplay(self): log.debug(u'resetDisplay') Receiver.send_message(u'slidecontroller_live_stop_loop') @@ -219,27 +253,21 @@ class MainDisplay(DisplayWidget): log.debug(u'hideDisplay mode = %d', mode) self.storeImage = QtGui.QPixmap(self.display_image.pixmap()) self.storeText = QtGui.QPixmap(self.display_text.pixmap()) - self.display_alert.setPixmap(self.transparent) - self.display_text.setPixmap(self.transparent) + #self.display_alert.setPixmap(self.transparent) + #self.display_text.setPixmap(self.transparent) if mode == HideMode.Screen: - self.display_image.setPixmap(self.transparent) + #self.display_image.setPixmap(self.transparent) + self.setVisible(False) elif mode == HideMode.Blank: - self.display_image.setPixmap( + self.display_blank.setPixmap( QtGui.QPixmap.fromImage(self.blankFrame)) else: if self.parent.renderManager.renderer.bg_frame: - self.display_image.setPixmap(QtGui.QPixmap.fromImage( + self.display_blank.setPixmap(QtGui.QPixmap.fromImage( self.parent.renderManager.renderer.bg_frame)) else: - self.display_image.setPixmap( + self.display_blank.setPixmap( QtGui.QPixmap.fromImage(self.blankFrame)) - self.moveToTop() - - def moveToTop(self): - log.debug(u'moveToTop') - self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint | - QtCore.Qt.FramelessWindowHint | QtCore.Qt.Dialog) - self.show() def showDisplay(self): """ @@ -255,7 +283,6 @@ class MainDisplay(DisplayWidget): self.display_text.setPixmap(self.storeText) self.storeImage = None self.store = None - self.moveToTop() Receiver.send_message(u'maindisplay_active') def addImageWithText(self, frame): @@ -263,7 +290,6 @@ class MainDisplay(DisplayWidget): frame = resize_image( frame, self.screen[u'size'].width(), self.screen[u'size'].height()) self.display_image.setPixmap(QtGui.QPixmap.fromImage(frame)) - self.moveToTop() def setAlertSize(self, top, height): log.debug(u'setAlertSize') @@ -277,7 +303,6 @@ class MainDisplay(DisplayWidget): self.display_alert.setPixmap(self.transparent) else: self.display_alert.setPixmap(frame) - self.moveToTop() def frameView(self, frame, transition=False, display=True): """ @@ -345,11 +370,11 @@ class VideoDisplay(Phonon.VideoWidget): Phonon.createPath(self.mediaObject, self) Phonon.createPath(self.mediaObject, self.audioObject) flags = QtCore.Qt.FramelessWindowHint | QtCore.Qt.Dialog - # WindowsStaysOnBottomHint is not available in QT4.4 - try: - flags = flags | QtCore.Qt.WindowStaysOnBottomHint - except AttributeError: - pass +# # WindowsStaysOnBottomHint is not available in QT4.4 +# try: +# flags = flags | QtCore.Qt.WindowStaysOnBottomHint +# except AttributeError: +# pass self.setWindowFlags(flags) QtCore.QObject.connect(Receiver.get_receiver(), @@ -392,13 +417,22 @@ class VideoDisplay(Phonon.VideoWidget): #Sort out screen locations and sizes self.setGeometry(self.screen[u'size']) # To display or not to display? - if not self.screen[u'primary'] and self.isVisible(): - self.showFullScreen() + if not self.screen[u'primary']: # and self.isVisible(): + #self.showFullScreen() + self.setVisible(True) self.primary = False else: self.setVisible(False) self.primary = True + def closeEvent(self, event): + """ + Shutting down so clean up connections + """ + self.onMediaStop() + for pth in self.outputPaths(): + disconnected = pth.disconnect() + def onMediaBackground(self, message=None): """ Play a video triggered from the video plugin with the @@ -442,7 +476,7 @@ class VideoDisplay(Phonon.VideoWidget): log.debug(u'VideoDisplay _play called') self.mediaObject.play() self.setVisible(True) - self.showFullScreen() + #self.showFullScreen() def onMediaPause(self): """ @@ -484,3 +518,97 @@ class VideoDisplay(Phonon.VideoWidget): if self.hidden: self.hidden = False self._play() + +class AudioPlayer(QtCore.QObject): + """ + This Class will play audio only allowing components to work witn a + soundtrack which does not take over the user interface. + """ + log.info(u'AudioPlayer Loaded') + + def __init__(self, parent): + """ + The constructor for the display form. + + ``parent`` + The parent widget. + + ``screens`` + The list of screens. + """ + log.debug(u'AudioPlayer Initialisation started') + QtCore.QObject.__init__(self) + self.parent = parent + self.message = None + self.mediaObject = Phonon.MediaObject() + self.audioObject = Phonon.AudioOutput(Phonon.VideoCategory) + Phonon.createPath(self.mediaObject, self.audioObject) + +# QtCore.QObject.connect(Receiver.get_receiver(), +# QtCore.SIGNAL(u'videodisplay_start'), self.onMediaQueue) +# QtCore.QObject.connect(Receiver.get_receiver(), +# QtCore.SIGNAL(u'videodisplay_play'), self.onMediaPlay) +# QtCore.QObject.connect(Receiver.get_receiver(), +# QtCore.SIGNAL(u'videodisplay_pause'), self.onMediaPause) +# QtCore.QObject.connect(Receiver.get_receiver(), +# QtCore.SIGNAL(u'videodisplay_stop'), self.onMediaStop) +# QtCore.QObject.connect(Receiver.get_receiver(), +# QtCore.SIGNAL(u'videodisplay_background'), self.onMediaBackground) +# QtCore.QObject.connect(Receiver.get_receiver(), +# QtCore.SIGNAL(u'config_updated'), self.setup) +# QtCore.QObject.connect(self.mediaObject, +# QtCore.SIGNAL(u'finished()'), self.onMediaBackground) + + def setup(self): + """ + Sets up the Audio Player for use + """ + log.debug(u'AudioPlayer Setup') + + def close(self): + """ + Shutting down so clean up connections + """ + self.onMediaStop() + for pth in self.mediaObject.outputPaths(): + disconnected = pth.disconnect() + + def onMediaQueue(self, message): + """ + Set up a video to play from the serviceitem. + """ + log.debug(u'AudioPlayer Queue new media message %s' % message) + file = os.path.join(message[0].get_frame_path(), + message[0].get_frame_title()) + self.mediaObject.setCurrentSource(Phonon.MediaSource(file)) + self.onMediaPlay() + + def onMediaPlay(self): + """ + We want to play the play so start it + """ + log.debug(u'AudioPlayer _play called') + self.mediaObject.play() + + def onMediaPause(self): + """ + Pause the Audio + """ + log.debug(u'AudioPlayer Media paused by user') + self.mediaObject.pause() + + def onMediaStop(self): + """ + Stop the Audio and clean up + """ + log.debug(u'AudioPlayer Media stopped by user') + self.message = None + self.mediaObject.stop() + self.onMediaFinish() + + def onMediaFinish(self): + """ + Clean up the Object queue + """ + log.debug(u'AudioPlayer Reached end of media playlist') + self.mediaObject.clearQueue() From b4626d80eb91694186de52358f64104c26566bd8 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Thu, 24 Jun 2010 19:06:34 +0100 Subject: [PATCH 11/49] Screen sizes now work --- openlp/core/ui/maindisplay.py | 34 ++++++++++++++----------------- openlp/core/ui/slidecontroller.py | 2 +- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 8e996a147..267de9bf8 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -118,12 +118,10 @@ class MainDisplay(DisplayWidget): """ log.debug(u'Initialisation started') DisplayWidget.__init__(self, parent) -# self.setWindowFlags(QtCore.Qt.Window | QtCore.Qt.FramelessWindowHint) -# self.setWindowState(QtCore.Qt.WindowFullScreen) + self.setWindowFlags(QtCore.Qt.Window | QtCore.Qt.FramelessWindowHint) self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self.parent = parent - #self.setWindowTitle(u'OpenLP Display') # WA_TranslucentBackground is not available in QT4.4 try: self.setAttribute(QtCore.Qt.WA_TranslucentBackground) @@ -146,6 +144,7 @@ class MainDisplay(DisplayWidget): QtCore.SIGNAL(u'maindisplay_show'), self.showDisplay) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'videodisplay_background'), self.hideDisplayForVideo) + self.setVisible(False) def setup(self): """ @@ -156,12 +155,8 @@ class MainDisplay(DisplayWidget): self.setVisible(False) self.screen = self.screens.current #Sort out screen locations and sizes -# self.display_alert.setGeometry(self.screen[u'size']) -# self.display_image.resize( -# self.screen[u'size'].width(), self.screen[u'size'].height()) -# self.display_text.resize( -# self.screen[u'size'].width(), self.screen[u'size'].height()) self.setGeometry(self.screen[u'size']) + self.scene.setSceneRect(0,0,self.size().width(), self.size().height()) #Build a custom splash screen self.InitialFrame = QtGui.QImage( self.screen[u'size'].width(), @@ -191,10 +186,10 @@ class MainDisplay(DisplayWidget): self.transparent.fill(QtCore.Qt.transparent) # self.display_alert.setPixmap(self.transparent) # self.display_text.setPixmap(self.transparent) - self.frameView(self.transparent) + #self.frameView(self.transparent) # To display or not to display? if not self.screen[u'primary']: - self.showFullScreen() + self.setVisible(True) self.primary = False else: self.setVisible(False) @@ -202,7 +197,7 @@ class MainDisplay(DisplayWidget): def setupScene(self): self.scene = QtGui.QGraphicsScene(self) - self.scene.setSceneRect(0,0,self.size().width()-2, self.size().height()-2) + self.scene.setSceneRect(0,0,self.size().width(), self.size().height()) self.setScene(self.scene) def setupImage(self): @@ -213,7 +208,7 @@ class MainDisplay(DisplayWidget): def setupText(self): #self.display_text = QtGui.QGraphicsTextItem() self.display_text = QtGui.QGraphicsPixmapItem() - self.display_text.setPos(0,self.size().height()/2) + #self.display_text.setPos(0,self.size().height()/2) #self.display_text.setTextWidth(self.size().width()) self.display_text.setZValue(4) self.scene.addItem(self.display_text) @@ -278,9 +273,9 @@ class MainDisplay(DisplayWidget): log.debug(u'showDisplay') if self.storeImage: self.display_image.setPixmap(self.storeImage) - self.display_alert.setPixmap(self.transparent) if self.storeText: self.display_text.setPixmap(self.storeText) + #self.display_alert.setPixmap(self.transparent) self.storeImage = None self.store = None Receiver.send_message(u'maindisplay_active') @@ -293,9 +288,9 @@ class MainDisplay(DisplayWidget): def setAlertSize(self, top, height): log.debug(u'setAlertSize') - self.display_alert.setGeometry( - QtCore.QRect(0, top, - self.screen[u'size'].width(), height)) +# self.display_alert.setGeometry( +# QtCore.QRect(0, top, +# self.screen[u'size'].width(), height)) def addAlertImage(self, frame, blank=False): log.debug(u'addAlertImage') @@ -311,13 +306,14 @@ class MainDisplay(DisplayWidget): ``frame`` Image frame to be rendered """ - log.debug(u'frameView %d' % (display)) + log.debug(u'frameView %d' % display) + print "display ", display if display: if transition: if self.frame is not None: self.display_text.setPixmap( QtGui.QPixmap.fromImage(self.frame)) - self.repaint() + self.update() self.frame = None if frame[u'trans'] is not None: self.display_text.setPixmap( @@ -419,7 +415,7 @@ class VideoDisplay(Phonon.VideoWidget): # To display or not to display? if not self.screen[u'primary']: # and self.isVisible(): #self.showFullScreen() - self.setVisible(True) + self.setVisible(False) self.primary = False else: self.setVisible(False) diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 87f6f20fe..1b9e4578d 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -780,7 +780,7 @@ class SlideController(QtGui.QWidget): log.log( 15, u'Slide Rendering took %4s' % (time.time() - before)) if self.isLive: - self.mainDisplay.frameView(frame, True, self.canDisplay) + self.mainDisplay.frameView(frame, True)#, self.canDisplay) self.selectedRow = row Receiver.send_message(u'slidecontroller_%s_changed' % self.typePrefix, row) From 780e45891c778a8c675fcd426f1dd0818f2ba1a8 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Fri, 25 Jun 2010 21:44:13 +0100 Subject: [PATCH 12/49] More fixes --- openlp/core/ui/maindisplay.py | 15 ++++++++------- openlp/core/ui/slidecontroller.py | 10 ++++++++++ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 267de9bf8..0196732fe 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -195,6 +195,7 @@ class MainDisplay(DisplayWidget): self.setVisible(False) self.primary = True + def setupScene(self): self.scene = QtGui.QGraphicsScene(self) self.scene.setSceneRect(0,0,self.size().width(), self.size().height()) @@ -232,7 +233,8 @@ class MainDisplay(DisplayWidget): if self.primary: self.setVisible(False) else: - self.showFullScreen() + self.setVisible(True) + #self.showFullScreen() def hideDisplayForVideo(self): """ @@ -307,7 +309,6 @@ class MainDisplay(DisplayWidget): Image frame to be rendered """ log.debug(u'frameView %d' % display) - print "display ", display if display: if transition: if self.frame is not None: @@ -332,7 +333,7 @@ class MainDisplay(DisplayWidget): self.display_frame = frame if not self.isVisible() and self.screens.display: self.setVisible(True) - self.showFullScreen() + #self.showFullScreen() else: self.storeText = QtGui.QPixmap.fromImage(frame[u'main']) @@ -367,10 +368,10 @@ class VideoDisplay(Phonon.VideoWidget): Phonon.createPath(self.mediaObject, self.audioObject) flags = QtCore.Qt.FramelessWindowHint | QtCore.Qt.Dialog # # WindowsStaysOnBottomHint is not available in QT4.4 -# try: -# flags = flags | QtCore.Qt.WindowStaysOnBottomHint -# except AttributeError: -# pass + try: + flags = flags | QtCore.Qt.WindowStaysOnBottomHint + except AttributeError: + pass self.setWindowFlags(flags) QtCore.QObject.connect(Receiver.get_receiver(), diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 66cd70f73..c1757c2f8 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -253,6 +253,16 @@ class SlideController(QtGui.QWidget): translate('SlideController', 'Start playing media'), self.onMediaStop) if self.isLive: + self.button = QtGui.QToolButton(self.Toolbar) + self.Toolbar.addToolbarWidget(u'Hide Menu', self.button) + self.button.setText(translate('SlideController', 'Hide')) + self.menu = QtGui.QMenu(self.button) + blank_screen = QtGui.QAction(QtGui.QIcon( u':/slides/slide_blank.png'), u'Blank Screen', self.button) + theme_screen = QtGui.QAction(QtGui.QIcon(u':/slides/slide_theme.png'), u'Blank to Theme', self.button) + desktop_screen = QtGui.QAction(QtGui.QIcon(u':/slides/slide_desktop.png'), u'Show Desktop', self.button) + self.menu.addAction(blank_screen) + self.menu.addAction(theme_screen) + self.menu.addAction(desktop_screen) self.blankButton = self.Mediabar.addToolbarButton( u'Blank Screen', u':/slides/slide_blank.png', translate('SlideController', 'Blank Screen'), From 90cf4428c40610ff1a96ae1ac446d7c16be41582 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sat, 26 Jun 2010 07:24:38 +0100 Subject: [PATCH 13/49] Hide buttons to menu part 1 --- openlp/core/ui/slidecontroller.py | 75 ++++++++++++++----------------- 1 file changed, 34 insertions(+), 41 deletions(-) diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index c1757c2f8..3601df82b 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -196,18 +196,25 @@ class SlideController(QtGui.QWidget): self.onSlideSelectedLast) if self.isLive: self.Toolbar.addToolbarSeparator(u'Close Separator') - self.blankButton = self.Toolbar.addToolbarButton( - u'Blank Screen', u':/slides/slide_blank.png', - translate('SlideController', 'Blank Screen'), - self.onBlankDisplay, True) - self.themeButton = self.Toolbar.addToolbarButton( - u'Display Theme', u':/slides/slide_theme.png', - translate('SlideController', 'Theme Screen'), - self.onThemeDisplay, True) - self.hideButton = self.Toolbar.addToolbarButton( - u'Hide screen', u':/slides/slide_desktop.png', - translate('SlideController', 'Hide Screen'), - self.onHideDisplay, True) + self.HideMenu = QtGui.QToolButton(self.Toolbar) + self.HideMenu.setText(translate('SlideController', 'Hide')) + self.HideMenu.setPopupMode(QtGui.QToolButton.MenuButtonPopup) + self.Toolbar.addToolbarWidget(u'Hide Menu', self.HideMenu) + self.HideMenu.setMenu(QtGui.QMenu( + translate('SlideController', 'Hide'), self.Toolbar)) + self.BlankScreen = QtGui.QAction(QtGui.QIcon( u':/slides/slide_blank.png'), u'Blank Screen', self.HideMenu) + self.BlankScreen.setCheckable(True) + QtCore.QObject.connect(self.BlankScreen, QtCore.SIGNAL("triggered(bool)"), self.onBlankDisplay) + self.ThemeScreen = QtGui.QAction(QtGui.QIcon(u':/slides/slide_theme.png'), u'Blank to Theme', self.HideMenu) + self.ThemeScreen.setCheckable(True) + QtCore.QObject.connect(self.BlankScreen, QtCore.SIGNAL("triggered(bool)"), self.onThemeDisplay) + self.DesktopScreen = QtGui.QAction(QtGui.QIcon(u':/slides/slide_desktop.png'), u'Show Desktop', self.HideMenu) + self.DesktopScreen.setCheckable(True) + QtCore.QObject.connect(self.BlankScreen, QtCore.SIGNAL("triggered(bool)"), self.onHideDisplay) + self.HideMenu.setDefaultAction(self.BlankScreen) + self.HideMenu.menu().addAction(self.BlankScreen) + self.HideMenu.menu().addAction(self.ThemeScreen) + self.HideMenu.menu().addAction(self.DesktopScreen) if not self.isLive: self.Toolbar.addToolbarSeparator(u'Close Separator') self.Toolbar.addToolbarButton( @@ -252,29 +259,6 @@ class SlideController(QtGui.QWidget): u'Media Stop', u':/slides/media_playback_stop.png', translate('SlideController', 'Start playing media'), self.onMediaStop) - if self.isLive: - self.button = QtGui.QToolButton(self.Toolbar) - self.Toolbar.addToolbarWidget(u'Hide Menu', self.button) - self.button.setText(translate('SlideController', 'Hide')) - self.menu = QtGui.QMenu(self.button) - blank_screen = QtGui.QAction(QtGui.QIcon( u':/slides/slide_blank.png'), u'Blank Screen', self.button) - theme_screen = QtGui.QAction(QtGui.QIcon(u':/slides/slide_theme.png'), u'Blank to Theme', self.button) - desktop_screen = QtGui.QAction(QtGui.QIcon(u':/slides/slide_desktop.png'), u'Show Desktop', self.button) - self.menu.addAction(blank_screen) - self.menu.addAction(theme_screen) - self.menu.addAction(desktop_screen) - self.blankButton = self.Mediabar.addToolbarButton( - u'Blank Screen', u':/slides/slide_blank.png', - translate('SlideController', 'Blank Screen'), - self.onBlankDisplay, True) - self.themeButton = self.Mediabar.addToolbarButton( - u'Display Theme', u':/slides/slide_theme.png', - translate('SlideController', 'Theme Screen'), - self.onThemeDisplay, True) - self.hideButton = self.Mediabar.addToolbarButton( - u'Hide screen', u':/slides/slide_desktop.png', - translate('SlideController', 'Hide Screen'), - self.onHideDisplay, True) if not self.isLive: self.seekSlider = Phonon.SeekSlider() self.seekSlider.setGeometry(QtCore.QRect(90, 260, 221, 24)) @@ -686,8 +670,11 @@ class SlideController(QtGui.QWidget): Handle the blank screen button actions """ log.debug(u'onBlankDisplay %d' % checked) - self.hideButton.setChecked(False) - self.themeButton.setChecked(False) + self.HideMenu.setDefaultAction(self.BlankScreen) + self.BlankScreen.setCheckable(True) + self.BlankScreen.setChecked(True) + self.ThemeScreen.setChecked(False) + self.DesktopScreen.setChecked(False) self.canDisplay = not checked QtCore.QSettings().setValue( self.parent.generalSettingsSection + u'/screen blank', @@ -704,8 +691,11 @@ class SlideController(QtGui.QWidget): Handle the Theme screen button """ log.debug(u'onThemeDisplay %d' % checked) - self.blankButton.setChecked(False) - self.hideButton.setChecked(False) + self.HideMenu.setDefaultAction(self.ThemeScreen) + self.ThemeScreen.setCheckable(True) + self.BlankScreen.setChecked(False) + self.ThemeScreen.setChecked(True) + self.DesktopScreen.setChecked(False) self.canDisplay = False if checked: Receiver.send_message(u'maindisplay_hide', HideMode.Theme) @@ -719,8 +709,11 @@ class SlideController(QtGui.QWidget): Handle the Hide screen button """ log.debug(u'onHideDisplay %d' % checked) - self.blankButton.setChecked(False) - self.themeButton.setChecked(False) + self.HideMenu.setDefaultAction(self.DesktopScreen) + self.DesktopScreen.setCheckable(True) + self.BlankScreen.setChecked(False) + self.ThemeScreen.setChecked(False) + self.DesktopScreen.setChecked(True) self.canDisplay = False if checked: Receiver.send_message(u'maindisplay_hide', HideMode.Screen) From b59b2bdafaa216af50db61cb218135b2c9ebd883 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sat, 26 Jun 2010 08:19:30 +0100 Subject: [PATCH 14/49] Fix bug #596541 hide theme combo for global themes --- openlp/core/ui/servicemanager.py | 22 +++++++++++++++++----- openlp/core/ui/slidecontroller.py | 16 ++++++++-------- openlp/core/ui/themestab.py | 2 +- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index 540be0ff4..284d9c7e4 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -33,7 +33,7 @@ log = logging.getLogger(__name__) from PyQt4 import QtCore, QtGui from openlp.core.lib import OpenLPToolbar, ServiceItem, context_menu_action, \ - Receiver, build_icon, ItemCapabilities, SettingsManager, translate + Receiver, build_icon, ItemCapabilities, SettingsManager, translate, ThemeLevel from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm from openlp.core.utils import AppLocation @@ -134,15 +134,13 @@ class ServiceManager(QtGui.QWidget): self.ThemeLabel = QtGui.QLabel(translate('ServiceManager', 'Theme:'), self) self.ThemeLabel.setMargin(3) - self.Toolbar.addWidget(self.ThemeLabel) + self.Toolbar.addToolbarWidget(u'ThemeLabel', self.ThemeLabel) self.ThemeComboBox = QtGui.QComboBox(self.Toolbar) self.ThemeComboBox.setToolTip(translate('ServiceManager', 'Select a theme for the service')) self.ThemeComboBox.setSizeAdjustPolicy( QtGui.QComboBox.AdjustToContents) - self.ThemeWidget = QtGui.QWidgetAction(self.Toolbar) - self.ThemeWidget.setDefaultWidget(self.ThemeComboBox) - self.Toolbar.addAction(self.ThemeWidget) + self.Toolbar.addToolbarWidget(u'ThemeWidget', self.ThemeComboBox) self.Layout.addWidget(self.Toolbar) # Create the service manager list self.ServiceManagerList = ServiceManagerList(self) @@ -214,6 +212,8 @@ class ServiceManager(QtGui.QWidget): QtCore.SIGNAL(u'servicemanager_list_request'), self.listRequest) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'config_updated'), self.regenerateServiceItems) + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'theme_update_global'), self.themeChange) # Last little bits of setting up self.service_theme = unicode(QtCore.QSettings().value( self.parent.serviceSettingsSection + u'/service theme', @@ -756,6 +756,18 @@ class ServiceManager(QtGui.QWidget): QtCore.QVariant(self.service_theme)) self.regenerateServiceItems() + def themeChange(self): + """ + The theme may have changed in the settings dialog so make + sure the theme combo box is in the correct state. + """ + if self.parent.RenderManager.theme_level == ThemeLevel.Global: + self.Toolbar.actions[u'ThemeLabel'].setVisible(False) + self.Toolbar.actions[u'ThemeWidget'].setVisible(False) + else: + self.Toolbar.actions[u'ThemeLabel'].setVisible(True) + self.Toolbar.actions[u'ThemeWidget'].setVisible(True) + def regenerateServiceItems(self): """ Rebuild the service list as things have changed and a diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 67c498f45..bfb5e291e 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -513,21 +513,21 @@ class SlideController(QtGui.QWidget): """ log.debug(u'processManagerItem') self.onStopLoop() - #If old item was a command tell it to stop + #If old item was a command tell it to stop if self.serviceItem: if self.serviceItem.is_command(): - Receiver.send_message(u'%s_stop' % + Receiver.send_message(u'%s_stop' % self.serviceItem.name.lower(), [serviceItem, self.isLive]) if self.serviceItem.is_media(): self.onMediaStop() if serviceItem.is_media(): self.onMediaStart(serviceItem) - if self.isLive: - blanked = self.blankButton.isChecked() - else: - blanked = False - Receiver.send_message(u'%s_start' % serviceItem.name.lower(), - [serviceItem, self.isLive, blanked, slideno]) +# if self.isLive: +# blanked = self.blankButton.isChecked() +# else: +# blanked = False +# Receiver.send_message(u'%s_start' % serviceItem.name.lower(), +# [serviceItem, self.isLive, blanked, slideno]) self.slideList = {} width = self.parent.ControlSplitter.sizes()[self.split] #Set pointing cursor when we have somthing to point at diff --git a/openlp/core/ui/themestab.py b/openlp/core/ui/themestab.py index 73fbfeb88..007a51fd6 100644 --- a/openlp/core/ui/themestab.py +++ b/openlp/core/ui/themestab.py @@ -150,9 +150,9 @@ class ThemesTab(SettingsTab): settings.setValue(u'global theme', QtCore.QVariant(self.global_theme)) settings.endGroup() - Receiver.send_message(u'theme_update_global', self.global_theme) self.parent.RenderManager.set_global_theme( self.global_theme, self.theme_level) + Receiver.send_message(u'theme_update_global', self.global_theme) def postSetUp(self): Receiver.send_message(u'theme_update_global', self.global_theme) From d82f94e3267166eaa9c60231128ea7caca9a6b77 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sat, 26 Jun 2010 09:09:09 +0100 Subject: [PATCH 15/49] Refactor Alert code for Html --- openlp/core/ui/maindisplay.py | 39 +++++++-------- openlp/plugins/alerts/lib/alertsmanager.py | 56 +++++----------------- openlp/plugins/alerts/lib/alertstab.py | 9 ++-- 3 files changed, 39 insertions(+), 65 deletions(-) diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 0196732fe..981647846 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -52,7 +52,16 @@ class DisplayManager(QtGui.QWidget): self.videoDisplay.setup() self.mainDisplay.setup() + def addAlert(self, alertMessage, location): + """ + Handles the add Alert Message to the Displays + """ + self.mainDisplay.addAlert(alertMessage, location) + def close(self): + """ + Handles the closure of the displays + """ self.videoDisplay.close() self.audioPlayer.close() self.mainDisplay.close() @@ -184,7 +193,6 @@ class MainDisplay(DisplayWidget): self.transparent = QtGui.QPixmap( self.screen[u'size'].width(), self.screen[u'size'].height()) self.transparent.fill(QtCore.Qt.transparent) -# self.display_alert.setPixmap(self.transparent) # self.display_text.setPixmap(self.transparent) #self.frameView(self.transparent) # To display or not to display? @@ -195,7 +203,6 @@ class MainDisplay(DisplayWidget): self.setVisible(False) self.primary = True - def setupScene(self): self.scene = QtGui.QGraphicsScene(self) self.scene.setSceneRect(0,0,self.size().width(), self.size().height()) @@ -209,15 +216,13 @@ class MainDisplay(DisplayWidget): def setupText(self): #self.display_text = QtGui.QGraphicsTextItem() self.display_text = QtGui.QGraphicsPixmapItem() - #self.display_text.setPos(0,self.size().height()/2) + #self.display_text.setPos(0,0) #self.display_text.setTextWidth(self.size().width()) self.display_text.setZValue(4) self.scene.addItem(self.display_text) def setupAlert(self): self.alertText = QtGui.QGraphicsTextItem() - self.alertText.setPos(0,self.size().height()/2) - self.alertText.setPos(0,self.size().height() - 76) self.alertText.setTextWidth(self.size().width()) self.alertText.setZValue(8) self.scene.addItem(self.alertText) @@ -234,7 +239,6 @@ class MainDisplay(DisplayWidget): self.setVisible(False) else: self.setVisible(True) - #self.showFullScreen() def hideDisplayForVideo(self): """ @@ -250,7 +254,6 @@ class MainDisplay(DisplayWidget): log.debug(u'hideDisplay mode = %d', mode) self.storeImage = QtGui.QPixmap(self.display_image.pixmap()) self.storeText = QtGui.QPixmap(self.display_text.pixmap()) - #self.display_alert.setPixmap(self.transparent) #self.display_text.setPixmap(self.transparent) if mode == HideMode.Screen: #self.display_image.setPixmap(self.transparent) @@ -277,7 +280,6 @@ class MainDisplay(DisplayWidget): self.display_image.setPixmap(self.storeImage) if self.storeText: self.display_text.setPixmap(self.storeText) - #self.display_alert.setPixmap(self.transparent) self.storeImage = None self.store = None Receiver.send_message(u'maindisplay_active') @@ -288,18 +290,18 @@ class MainDisplay(DisplayWidget): frame, self.screen[u'size'].width(), self.screen[u'size'].height()) self.display_image.setPixmap(QtGui.QPixmap.fromImage(frame)) - def setAlertSize(self, top, height): - log.debug(u'setAlertSize') -# self.display_alert.setGeometry( -# QtCore.QRect(0, top, -# self.screen[u'size'].width(), height)) - - def addAlertImage(self, frame, blank=False): + def addAlert(self, message, location): + """ + Places the Alert text on the display at the correct location + """ log.debug(u'addAlertImage') - if blank: - self.display_alert.setPixmap(self.transparent) + if location == 0: + self.alertText.setPos(0, 0) + elif location == 1: + self.alertText.setPos(0,self.size().height()/2) else: - self.display_alert.setPixmap(frame) + self.alertText.setPos(0,self.size().height() - 76) + self.alertText.setHtml(message) def frameView(self, frame, transition=False, display=True): """ @@ -333,7 +335,6 @@ class MainDisplay(DisplayWidget): self.display_frame = frame if not self.isVisible() and self.screens.display: self.setVisible(True) - #self.showFullScreen() else: self.storeText = QtGui.QPixmap.fromImage(frame[u'main']) diff --git a/openlp/plugins/alerts/lib/alertsmanager.py b/openlp/plugins/alerts/lib/alertsmanager.py index ecd41bbd1..2b1d7c265 100644 --- a/openlp/plugins/alerts/lib/alertsmanager.py +++ b/openlp/plugins/alerts/lib/alertsmanager.py @@ -31,6 +31,15 @@ from openlp.core.lib import Receiver, translate log = logging.getLogger(__name__) +HTMLCODE = u""" +

+ %s +

+""" + class AlertsManager(QtCore.QObject): """ AlertsTab is the Alerts settings tab in the settings dialog. @@ -47,28 +56,6 @@ class AlertsManager(QtCore.QObject): QtCore.SIGNAL(u'maindisplay_active'), self.generateAlert) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'alerts_text'), self.onAlertText) - QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'config_screen_changed'), self.screenChanged) - - def screenChanged(self): - log.debug(u'screen changed') - self.alertTab = self.parent.alertsTab - self.screen = self.parent.maindisplay.screens.current - self.font = QtGui.QFont() - self.font.setFamily(self.alertTab.font_face) - self.font.setBold(True) - self.font.setPointSize(self.alertTab.font_size) - self.metrics = QtGui.QFontMetrics(self.font) - self.alertHeight = self.metrics.height() + 4 - if self.alertTab.location == 0: - self.alertScreenPosition = 0 - else: - self.alertScreenPosition = self.screen[u'size'].height() \ - - self.alertHeight - self.alertHeight = self.screen[u'size'].height() \ - - self.alertScreenPosition - self.parent.maindisplay.setAlertSize(self.alertScreenPosition, - self.alertHeight) def onAlertText(self, message): """ @@ -88,8 +75,6 @@ class AlertsManager(QtCore.QObject): display text """ log.debug(u'display alert called %s' % text) - if not self.screen: - self.screenChanged() self.alertList.append(text) if self.timer_id != 0: Receiver.send_message(u'maindisplay_status_text', @@ -105,24 +90,9 @@ class AlertsManager(QtCore.QObject): return text = self.alertList.pop(0) alertTab = self.parent.alertsTab - alertframe = \ - QtGui.QPixmap(self.screen[u'size'].width(), self.alertHeight) - alertframe.fill(QtCore.Qt.transparent) - painter = QtGui.QPainter(alertframe) - painter.fillRect(alertframe.rect(), QtCore.Qt.transparent) - painter.setRenderHint(QtGui.QPainter.Antialiasing) - painter.fillRect( - QtCore.QRect( - 0, 0, alertframe.rect().width(), - alertframe.rect().height()), - QtGui.QColor(self.alertTab.bg_color)) - painter.setFont(self.font) - painter.setPen(QtGui.QColor(self.alertTab.font_color)) - x, y = (0, 2) - painter.drawText( - x, y + self.metrics.height() - self.metrics.descent() - 1, text) - painter.end() - self.parent.maindisplay.addAlertImage(alertframe) + text = HTMLCODE % (alertTab.font_color, alertTab.bg_color, + alertTab.font_face, alertTab.font_size, text) + self.parent.preview_controller.parent.displayManager.addAlert(text, alertTab.location) # check to see if we have a timer running if self.timer_id == 0: self.timer_id = self.startTimer(int(alertTab.timeout) * 1000) @@ -130,7 +100,7 @@ class AlertsManager(QtCore.QObject): def timerEvent(self, event): log.debug(u'timer event') if event.timerId() == self.timer_id: - self.parent.maindisplay.addAlertImage(None, True) + self.parent.preview_controller.parent.displayManager.addAlert(u'', self.alertTab.location) self.killTimer(self.timer_id) self.timer_id = 0 self.generateAlert() diff --git a/openlp/plugins/alerts/lib/alertstab.py b/openlp/plugins/alerts/lib/alertstab.py index 31a9f7a3e..e03bbfabe 100644 --- a/openlp/plugins/alerts/lib/alertstab.py +++ b/openlp/plugins/alerts/lib/alertstab.py @@ -128,6 +128,7 @@ class AlertsTab(SettingsTab): self.LocationComboBox = QtGui.QComboBox(self.LocationWidget) self.LocationComboBox.addItem(QtCore.QString()) self.LocationComboBox.addItem(QtCore.QString()) + self.LocationComboBox.addItem(QtCore.QString()) self.LocationComboBox.setObjectName(u'LocationComboBox') self.LocationLayout.addWidget(self.LocationComboBox) self.LocationSpacer = QtGui.QSpacerItem(147, 20, @@ -208,9 +209,11 @@ class AlertsTab(SettingsTab): translate('AlertsPlugin.AlertsTab', 'Preview')) self.FontPreview.setText( translate('AlertsPlugin.AlertsTab', 'openlp.org')) - self.LocationComboBox.setItemText(0, + self.LocationComboBox.setItemText(0, translate('AlertsPlugin.AlertsTab', 'Top')) - self.LocationComboBox.setItemText(1, + self.LocationComboBox.setItemText(1, + translate('AlertsPlugin.AlertsTab', 'Middle')) + self.LocationComboBox.setItemText(2, translate('AlertsPlugin.AlertsTab', 'Bottom')) def onBackgroundColorButtonClicked(self): @@ -295,4 +298,4 @@ class AlertsTab(SettingsTab): font.setPointSize(self.font_size) self.FontPreview.setFont(font) self.FontPreview.setStyleSheet(u'background-color: %s; color: %s' % - (self.bg_color, self.font_color)) \ No newline at end of file + (self.bg_color, self.font_color)) From 4b38c22d304f04683798936c2d48c39529cd3987 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sat, 26 Jun 2010 15:13:10 +0100 Subject: [PATCH 16/49] Alerts now work and more hiding cleanups --- openlp/core/ui/maindisplay.py | 67 ++++++++++++---------- openlp/core/ui/slidecontroller.py | 38 +++++------- openlp/plugins/alerts/lib/alertsmanager.py | 13 ++++- 3 files changed, 65 insertions(+), 53 deletions(-) diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 981647846..65b850eae 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -47,11 +47,31 @@ class DisplayManager(QtGui.QWidget): self.videoDisplay = VideoDisplay(self, screens) self.audioPlayer = AudioPlayer(self) self.mainDisplay = MainDisplay(self, screens) + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'maindisplay_hide'), self.hideDisplay) + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'maindisplay_show'), self.showDisplay) +# QtCore.QObject.connect(Receiver.get_receiver(), +# QtCore.SIGNAL(u'videodisplay_start'), self.hideDisplayForVideo) def setup(self): self.videoDisplay.setup() self.mainDisplay.setup() + def hideDisplay(self, message): + """ + Hide the output displays + """ + self.videoDisplay.mediaHide(message) + self.mainDisplay.hideDisplay(message) + + def showDisplay(self, message): + """ + Hide the output displays + """ + self.videoDisplay.mediaShow(message) + self.mainDisplay.showDisplay(message) + def addAlert(self, alertMessage, location): """ Handles the add Alert Message to the Displays @@ -145,14 +165,8 @@ class MainDisplay(DisplayWidget): self.primary = True self.blankFrame = None self.frame = None - QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'videodisplay_start'), self.hideDisplayForVideo) - QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'maindisplay_hide'), self.hideDisplay) - QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'maindisplay_show'), self.showDisplay) - QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'videodisplay_background'), self.hideDisplayForVideo) + #Hide desktop for now untill we know where to put it + #and what size it should be. self.setVisible(False) def setup(self): @@ -240,11 +254,11 @@ class MainDisplay(DisplayWidget): else: self.setVisible(True) - def hideDisplayForVideo(self): - """ - Hides the main display if for the video to be played - """ - self.hideDisplay(HideMode.Screen) +# def hideDisplayForVideo(self): +# """ +# Hides the main display if for the video to be played +# """ +# self.hideDisplay(HideMode.Screen) def hideDisplay(self, mode=HideMode.Screen): """ @@ -252,8 +266,6 @@ class MainDisplay(DisplayWidget): Store the images so they can be replaced when required """ log.debug(u'hideDisplay mode = %d', mode) - self.storeImage = QtGui.QPixmap(self.display_image.pixmap()) - self.storeText = QtGui.QPixmap(self.display_text.pixmap()) #self.display_text.setPixmap(self.transparent) if mode == HideMode.Screen: #self.display_image.setPixmap(self.transparent) @@ -269,19 +281,14 @@ class MainDisplay(DisplayWidget): self.display_blank.setPixmap( QtGui.QPixmap.fromImage(self.blankFrame)) - def showDisplay(self): + def showDisplay(self, message=u''): """ Show the stored layers so the screen reappears as it was originally. Make the stored images None to release memory. """ log.debug(u'showDisplay') - if self.storeImage: - self.display_image.setPixmap(self.storeImage) - if self.storeText: - self.display_text.setPixmap(self.storeText) - self.storeImage = None - self.store = None + self.display_blank.setPixmap(self.transparent) Receiver.send_message(u'maindisplay_active') def addImageWithText(self, frame): @@ -293,6 +300,11 @@ class MainDisplay(DisplayWidget): def addAlert(self, message, location): """ Places the Alert text on the display at the correct location + ``messgae`` + Text to be displayed + ``location`` + Where on the screen the text should be. From the AlertTab + Combo box. """ log.debug(u'addAlertImage') if location == 0: @@ -309,6 +321,8 @@ class MainDisplay(DisplayWidget): if the alert is in progress the alert is added on top ``frame`` Image frame to be rendered + ``transition`` + Are transitions required. """ log.debug(u'frameView %d' % display) if display: @@ -374,11 +388,6 @@ class VideoDisplay(Phonon.VideoWidget): except AttributeError: pass self.setWindowFlags(flags) - - QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'maindisplay_hide'), self.mediaHide) - QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'maindisplay_show'), self.mediaShow) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'videodisplay_start'), self.onMediaQueue) QtCore.QObject.connect(Receiver.get_receiver(), @@ -501,7 +510,7 @@ class VideoDisplay(Phonon.VideoWidget): self.mediaObject.clearQueue() self.setVisible(False) - def mediaHide(self): + def mediaHide(self, message=u''): """ Hide the video display """ @@ -509,7 +518,7 @@ class VideoDisplay(Phonon.VideoWidget): self.hidden = True self.setVisible(False) - def mediaShow(self): + def mediaShow(self, message=''): """ Show the video disaply if it was already hidden """ diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index bfb5e291e..72a12aced 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -207,10 +207,10 @@ class SlideController(QtGui.QWidget): QtCore.QObject.connect(self.BlankScreen, QtCore.SIGNAL("triggered(bool)"), self.onBlankDisplay) self.ThemeScreen = QtGui.QAction(QtGui.QIcon(u':/slides/slide_theme.png'), u'Blank to Theme', self.HideMenu) self.ThemeScreen.setCheckable(True) - QtCore.QObject.connect(self.BlankScreen, QtCore.SIGNAL("triggered(bool)"), self.onThemeDisplay) + QtCore.QObject.connect(self.ThemeScreen, QtCore.SIGNAL("triggered(bool)"), self.onThemeDisplay) self.DesktopScreen = QtGui.QAction(QtGui.QIcon(u':/slides/slide_desktop.png'), u'Show Desktop', self.HideMenu) self.DesktopScreen.setCheckable(True) - QtCore.QObject.connect(self.BlankScreen, QtCore.SIGNAL("triggered(bool)"), self.onHideDisplay) + QtCore.QObject.connect(self.DesktopScreen, QtCore.SIGNAL("triggered(bool)"), self.onHideDisplay) self.HideMenu.setDefaultAction(self.BlankScreen) self.HideMenu.menu().addAction(self.BlankScreen) self.HideMenu.menu().addAction(self.ThemeScreen) @@ -655,7 +655,7 @@ class SlideController(QtGui.QWidget): """ log.debug(u'mainDisplaySetBackground') if not self.mainDisplay.primary: - self.blankButton.setChecked(True) + self.onBlankDisplay(True) def onSlideBlank(self): """ @@ -673,64 +673,55 @@ class SlideController(QtGui.QWidget): """ Handle the blank screen button actions """ - log.debug(u'onBlankDisplay %d' % checked) + log.debug(u'onBlankDisplay %s' % checked) self.HideMenu.setDefaultAction(self.BlankScreen) - self.BlankScreen.setCheckable(True) - self.BlankScreen.setChecked(True) + self.BlankScreen.setChecked(checked) self.ThemeScreen.setChecked(False) self.DesktopScreen.setChecked(False) - self.canDisplay = not checked QtCore.QSettings().setValue( self.parent.generalSettingsSection + u'/screen blank', QtCore.QVariant(checked)) if checked: Receiver.send_message(u'maindisplay_hide', HideMode.Blank) - self.blankPlugin(True) else: Receiver.send_message(u'maindisplay_show') - self.blankPlugin(False) + self.blankPlugin(checked) def onThemeDisplay(self, checked): """ Handle the Theme screen button """ - log.debug(u'onThemeDisplay %d' % checked) + log.debug(u'onThemeDisplay %s' % checked) self.HideMenu.setDefaultAction(self.ThemeScreen) - self.ThemeScreen.setCheckable(True) self.BlankScreen.setChecked(False) - self.ThemeScreen.setChecked(True) + self.ThemeScreen.setChecked(checked) self.DesktopScreen.setChecked(False) - self.canDisplay = False if checked: Receiver.send_message(u'maindisplay_hide', HideMode.Theme) - self.blankPlugin(True) else: Receiver.send_message(u'maindisplay_show') - self.blankPlugin(False) + self.blankPlugin(checked) def onHideDisplay(self, checked): """ Handle the Hide screen button """ - log.debug(u'onHideDisplay %d' % checked) + log.debug(u'onHideDisplay %s' % checked) self.HideMenu.setDefaultAction(self.DesktopScreen) - self.DesktopScreen.setCheckable(True) self.BlankScreen.setChecked(False) self.ThemeScreen.setChecked(False) - self.DesktopScreen.setChecked(True) - self.canDisplay = False + self.DesktopScreen.setChecked(checked) if checked: Receiver.send_message(u'maindisplay_hide', HideMode.Screen) - self.hidePlugin(True) else: Receiver.send_message(u'maindisplay_show') - self.hidePlugin(False) + self.hidePlugin(checked) def blankPlugin(self, blank): """ Blank the display screen within a plugin if required. """ - log.debug(u'blankPlugin %d ', blank) + log.debug(u'blankPlugin %s ', blank) if self.serviceItem is not None: if blank: Receiver.send_message(u'%s_blank' @@ -743,8 +734,9 @@ class SlideController(QtGui.QWidget): def hidePlugin(self, hide): """ - Blank the display screen. + Tell the plugin to hide the display screen. """ + log.debug(u'hidePlugin %s ', hide) if self.serviceItem is not None: if hide: Receiver.send_message(u'%s_hide' diff --git a/openlp/plugins/alerts/lib/alertsmanager.py b/openlp/plugins/alerts/lib/alertsmanager.py index 2b1d7c265..10565a3d1 100644 --- a/openlp/plugins/alerts/lib/alertsmanager.py +++ b/openlp/plugins/alerts/lib/alertsmanager.py @@ -85,6 +85,9 @@ class AlertsManager(QtCore.QObject): self.generateAlert() def generateAlert(self): + """ + Format and request the Alert and start the timer + """ log.debug(u'Generate Alert called') if len(self.alertList) == 0: return @@ -98,9 +101,17 @@ class AlertsManager(QtCore.QObject): self.timer_id = self.startTimer(int(alertTab.timeout) * 1000) def timerEvent(self, event): + """ + Time has finished so if our time then request the next Alert + if there is one and reset the timer. + ``event`` + the QT event that has been triggered. + + """ log.debug(u'timer event') + alertTab = self.parent.alertsTab if event.timerId() == self.timer_id: - self.parent.preview_controller.parent.displayManager.addAlert(u'', self.alertTab.location) + self.parent.preview_controller.parent.displayManager.addAlert(u'', alertTab.location) self.killTimer(self.timer_id) self.timer_id = 0 self.generateAlert() From 7cf31532b84feb51a15c3d88c57342f1d54cf8c5 Mon Sep 17 00:00:00 2001 From: Jonathan Corwin Date: Sat, 26 Jun 2010 21:34:26 +0100 Subject: [PATCH 17/49] Remove error trace if no impress --- .../presentations/lib/impresscontroller.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/openlp/plugins/presentations/lib/impresscontroller.py b/openlp/plugins/presentations/lib/impresscontroller.py index 52de42ca7..4cbadc9dd 100644 --- a/openlp/plugins/presentations/lib/impresscontroller.py +++ b/openlp/plugins/presentations/lib/impresscontroller.py @@ -42,9 +42,13 @@ from openlp.core.lib import resize_image if os.name == u'nt': from win32com.client import Dispatch else: - import uno - from com.sun.star.beans import PropertyValue - + try: + import uno + from com.sun.star.beans import PropertyValue + uno_available = True + except ImportError: + uno_available = False + from PyQt4 import QtCore from presentationcontroller import PresentationController, PresentationDocument @@ -78,9 +82,7 @@ class ImpressController(PresentationController): if os.name == u'nt': return self.get_com_servicemanager() is not None else: - # If not windows, and we've got this far then probably - # installed else the import uno would likely have failed - return True + return uno_available def start_process(self): """ @@ -322,7 +324,10 @@ class ImpressDocument(PresentationDocument): Returns true if screen is blank """ log.debug(u'is blank OpenOffice') - return self.control.isPaused() + if self.control: + return self.control.isPaused() + else: + return False def stop_presentation(self): log.debug(u'stop presentation OpenOffice') From 5ba7febc3b90358d89c338331e285b5ed382a161 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Sun, 27 Jun 2010 08:19:34 +0100 Subject: [PATCH 18/49] Video cleanups for display --- openlp/core/ui/maindisplay.py | 45 +++++++++++++++---------------- openlp/core/ui/slidecontroller.py | 3 +-- 2 files changed, 23 insertions(+), 25 deletions(-) diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 65b850eae..21cec593a 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -51,8 +51,10 @@ class DisplayManager(QtGui.QWidget): QtCore.SIGNAL(u'maindisplay_hide'), self.hideDisplay) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'maindisplay_show'), self.showDisplay) -# QtCore.QObject.connect(Receiver.get_receiver(), -# QtCore.SIGNAL(u'videodisplay_start'), self.hideDisplayForVideo) + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'videodisplay_start'), self.onStartVideo) + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'videodisplay_stop'), self.onStopVideo) def setup(self): self.videoDisplay.setup() @@ -78,6 +80,22 @@ class DisplayManager(QtGui.QWidget): """ self.mainDisplay.addAlert(alertMessage, location) + def onStartVideo(self, item): + """ + Handles the Starting of a Video and Display Management + """ + self.videoDisplay.setVisible(True) + self.mainDisplay.setVisible(False) + self.videoDisplay.onMediaQueue(item) + + def onStopVideo(self): + """ + Handles the Stopping of a Video and Display Management + """ + self.mainDisplay.setVisible(True) + self.videoDisplay.setVisible(False) + self.videoDisplay.onMediaStop() + def close(self): """ Handles the closure of the displays @@ -388,14 +406,10 @@ class VideoDisplay(Phonon.VideoWidget): except AttributeError: pass self.setWindowFlags(flags) - QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'videodisplay_start'), self.onMediaQueue) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'videodisplay_play'), self.onMediaPlay) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'videodisplay_pause'), self.onMediaPause) - QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'videodisplay_stop'), self.onMediaStop) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'videodisplay_background'), self.onMediaBackground) QtCore.QObject.connect(Receiver.get_receiver(), @@ -462,8 +476,8 @@ class VideoDisplay(Phonon.VideoWidget): Set up a video to play from the serviceitem. """ log.debug(u'VideoDisplay Queue new media message %s' % message) - file = os.path.join(message[0].get_frame_path(), - message[0].get_frame_title()) + file = os.path.join(message.get_frame_path(), + message.get_frame_title()) self.mediaObject.setCurrentSource(Phonon.MediaSource(file)) self._play() @@ -551,21 +565,6 @@ class AudioPlayer(QtCore.QObject): self.audioObject = Phonon.AudioOutput(Phonon.VideoCategory) Phonon.createPath(self.mediaObject, self.audioObject) -# QtCore.QObject.connect(Receiver.get_receiver(), -# QtCore.SIGNAL(u'videodisplay_start'), self.onMediaQueue) -# QtCore.QObject.connect(Receiver.get_receiver(), -# QtCore.SIGNAL(u'videodisplay_play'), self.onMediaPlay) -# QtCore.QObject.connect(Receiver.get_receiver(), -# QtCore.SIGNAL(u'videodisplay_pause'), self.onMediaPause) -# QtCore.QObject.connect(Receiver.get_receiver(), -# QtCore.SIGNAL(u'videodisplay_stop'), self.onMediaStop) -# QtCore.QObject.connect(Receiver.get_receiver(), -# QtCore.SIGNAL(u'videodisplay_background'), self.onMediaBackground) -# QtCore.QObject.connect(Receiver.get_receiver(), -# QtCore.SIGNAL(u'config_updated'), self.setup) -# QtCore.QObject.connect(self.mediaObject, -# QtCore.SIGNAL(u'finished()'), self.onMediaBackground) - def setup(self): """ Sets up the Audio Player for use diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 72a12aced..2a92cd20d 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -923,8 +923,7 @@ class SlideController(QtGui.QWidget): """ log.debug(u'SlideController onMediaStart') if self.isLive: - Receiver.send_message(u'videodisplay_start', - [item, self.blankButton.isChecked()]) + Receiver.send_message(u'videodisplay_start', item) else: self.mediaObject.stop() self.mediaObject.clearQueue() From b188592c327dee9c9f22c9785682fbabec7e3f32 Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Sun, 27 Jun 2010 14:49:01 +0200 Subject: [PATCH 19/49] Fixed up problems with version checking. --- openlp/.version | 2 +- openlp/core/ui/mainwindow.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openlp/.version b/openlp/.version index 2007f03af..8fdcf3869 100644 --- a/openlp/.version +++ b/openlp/.version @@ -1 +1 @@ -1.9.1-bzr821 +1.9.2 diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 0f21b7307..7f1c0408b 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -63,7 +63,7 @@ class VersionThread(QtCore.QThread): self.parent = parent self.app_version = app_version self.version_splitter = re.compile( - r'([0-9]+).([0-9]+).([0-9]+)(?:-bzr([0-9]+))') + r'([0-9]+).([0-9]+).([0-9]+)(?:-bzr([0-9]+))?') def run(self): """ @@ -79,14 +79,14 @@ class VersionThread(QtCore.QThread): remote_version[u'major'] = int(match.group(1)) remote_version[u'minor'] = int(match.group(2)) remote_version[u'release'] = int(match.group(3)) - if len(match.groups()) > 3: + if len(match.groups()) > 3 and match.group(4): remote_version[u'revision'] = int(match.group(4)) match = self.version_splitter.match(self.app_version[u'full']) if match: local_version[u'major'] = int(match.group(1)) local_version[u'minor'] = int(match.group(2)) local_version[u'release'] = int(match.group(3)) - if len(match.groups()) > 3: + if len(match.groups()) > 3 and match.group(4): local_version[u'revision'] = int(match.group(4)) if remote_version[u'major'] > local_version[u'major'] or \ remote_version[u'minor'] > local_version[u'minor'] or \ From 9a2b05f830fcad1135c298288466c7b065166223 Mon Sep 17 00:00:00 2001 From: Jonathan Corwin Date: Sun, 27 Jun 2010 23:34:33 +0100 Subject: [PATCH 20/49] Prevent crash if OpenOffice not installed on Windows --- openlp/plugins/presentations/lib/impresscontroller.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openlp/plugins/presentations/lib/impresscontroller.py b/openlp/plugins/presentations/lib/impresscontroller.py index 4cbadc9dd..c4250f27a 100644 --- a/openlp/plugins/presentations/lib/impresscontroller.py +++ b/openlp/plugins/presentations/lib/impresscontroller.py @@ -41,6 +41,7 @@ from openlp.core.lib import resize_image if os.name == u'nt': from win32com.client import Dispatch + import pywintypes else: try: import uno From ad9328a30f84c79e89946b2352a35d5aec89ae87 Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Mon, 28 Jun 2010 12:24:18 +0100 Subject: [PATCH 21/49] RFC: Fix couple of leftovers --- openlp/plugins/songs/forms/editsongform.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py index ace2d4f24..7a103931a 100644 --- a/openlp/plugins/songs/forms/editsongform.py +++ b/openlp/plugins/songs/forms/editsongform.py @@ -290,7 +290,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): QtGui.QMessageBox.Yes) == QtGui.QMessageBox.Yes: author = Author.populate(first_name=text.rsplit(u' ', 1)[0], last_name=text.rsplit(u' ', 1)[1], display_name=text) - self.songmanager.save_author(author) + self.songmanager.insert_object(author) self.song.authors.append(author) author_item = QtGui.QListWidgetItem( unicode(author.display_name)) @@ -342,7 +342,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, QtGui.QMessageBox.Yes) == QtGui.QMessageBox.Yes: topic = Topic.populate(name=text) - self.songmanager.save_topic(topic) + self.songmanager.insert_object(topic) self.song.topics.append(topic) topic_item = QtGui.QListWidgetItem(unicode(topic.name)) topic_item.setData(QtCore.Qt.UserRole, @@ -392,7 +392,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, QtGui.QMessageBox.Yes) == QtGui.QMessageBox.Yes: book = Book.populate(name=text) - self.songmanager.save_book(book) + self.songmanager.insert_object(book) self.song.book = book self.loadBooks() else: From f0896422d43455967e5a8598e59c6cf0322d0a5f Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Mon, 28 Jun 2010 13:43:14 +0100 Subject: [PATCH 22/49] Fix off-by-one in song saving --- openlp/plugins/songs/forms/editsongform.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py index cbb79bff4..8bd839e3f 100644 --- a/openlp/plugins/songs/forms/editsongform.py +++ b/openlp/plugins/songs/forms/editsongform.py @@ -396,7 +396,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.loadBooks() else: return - elif item > 1: + elif item >= 1: item = int(self.SongbookCombo.currentIndex()) self.song.song_book_id = \ (self.SongbookCombo.itemData(item)).toInt()[0] From 3be57e57e7b5e42f55cb46c587253e8354fa1265 Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Mon, 28 Jun 2010 14:38:29 +0100 Subject: [PATCH 23/49] Rename method to save_object() --- openlp/core/lib/db.py | 2 +- openlp/plugins/alerts/forms/alertform.py | 4 ++-- openlp/plugins/bibles/lib/db.py | 10 +++++----- openlp/plugins/custom/forms/editcustomform.py | 2 +- openlp/plugins/songs/forms/editsongform.py | 8 ++++---- openlp/plugins/songs/forms/songmaintenanceform.py | 12 ++++++------ openlp/plugins/songs/lib/songimport.py | 8 ++++---- openlp/plugins/songusage/songusageplugin.py | 4 ++-- 8 files changed, 25 insertions(+), 25 deletions(-) diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index 19cd3eadf..b000fe918 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -135,7 +135,7 @@ class Manager(object): settings.endGroup() self.session = init_schema(self.db_url) - def insert_object(self, object_instance): + def save_object(self, object_instance): """ Save an object to the database diff --git a/openlp/plugins/alerts/forms/alertform.py b/openlp/plugins/alerts/forms/alertform.py index 446f9698f..bf75f9ced 100644 --- a/openlp/plugins/alerts/forms/alertform.py +++ b/openlp/plugins/alerts/forms/alertform.py @@ -98,7 +98,7 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): else: alert = AlertItem() alert.text = unicode(self.AlertTextEdit.text()) - self.manager.insert_object(alert) + self.manager.save_object(alert) self.AlertTextEdit.setText(u'') self.loadList() @@ -109,7 +109,7 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): if self.item_id: alert = self.manager.get_object(AlertItem, self.item_id) alert.text = unicode(self.AlertTextEdit.text()) - self.manager.insert_object(alert) + self.manager.save_object(alert) self.item_id = None self.loadList() else: diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py index d2a62ec59..c799d71dd 100644 --- a/openlp/plugins/bibles/lib/db.py +++ b/openlp/plugins/bibles/lib/db.py @@ -200,9 +200,9 @@ class BibleDB(QtCore.QObject, Manager): """ self.wizard = wizard self.create_meta(u'dbversion', u'2') - self.insert_object(Testament.populate(name=u'Old Testament')) - self.insert_object(Testament.populate(name=u'New Testament')) - self.insert_object(Testament.populate(name=u'Apocrypha')) + self.save_object(Testament.populate(name=u'Old Testament')) + self.save_object(Testament.populate(name=u'New Testament')) + self.save_object(Testament.populate(name=u'Apocrypha')) return self.name def create_book(self, name, abbrev, testament=1): @@ -221,7 +221,7 @@ class BibleDB(QtCore.QObject, Manager): log.debug(u'create_book %s,%s', name, abbrev) book = Book.populate(name=name, abbreviation=abbrev, testament_id=testament) - self.insert_object(book) + self.save_object(book) return book def create_chapter(self, book_id, chapter, textlist): @@ -289,7 +289,7 @@ class BibleDB(QtCore.QObject, Manager): The value for this instance """ log.debug(u'save_meta %s/%s', key, value) - self.insert_object(BibleMeta.populate(key=key, value=value)) + self.save_object(BibleMeta.populate(key=key, value=value)) def get_book(self, book): """ diff --git a/openlp/plugins/custom/forms/editcustomform.py b/openlp/plugins/custom/forms/editcustomform.py index c3d25eabb..a266c44c5 100644 --- a/openlp/plugins/custom/forms/editcustomform.py +++ b/openlp/plugins/custom/forms/editcustomform.py @@ -166,7 +166,7 @@ class EditCustomForm(QtGui.QDialog, Ui_customEditDialog): u'utf-8') self.customSlide.theme_name = unicode(self.ThemeComboBox.currentText(), u'utf-8') - return self.custommanager.insert_object(self.customSlide) + return self.custommanager.save_object(self.customSlide) def onUpButtonPressed(self): selectedRow = self.VerseListView.currentRow() diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py index 7a103931a..c122c622c 100644 --- a/openlp/plugins/songs/forms/editsongform.py +++ b/openlp/plugins/songs/forms/editsongform.py @@ -290,7 +290,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): QtGui.QMessageBox.Yes) == QtGui.QMessageBox.Yes: author = Author.populate(first_name=text.rsplit(u' ', 1)[0], last_name=text.rsplit(u' ', 1)[1], display_name=text) - self.songmanager.insert_object(author) + self.songmanager.save_object(author) self.song.authors.append(author) author_item = QtGui.QListWidgetItem( unicode(author.display_name)) @@ -342,7 +342,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, QtGui.QMessageBox.Yes) == QtGui.QMessageBox.Yes: topic = Topic.populate(name=text) - self.songmanager.insert_object(topic) + self.songmanager.save_object(topic) self.song.topics.append(topic) topic_item = QtGui.QListWidgetItem(unicode(topic.name)) topic_item.setData(QtCore.Qt.UserRole, @@ -392,7 +392,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, QtGui.QMessageBox.Yes) == QtGui.QMessageBox.Yes: book = Book.populate(name=text) - self.songmanager.insert_object(book) + self.songmanager.save_object(book) self.song.book = book self.loadBooks() else: @@ -631,7 +631,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): if self._validate_song(): self.processLyrics() self.processTitle() - self.songmanager.insert_object(self.song) + self.songmanager.save_object(self.song) return True return False diff --git a/openlp/plugins/songs/forms/songmaintenanceform.py b/openlp/plugins/songs/forms/songmaintenanceform.py index ca56a5492..54a8d539f 100644 --- a/openlp/plugins/songs/forms/songmaintenanceform.py +++ b/openlp/plugins/songs/forms/songmaintenanceform.py @@ -131,7 +131,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): first_name=unicode(self.authorform.FirstNameEdit.text()), last_name=unicode(self.authorform.LastNameEdit.text()), display_name=unicode(self.authorform.DisplayEdit.text())) - if self.songmanager.insert_object(author): + if self.songmanager.save_object(author): self.resetAuthors() else: QtGui.QMessageBox.critical( @@ -143,7 +143,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): def onTopicAddButtonClick(self): if self.topicform.exec_(): topic = Topic.populate(name=unicode(self.topicform.NameEdit.text())) - if self.songmanager.insert_object(topic): + if self.songmanager.save_object(topic): self.resetTopics() else: QtGui.QMessageBox.critical( @@ -157,7 +157,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): book = Book.populate( name=unicode(self.bookform.NameEdit.text()), publisher=unicode(self.bookform.PublisherEdit.text())) - if self.songmanager.insert_object(book): + if self.songmanager.save_object(book): self.resetBooks() else: QtGui.QMessageBox.critical( @@ -187,7 +187,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): author.last_name = unicode(self.authorform.LastNameEdit.text()) author.display_name = unicode( self.authorform.DisplayEdit.text()) - if self.songmanager.insert_object(author): + if self.songmanager.save_object(author): self.resetAuthors() else: QtGui.QMessageBox.critical( @@ -203,7 +203,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): self.topicform.NameEdit.setText(topic.name) if self.topicform.exec_(False): topic.name = unicode(self.topicform.NameEdit.text()) - if self.songmanager.insert_object(topic): + if self.songmanager.save_object(topic): self.resetTopics() else: QtGui.QMessageBox.critical( @@ -221,7 +221,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): if self.bookform.exec_(False): book.name = unicode(self.bookform.NameEdit.text()) book.publisher = unicode(self.bookform.PublisherEdit.text()) - if self.songmanager.insert_object(book): + if self.songmanager.save_object(book): self.resetBooks() else: QtGui.QMessageBox.critical( diff --git a/openlp/plugins/songs/lib/songimport.py b/openlp/plugins/songs/lib/songimport.py index bc77e7f9b..08855f01a 100644 --- a/openlp/plugins/songs/lib/songimport.py +++ b/openlp/plugins/songs/lib/songimport.py @@ -309,7 +309,7 @@ class SongImport(object): author.display_name = authortext author.last_name = authortext.split(u' ')[-1] author.first_name = u' '.join(authortext.split(u' ')[:-1]) - self.manager.insert_object(author) + self.manager.save_object(author) song.authors.append(author) if self.song_book_name: filter_string = u'name=%s' % self.song_book_name @@ -318,7 +318,7 @@ class SongImport(object): song_book = Book() song_book.name = self.song_book_name song_book.publisher = self.song_book_pub - self.manager.insert_object(song_book) + self.manager.save_object(song_book) song.song_book_id = song_book.id for topictext in self.topics: filter_string = u'name=%s' % topictext @@ -326,9 +326,9 @@ class SongImport(object): if topic is None: topic = Topic() topic.name = topictext - self.manager.insert_object(topic) + self.manager.save_object(topic) song.topics.append(topictext) - self.manager.insert_object(song) + self.manager.save_object(song) def print_song(self): """ diff --git a/openlp/plugins/songusage/songusageplugin.py b/openlp/plugins/songusage/songusageplugin.py index 179ff41af..06687acfe 100644 --- a/openlp/plugins/songusage/songusageplugin.py +++ b/openlp/plugins/songusage/songusageplugin.py @@ -148,7 +148,7 @@ class SongUsagePlugin(Plugin): song_usage_item.authors = u'' for author in audit[1]: song_usage_item.authors += author + u' ' - self.songusagemanager.insert_object(song_usage_item) + self.songusagemanager.save_object(song_usage_item) def onSongUsageDelete(self): self.SongUsagedeleteform.exec_() @@ -162,4 +162,4 @@ class SongUsagePlugin(Plugin): 'SongUsage Plugin
This plugin ' 'records the use of songs and when they have been used during ' 'a live service') - return about_text \ No newline at end of file + return about_text From 4f05a426272ad3c1bab95eeb0efff570dafa5da4 Mon Sep 17 00:00:00 2001 From: andreas Date: Mon, 28 Jun 2010 17:43:40 +0200 Subject: [PATCH 24/49] fixed bug #599066 --- openlp/plugins/images/lib/mediaitem.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py index 29985a9ed..fa3ba0eea 100644 --- a/openlp/plugins/images/lib/mediaitem.py +++ b/openlp/plugins/images/lib/mediaitem.py @@ -120,8 +120,12 @@ class ImageMediaItem(MediaManagerItem): if check_item_selected(self.ListView, translate('ImagePlugin.MediaItem', 'You must select an item to delete.')): items = self.ListView.selectedIndexes() + row_count = [] for item in items: - text = self.ListView.item(item.row()) + row_count.append(item.row()) + row_count.sort(reverse=True) + for item in row_count: + text = self.ListView.item(item) if text: try: os.remove(os.path.join(self.servicePath, @@ -129,7 +133,7 @@ class ImageMediaItem(MediaManagerItem): except OSError: #if not present do not worry pass - self.ListView.takeItem(item.row()) + self.ListView.takeItem(item) SettingsManager.set_list(self.settingsSection, self.settingsSection, self.getFileList()) From 5de4832ae7d047760bc07e6c918b2e23c3abaa6c Mon Sep 17 00:00:00 2001 From: andreas Date: Mon, 28 Jun 2010 18:23:59 +0200 Subject: [PATCH 25/49] changed the variable name --- openlp/plugins/images/lib/mediaitem.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py index fa3ba0eea..5a8b1969e 100644 --- a/openlp/plugins/images/lib/mediaitem.py +++ b/openlp/plugins/images/lib/mediaitem.py @@ -120,11 +120,11 @@ class ImageMediaItem(MediaManagerItem): if check_item_selected(self.ListView, translate('ImagePlugin.MediaItem', 'You must select an item to delete.')): items = self.ListView.selectedIndexes() - row_count = [] + row_list = [] for item in items: - row_count.append(item.row()) - row_count.sort(reverse=True) - for item in row_count: + row_list.append(item.row()) + row_list.sort(reverse=True) + for item in row_list: text = self.ListView.item(item) if text: try: From eafdf71e5c45a3ae63c6dd8364094629edeb9caf Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Mon, 28 Jun 2010 17:48:21 +0100 Subject: [PATCH 26/49] Fix up screen blanking and videos --- openlp/core/ui/maindisplay.py | 56 +++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 21cec593a..632178f87 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -307,6 +307,7 @@ class MainDisplay(DisplayWidget): """ log.debug(u'showDisplay') self.display_blank.setPixmap(self.transparent) + #Trigger actions when display is active again Receiver.send_message(u'maindisplay_active') def addImageWithText(self, frame): @@ -394,28 +395,29 @@ class VideoDisplay(Phonon.VideoWidget): self.screens = screens self.hidden = False self.message = None + self.mediaActive = False self.mediaObject = Phonon.MediaObject() self.setAspectRatio(aspect) self.audioObject = Phonon.AudioOutput(Phonon.VideoCategory) Phonon.createPath(self.mediaObject, self) Phonon.createPath(self.mediaObject, self.audioObject) flags = QtCore.Qt.FramelessWindowHint | QtCore.Qt.Dialog -# # WindowsStaysOnBottomHint is not available in QT4.4 - try: - flags = flags | QtCore.Qt.WindowStaysOnBottomHint - except AttributeError: - pass +## # WindowsStaysOnBottomHint is not available in QT4.4 +# try: +# flags = flags | QtCore.Qt.WindowStaysOnBottomHint +# except AttributeError: +# pass self.setWindowFlags(flags) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'videodisplay_play'), self.onMediaPlay) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'videodisplay_pause'), self.onMediaPause) - QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'videodisplay_background'), self.onMediaBackground) +# QtCore.QObject.connect(Receiver.get_receiver(), +# QtCore.SIGNAL(u'videodisplay_background'), self.onMediaBackground) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'config_updated'), self.setup) QtCore.QObject.connect(self.mediaObject, - QtCore.SIGNAL(u'finished()'), self.onMediaBackground) + QtCore.SIGNAL(u'finished()'), self.onMediaStop) self.setVisible(False) def keyPressEvent(self, event): @@ -454,22 +456,22 @@ class VideoDisplay(Phonon.VideoWidget): for pth in self.outputPaths(): disconnected = pth.disconnect() - def onMediaBackground(self, message=None): - """ - Play a video triggered from the video plugin with the - file name passed in on the event. - Also triggered from the Finish event so the video will loop - if it is triggered from the plugin - """ - log.debug(u'VideoDisplay Queue new media message %s' % message) - #If not file take the stored one - if not message: - message = self.message - # still no file name then stop as it was a normal video stopping - if message: - self.mediaObject.setCurrentSource(Phonon.MediaSource(message)) - self.message = message - self._play() +# def onMediaBackground(self, message=None): +# """ +# Play a video triggered from the video plugin with the +# file name passed in on the event. +# Also triggered from the Finish event so the video will loop +# if it is triggered from the plugin +# """ +# log.debug(u'VideoDisplay Queue new media message %s' % message) +# #If not file take the stored one +# if not message: +# message = self.message +# # still no file name then stop as it was a normal video stopping +# if message: +# self.mediaObject.setCurrentSource(Phonon.MediaSource(message)) +# self.message = message +# self._play() def onMediaQueue(self, message): """ @@ -479,6 +481,7 @@ class VideoDisplay(Phonon.VideoWidget): file = os.path.join(message.get_frame_path(), message.get_frame_title()) self.mediaObject.setCurrentSource(Phonon.MediaSource(file)) + self.mediaActive = True self._play() def onMediaPlay(self): @@ -497,7 +500,6 @@ class VideoDisplay(Phonon.VideoWidget): log.debug(u'VideoDisplay _play called') self.mediaObject.play() self.setVisible(True) - #self.showFullScreen() def onMediaPause(self): """ @@ -513,6 +515,7 @@ class VideoDisplay(Phonon.VideoWidget): """ log.debug(u'VideoDisplay Media stopped by user') self.message = None + self.mediaActive = False self.mediaObject.stop() self.onMediaFinish() @@ -538,7 +541,8 @@ class VideoDisplay(Phonon.VideoWidget): """ if self.hidden: self.hidden = False - self._play() + if self.mediaActive: + self._play() class AudioPlayer(QtCore.QObject): """ From fd09e3d5a0cf9881e08782852689773eb47dc235 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Mon, 28 Jun 2010 18:54:29 +0100 Subject: [PATCH 27/49] Tidy up loop icons --- openlp/core/ui/slidecontroller.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 2a92cd20d..69019a696 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -107,7 +107,6 @@ class SlideController(QtGui.QWidget): self.mainDisplay = self.parent.displayManager.mainDisplay self.loopList = [ u'Start Loop', - u'Stop Loop', u'Loop Separator', u'Image SpinBox' ] @@ -334,6 +333,7 @@ class SlideController(QtGui.QWidget): self.receiveSpinDelay) if isLive: self.Toolbar.makeWidgetsInvisible(self.loopList) + self.Toolbar.actions[u'Stop Loop'].setVisible(False) else: self.Toolbar.makeWidgetsInvisible(self.songEditList) self.Mediabar.setVisible(False) @@ -430,8 +430,8 @@ class SlideController(QtGui.QWidget): self.Mediabar.setVisible(False) self.Toolbar.makeWidgetsInvisible([u'Song Menu']) self.Toolbar.makeWidgetsInvisible(self.loopList) + self.Toolbar.actions[u'Stop Loop'].setVisible(False) if item.is_text(): - self.Toolbar.makeWidgetsInvisible(self.loopList) if QtCore.QSettings().value( self.parent.songsSettingsSection + u'/show songbar', QtCore.QVariant(True)).toBool() and len(self.slideList) > 0: @@ -884,6 +884,8 @@ class SlideController(QtGui.QWidget): if self.PreviewListWidget.rowCount() > 1: self.timer_id = self.startTimer( int(self.DelaySpinBox.value()) * 1000) + self.Toolbar.actions[u'Stop Loop'].setVisible(True) + self.Toolbar.actions[u'Start Loop'].setVisible(False) def onStopLoop(self): """ @@ -892,6 +894,8 @@ class SlideController(QtGui.QWidget): if self.timer_id != 0: self.killTimer(self.timer_id) self.timer_id = 0 + self.Toolbar.actions[u'Start Loop'].setVisible(True) + self.Toolbar.actions[u'Stop Loop'].setVisible(False) def timerEvent(self, event): """ From eccd2999ee3f97343d84d864513febcc4094927e Mon Sep 17 00:00:00 2001 From: andreas Date: Mon, 28 Jun 2010 20:20:05 +0200 Subject: [PATCH 28/49] started fixing deletion bug in media manager (custom still to be done) --- openlp/plugins/images/lib/mediaitem.py | 11 +++----- openlp/plugins/media/lib/mediaitem.py | 11 ++++---- openlp/plugins/presentations/lib/mediaitem.py | 28 +++++++++++-------- 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py index 5a8b1969e..c08f530b0 100644 --- a/openlp/plugins/images/lib/mediaitem.py +++ b/openlp/plugins/images/lib/mediaitem.py @@ -119,13 +119,10 @@ class ImageMediaItem(MediaManagerItem): """ if check_item_selected(self.ListView, translate('ImagePlugin.MediaItem', 'You must select an item to delete.')): - items = self.ListView.selectedIndexes() - row_list = [] - for item in items: - row_list.append(item.row()) + row_list = [item.row() for item in self.ListView.selectedIndexes()] row_list.sort(reverse=True) - for item in row_list: - text = self.ListView.item(item) + for row in row_list: + text = self.ListView.item(row) if text: try: os.remove(os.path.join(self.servicePath, @@ -133,7 +130,7 @@ class ImageMediaItem(MediaManagerItem): except OSError: #if not present do not worry pass - self.ListView.takeItem(item) + self.ListView.takeItem(row) SettingsManager.set_list(self.settingsSection, self.settingsSection, self.getFileList()) diff --git a/openlp/plugins/media/lib/mediaitem.py b/openlp/plugins/media/lib/mediaitem.py index b6de22712..64882dd5a 100644 --- a/openlp/plugins/media/lib/mediaitem.py +++ b/openlp/plugins/media/lib/mediaitem.py @@ -143,11 +143,12 @@ class MediaMediaItem(MediaManagerItem): """ if check_item_selected(self.ListView, translate('MediaPlugin.MediaItem', 'You must select an item to delete.')): - item = self.ListView.currentItem() - row = self.ListView.row(item) - self.ListView.takeItem(row) - SettingsManager.set_list(self.settingsSection, - self.settingsSection, self.getFileList()) + row_list = [item.row() for item in self.ListView.selectedIndexes()] + row_list.sort(reverse=True) + for row in row_list: + self.ListView.takeItem(row) + SettingsManager.set_list(self.settingsSection, + self.settingsSection, self.getFileList()) def loadList(self, list): for file in list: diff --git a/openlp/plugins/presentations/lib/mediaitem.py b/openlp/plugins/presentations/lib/mediaitem.py index 384d28c4a..0651e429e 100644 --- a/openlp/plugins/presentations/lib/mediaitem.py +++ b/openlp/plugins/presentations/lib/mediaitem.py @@ -180,18 +180,22 @@ class PresentationMediaItem(MediaManagerItem): if check_item_selected(self.ListView, translate('PresentationPlugin.MediaItem', 'You must select an item to delete.')): - item = self.ListView.currentItem() - row = self.ListView.row(item) - self.ListView.takeItem(row) - SettingsManager.set_list(self.settingsSection, - self.settingsSection, self.getFileList()) - filepath = unicode(item.data(QtCore.Qt.UserRole).toString()) - #not sure of this has errors - #John please can you look at . - for cidx in self.controllers: - doc = self.controllers[cidx].add_doc(filepath) - doc.presentation_deleted() - doc.close_presentation() + items = self.ListView.selectedIndexes() + row_list = [item.row() for item in items] + row_list.sort(reverse=True) + for item in items: + filepath = unicode(item.data( + QtCore.Qt.UserRole).toString()) + #not sure of this has errors + #John please can you look at . + for cidx in self.controllers: + doc = self.controllers[cidx].add_doc(filepath) + doc.presentation_deleted() + doc.close_presentation() + for row in row_list: + self.ListView.takeItem(row) + SettingsManager.set_list(self.settingsSection, + self.settingsSection, self.getFileList()) def generateSlideData(self, service_item, item=None): items = self.ListView.selectedIndexes() From 51e07d66df9b232adca69c8f33847c6ce2816fca Mon Sep 17 00:00:00 2001 From: andreas Date: Mon, 28 Jun 2010 21:05:55 +0200 Subject: [PATCH 29/49] fixed deletion bug in media manager (custom, media, images, presentations) --- openlp/plugins/custom/lib/mediaitem.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/openlp/plugins/custom/lib/mediaitem.py b/openlp/plugins/custom/lib/mediaitem.py index a4fb54932..d7bd36d7b 100644 --- a/openlp/plugins/custom/lib/mediaitem.py +++ b/openlp/plugins/custom/lib/mediaitem.py @@ -134,11 +134,14 @@ class CustomMediaItem(MediaManagerItem): if check_item_selected(self.ListView, translate('CustomPlugin.MediaItem', 'You must select an item to delete.')): - item = self.ListView.currentItem() - item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] - self.parent.custommanager.delete_custom(item_id) - row = self.ListView.row(item) - self.ListView.takeItem(row) + row_list = [item.row() for item in self.ListView.selectedIndexes()] + row_list.sort(reverse=True) + id_list = [(item.data(QtCore.Qt.UserRole)).toInt()[0] + for item in self.ListView.selectedIndexes()] + for id in id_list: + self.parent.custommanager.delete_custom(id) + for row in row_list: + self.ListView.takeItem(row) def generateSlideData(self, service_item, item=None): raw_slides = [] From 68a934de716f2f672b7332c9c26f55204b53bd9a Mon Sep 17 00:00:00 2001 From: andreas Date: Mon, 28 Jun 2010 22:00:35 +0200 Subject: [PATCH 30/49] - small fixes --- openlp/plugins/custom/lib/mediaitem.py | 5 ----- openlp/plugins/images/lib/mediaitem.py | 4 ++-- openlp/plugins/media/lib/mediaitem.py | 4 ++-- openlp/plugins/presentations/lib/mediaitem.py | 4 ++-- 4 files changed, 6 insertions(+), 11 deletions(-) diff --git a/openlp/plugins/custom/lib/mediaitem.py b/openlp/plugins/custom/lib/mediaitem.py index 1ff229e9d..f2ac04c1b 100644 --- a/openlp/plugins/custom/lib/mediaitem.py +++ b/openlp/plugins/custom/lib/mediaitem.py @@ -144,11 +144,6 @@ class CustomMediaItem(MediaManagerItem): self.parent.custommanager.delete_custom(id) for row in row_list: self.ListView.takeItem(row) - item = self.ListView.currentItem() - item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] - self.parent.custommanager.delete_object(CustomSlide, item_id) - row = self.ListView.row(item) - self.ListView.takeItem(row) def generateSlideData(self, service_item, item=None): raw_slides = [] diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py index c08f530b0..bcc3a84c4 100644 --- a/openlp/plugins/images/lib/mediaitem.py +++ b/openlp/plugins/images/lib/mediaitem.py @@ -131,8 +131,8 @@ class ImageMediaItem(MediaManagerItem): #if not present do not worry pass self.ListView.takeItem(row) - SettingsManager.set_list(self.settingsSection, - self.settingsSection, self.getFileList()) + SettingsManager.set_list(self.settingsSection, + self.settingsSection, self.getFileList()) def loadList(self, list): for file in list: diff --git a/openlp/plugins/media/lib/mediaitem.py b/openlp/plugins/media/lib/mediaitem.py index 64882dd5a..6cd7b175b 100644 --- a/openlp/plugins/media/lib/mediaitem.py +++ b/openlp/plugins/media/lib/mediaitem.py @@ -147,8 +147,8 @@ class MediaMediaItem(MediaManagerItem): row_list.sort(reverse=True) for row in row_list: self.ListView.takeItem(row) - SettingsManager.set_list(self.settingsSection, - self.settingsSection, self.getFileList()) + SettingsManager.set_list(self.settingsSection, + self.settingsSection, self.getFileList()) def loadList(self, list): for file in list: diff --git a/openlp/plugins/presentations/lib/mediaitem.py b/openlp/plugins/presentations/lib/mediaitem.py index 0651e429e..ee50dd556 100644 --- a/openlp/plugins/presentations/lib/mediaitem.py +++ b/openlp/plugins/presentations/lib/mediaitem.py @@ -194,8 +194,8 @@ class PresentationMediaItem(MediaManagerItem): doc.close_presentation() for row in row_list: self.ListView.takeItem(row) - SettingsManager.set_list(self.settingsSection, - self.settingsSection, self.getFileList()) + SettingsManager.set_list(self.settingsSection, + self.settingsSection, self.getFileList()) def generateSlideData(self, service_item, item=None): items = self.ListView.selectedIndexes() From 4a4da4ba2c0aa44fece27167341cf241d09a7b81 Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Tue, 29 Jun 2010 08:07:03 +0100 Subject: [PATCH 31/49] Naming and docstrings --- openlp/core/theme/theme.py | 2 +- openlp/core/utils/languagemanager.py | 79 ++++++++++++++++++++-------- 2 files changed, 57 insertions(+), 24 deletions(-) diff --git a/openlp/core/theme/theme.py b/openlp/core/theme/theme.py index 2ea13d01b..6cddbcb45 100644 --- a/openlp/core/theme/theme.py +++ b/openlp/core/theme/theme.py @@ -168,7 +168,7 @@ class Theme(object): theme_strings.append(u'_%s_' % (getattr(self, key))) return u''.join(theme_strings) - def _set_from_XML(self, xml): + def _set_from_xml(self, xml): """ Set theme class attributes with data from XML diff --git a/openlp/core/utils/languagemanager.py b/openlp/core/utils/languagemanager.py index e556e7e7c..c0315559f 100644 --- a/openlp/core/utils/languagemanager.py +++ b/openlp/core/utils/languagemanager.py @@ -22,7 +22,10 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### - +""" +The :mod:`languagemanager` module provides all the translation settings and +language file loading for OpenLP. +""" import logging import os @@ -42,50 +45,74 @@ class LanguageManager(object): @staticmethod def get_translator(language): + """ + Set up a translator to use in this instance of OpenLP + + ``language`` + The language to load into the translator + """ if LanguageManager.AutoLanguage: language = QtCore.QLocale.system().name() lang_Path = AppLocation.get_directory(AppLocation.AppDir) lang_Path = os.path.join(lang_Path, u'resources', u'i18n') - appTranslator = QtCore.QTranslator() - if appTranslator.load("openlp_" + language, lang_Path): - return appTranslator + app_translator = QtCore.QTranslator() + if app_translator.load("openlp_" + language, lang_Path): + return app_translator @staticmethod def find_qm_files(): + """ + Find all available language files in this OpenLP install + """ trans_dir = AppLocation.get_directory(AppLocation.AppDir) trans_dir = QtCore.QDir(os.path.join(trans_dir, u'resources', u'i18n')) - fileNames = trans_dir.entryList(QtCore.QStringList("*.qm"), + file_names = trans_dir.entryList(QtCore.QStringList("*.qm"), QtCore.QDir.Files, QtCore.QDir.Name) - for name in fileNames: - fileNames.replaceInStrings(name, trans_dir.filePath(name)) - return fileNames + for name in file_names: + file_names.replaceInStrings(name, trans_dir.filePath(name)) + return file_names @staticmethod - def language_name(qmFile): + def language_name(qm_file): + """ + Load the language name from a language file + + ``qm_file`` + The file to obtain the name from + """ translator = QtCore.QTranslator() - translator.load(qmFile) + translator.load(qm_file) return translator.translate('MainWindow', 'English') @staticmethod def get_language(): + """ + Retrieve a saved language to use from settings + """ settings = QtCore.QSettings(u'OpenLP', u'OpenLP') language = unicode(settings.value( u'general/language', QtCore.QVariant(u'[en]')).toString()) log.info(u'Language file: \'%s\' Loaded from conf file' % language) - regEx = QtCore.QRegExp("^\[(.*)\]") - if regEx.exactMatch(language): + reg_ex = QtCore.QRegExp("^\[(.*)\]") + if reg_ex.exactMatch(language): LanguageManager.AutoLanguage = True - language = regEx.cap(1) + language = reg_ex.cap(1) return language @staticmethod def set_language(action): - actionName = u'%s' % action.objectName() - qmList = LanguageManager.get_qm_list() + """ + Set the language to translate OpenLP into + + ``action`` + The language menu option + """ + action_name = u'%s' % action.objectName() + qm_list = LanguageManager.get_qm_list() if LanguageManager.AutoLanguage: - language = u'[%s]' % qmList[actionName] + language = u'[%s]' % qm_list[action_name] else: - language = u'%s' % qmList[actionName] + language = u'%s' % qm_list[action_name] QtCore.QSettings().setValue( u'general/language', QtCore.QVariant(language)) log.info(u'Language file: \'%s\' written to conf file' % language) @@ -96,17 +123,23 @@ class LanguageManager(object): @staticmethod def init_qm_list(): + """ + Initialise the list of available translations + """ LanguageManager.__qmList__ = {} - qmFiles = LanguageManager.find_qm_files() - for i, qmf in enumerate(qmFiles): - regEx = QtCore.QRegExp("^.*openlp_(.*).qm") - if regEx.exactMatch(qmf): - langName = regEx.cap(1) + qm_files = LanguageManager.find_qm_files() + for i, qmf in enumerate(qm_files): + reg_ex = QtCore.QRegExp("^.*openlp_(.*).qm") + if reg_ex.exactMatch(qmf): + lang_name = reg_ex.cap(1) LanguageManager.__qmList__[u'%#2i %s' % (i+1, - LanguageManager.language_name(qmf))] = langName + LanguageManager.language_name(qmf))] = lang_name @staticmethod def get_qm_list(): + """ + Return the list of available translations + """ if LanguageManager.__qmList__ is None: LanguageManager.init_qm_list() return LanguageManager.__qmList__ From 0b8e4f2845d012b5c73e8131361ba3e97170aa99 Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Tue, 29 Jun 2010 11:02:23 +0100 Subject: [PATCH 32/49] Fix filter usage (Fixes theme deletion) --- openlp/plugins/custom/customplugin.py | 2 +- openlp/plugins/songs/songsplugin.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openlp/plugins/custom/customplugin.py b/openlp/plugins/custom/customplugin.py index 7f64aab52..362f8d64c 100644 --- a/openlp/plugins/custom/customplugin.py +++ b/openlp/plugins/custom/customplugin.py @@ -78,7 +78,7 @@ class CustomPlugin(Plugin): return about_text def can_delete_theme(self, theme): - filter_string = u'theme_name=%s' % theme + filter_string = u'theme_name=\'%s\'' % theme if not self.custommanager.get_all_objects_filtered(CustomSlide, filter_string): return True diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py index d128bc6a2..c24352a91 100644 --- a/openlp/plugins/songs/songsplugin.py +++ b/openlp/plugins/songs/songsplugin.py @@ -199,7 +199,7 @@ class SongsPlugin(Plugin): return about_text def can_delete_theme(self, theme): - filter_string = u'theme_name=%s' % theme + filter_string = u'theme_name=\'%s\'' % theme if not self.manager.get_all_objects_filtered(Song, filter_string): return True return False From d37b4d1e8db8d3d3a1be4ba2e77dd682401697d3 Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Tue, 29 Jun 2010 16:25:24 +0100 Subject: [PATCH 33/49] Plugin and other docstrings --- openlp/core/lib/renderer.py | 5 ++++- openlp/plugins/alerts/__init__.py | 2 +- openlp/plugins/bibles/__init__.py | 4 ++-- openlp/plugins/custom/__init__.py | 5 +++++ openlp/plugins/images/__init__.py | 4 ++++ openlp/plugins/media/__init__.py | 6 ++++++ openlp/plugins/presentations/__init__.py | 4 ++++ openlp/plugins/remotes/__init__.py | 4 ++++ openlp/plugins/songs/__init__.py | 4 ++++ openlp/plugins/songusage/__init__.py | 5 +++++ openlp/plugins/songusage/forms/songusagedetailform.py | 2 +- openlp/plugins/songusage/lib/manager.py | 4 +++- 12 files changed, 43 insertions(+), 6 deletions(-) diff --git a/openlp/core/lib/renderer.py b/openlp/core/lib/renderer.py index aa8c0a95a..c7f96528c 100644 --- a/openlp/core/lib/renderer.py +++ b/openlp/core/lib/renderer.py @@ -22,7 +22,10 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### - +""" +The :mod:`renderer` module enables OpenLP to take the input from plugins and +format it for the output display. +""" import logging from PyQt4 import QtGui, QtCore diff --git a/openlp/plugins/alerts/__init__.py b/openlp/plugins/alerts/__init__.py index cb376ec38..76ca202dd 100644 --- a/openlp/plugins/alerts/__init__.py +++ b/openlp/plugins/alerts/__init__.py @@ -24,5 +24,5 @@ ############################################################################### """ The :mod:`alerts` module provides the Alerts plugin for producing impromptu -on-screen announcements during a service +on-screen announcements during a service. """ diff --git a/openlp/plugins/bibles/__init__.py b/openlp/plugins/bibles/__init__.py index ca5ff7508..2491c4142 100644 --- a/openlp/plugins/bibles/__init__.py +++ b/openlp/plugins/bibles/__init__.py @@ -23,6 +23,6 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### """ -The :mod:`bibles' modules provides the Bible plugin to enable OpenLP to display -scripture +The :mod:`bibles' module provides the Bible plugin to enable OpenLP to display +scripture. """ diff --git a/openlp/plugins/custom/__init__.py b/openlp/plugins/custom/__init__.py index 1a348a0df..2b9a101f1 100644 --- a/openlp/plugins/custom/__init__.py +++ b/openlp/plugins/custom/__init__.py @@ -22,3 +22,8 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### +""" +The :mod:`custom` module provides the Custom plugin which allows custom, +themed, text based items to be displayed without having to misuse another item +type. +""" diff --git a/openlp/plugins/images/__init__.py b/openlp/plugins/images/__init__.py index 1a348a0df..58cfb69b5 100644 --- a/openlp/plugins/images/__init__.py +++ b/openlp/plugins/images/__init__.py @@ -22,3 +22,7 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### +""" +The :mod:`images` module provides the Images plugin. The Images plugin +provides the facility to display images from OpenLP. +""" diff --git a/openlp/plugins/media/__init__.py b/openlp/plugins/media/__init__.py index 1a348a0df..28ea0e960 100644 --- a/openlp/plugins/media/__init__.py +++ b/openlp/plugins/media/__init__.py @@ -22,3 +22,9 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### +""" +The :mod:`media` module provides the Media plugin which allows OpenLP to +display videos. The media supported depends not only on the Python support +but also extensively on the codecs installed on the underlying operating system +being picked up and usable by Python. +""" diff --git a/openlp/plugins/presentations/__init__.py b/openlp/plugins/presentations/__init__.py index 1a348a0df..b7f26b39b 100644 --- a/openlp/plugins/presentations/__init__.py +++ b/openlp/plugins/presentations/__init__.py @@ -22,3 +22,7 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### +""" +The :mod:`presentations` module provides the Presentations plugin which allows +OpenLP to show presentations from most popular presentation packages. +""" diff --git a/openlp/plugins/remotes/__init__.py b/openlp/plugins/remotes/__init__.py index 1a348a0df..59b771c0d 100644 --- a/openlp/plugins/remotes/__init__.py +++ b/openlp/plugins/remotes/__init__.py @@ -22,3 +22,7 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### +""" +The :mod:`remotes` plugin allows OpenLP to be controlled from another machine +over a network connection. +""" diff --git a/openlp/plugins/songs/__init__.py b/openlp/plugins/songs/__init__.py index 1a348a0df..4cd5537eb 100644 --- a/openlp/plugins/songs/__init__.py +++ b/openlp/plugins/songs/__init__.py @@ -22,3 +22,7 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### +""" +The :mod:`songs` module provides the Songs plugin. The Songs plugin provides +the main lyric projection function of OpenLP. +""" diff --git a/openlp/plugins/songusage/__init__.py b/openlp/plugins/songusage/__init__.py index 1a348a0df..adebb7c74 100644 --- a/openlp/plugins/songusage/__init__.py +++ b/openlp/plugins/songusage/__init__.py @@ -22,3 +22,8 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### +""" +The :mod:`songusage` module contains the Song Usage plugin. The Song Usage +plugin provides auditing capabilities for reporting the songs you are using to +copyright license organisations. +""" diff --git a/openlp/plugins/songusage/forms/songusagedetailform.py b/openlp/plugins/songusage/forms/songusagedetailform.py index 3cbe46735..be1b8221c 100644 --- a/openlp/plugins/songusage/forms/songusagedetailform.py +++ b/openlp/plugins/songusage/forms/songusagedetailform.py @@ -42,7 +42,7 @@ class SongUsageDetailForm(QtGui.QDialog, Ui_SongUsageDetailDialog): def __init__(self, parent=None): """ - Constructor + Initialise the form """ QtGui.QDialog.__init__(self, None) self.parent = parent diff --git a/openlp/plugins/songusage/lib/manager.py b/openlp/plugins/songusage/lib/manager.py index 363f06fb8..2c34f3a54 100644 --- a/openlp/plugins/songusage/lib/manager.py +++ b/openlp/plugins/songusage/lib/manager.py @@ -22,7 +22,9 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### - +""" +The :mod:`manager` module provides song usage specific database query code +""" import logging from sqlalchemy.exceptions import InvalidRequestError From c0a924e3042e6eddf063c07424b76e70635efcef Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Tue, 29 Jun 2010 17:07:45 +0100 Subject: [PATCH 34/49] Fix service loading --- openlp/core/ui/servicemanager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index 284d9c7e4..1ee0d13a5 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -662,7 +662,7 @@ class ServiceManager(QtGui.QWidget): name = filename.split(os.path.sep) if filename: SettingsManager.set_last_dir(self.parent.serviceSettingsSection, - os.path.split(filename)[0]) + name[0]) zip = None file_to = None try: From 5c4a835dac0f8df18fe32dd40e639ef9135ae104 Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Tue, 29 Jun 2010 23:23:56 +0200 Subject: [PATCH 35/49] Added decent images for remotes, alerts and song usage. --- openlp/plugins/alerts/alertsplugin.py | 6 ++-- openlp/plugins/remotes/remoteplugin.py | 5 +-- openlp/plugins/songusage/songusageplugin.py | 4 +-- resources/images/openlp-2.qrc | 33 +++++++++++--------- resources/images/plugin_alerts.png | Bin 0 -> 762 bytes resources/images/plugin_remote.png | Bin 0 -> 830 bytes resources/images/plugin_songusage.png | Bin 0 -> 946 bytes resources/images/song_maintenance.png | Bin 719 -> 516 bytes scripts/generate_resources.sh | 0 9 files changed, 27 insertions(+), 21 deletions(-) create mode 100644 resources/images/plugin_alerts.png create mode 100644 resources/images/plugin_remote.png create mode 100644 resources/images/plugin_songusage.png mode change 100644 => 100755 scripts/generate_resources.sh diff --git a/openlp/plugins/alerts/alertsplugin.py b/openlp/plugins/alerts/alertsplugin.py index b442edc5b..46d4e8cb7 100644 --- a/openlp/plugins/alerts/alertsplugin.py +++ b/openlp/plugins/alerts/alertsplugin.py @@ -41,7 +41,7 @@ class alertsPlugin(Plugin): def __init__(self, plugin_helpers): Plugin.__init__(self, u'Alerts', u'1.9.2', plugin_helpers) self.weight = -3 - self.icon = build_icon(u':/media/media_image.png') + self.icon = build_icon(u':/plugins/plugin_alerts.png') self.alertsmanager = AlertsManager(self) self.manager = Manager(u'alerts', init_schema) self.alertForm = AlertForm(self.manager, self) @@ -65,7 +65,7 @@ class alertsPlugin(Plugin): """ log.info(u'add tools menu') self.toolsAlertItem = QtGui.QAction(tools_menu) - AlertIcon = build_icon(u':/tools/tools_alert.png') + AlertIcon = build_icon(u':/plugins/plugin_alerts.png') self.toolsAlertItem.setIcon(AlertIcon) self.toolsAlertItem.setObjectName(u'toolsAlertItem') self.toolsAlertItem.setText( @@ -102,4 +102,4 @@ class alertsPlugin(Plugin): about_text = translate('AlertsPlugin', 'Alerts Plugin
This plugin ' 'controls the displaying of alerts on the presentations screen') - return about_text \ No newline at end of file + return about_text diff --git a/openlp/plugins/remotes/remoteplugin.py b/openlp/plugins/remotes/remoteplugin.py index 7004207e4..fad7ecbe8 100644 --- a/openlp/plugins/remotes/remoteplugin.py +++ b/openlp/plugins/remotes/remoteplugin.py @@ -25,7 +25,7 @@ import logging -from openlp.core.lib import Plugin, translate +from openlp.core.lib import Plugin, translate, build_icon from openlp.plugins.remotes.lib import RemoteTab, HttpServer log = logging.getLogger(__name__) @@ -38,6 +38,7 @@ class RemotesPlugin(Plugin): remotes constructor """ Plugin.__init__(self, u'Remotes', u'1.9.2', plugin_helpers) + self.icon = build_icon(u':/plugins/plugin_remote.png') self.weight = -1 self.server = None @@ -74,4 +75,4 @@ class RemotesPlugin(Plugin): 'provides the ability to send messages to a running version of ' 'openlp on a different computer via a web browser or other app
' 'The Primary use for this would be to send alerts from a creche') - return about_text \ No newline at end of file + return about_text diff --git a/openlp/plugins/songusage/songusageplugin.py b/openlp/plugins/songusage/songusageplugin.py index 06687acfe..a9994902a 100644 --- a/openlp/plugins/songusage/songusageplugin.py +++ b/openlp/plugins/songusage/songusageplugin.py @@ -42,7 +42,7 @@ class SongUsagePlugin(Plugin): def __init__(self, plugin_helpers): Plugin.__init__(self, u'SongUsage', u'1.9.2', plugin_helpers) self.weight = -4 - self.icon = build_icon(u':/media/media_image.png') + self.icon = build_icon(u':/plugins/plugin_songusage.png') self.songusagemanager = None self.songusageActive = False @@ -76,7 +76,7 @@ class SongUsagePlugin(Plugin): translate('SongUsagePlugin', 'Generate report on Song Usage')) self.SongUsageReport.setObjectName(u'SongUsageReport') #SongUsage activation - SongUsageIcon = build_icon(u':/tools/tools_alert.png') + SongUsageIcon = build_icon(u':/plugins/plugin_songusage.png') self.SongUsageStatus = QtGui.QAction(tools_menu) self.SongUsageStatus.setIcon(SongUsageIcon) self.SongUsageStatus.setCheckable(True) diff --git a/resources/images/openlp-2.qrc b/resources/images/openlp-2.qrc index 49309b8d5..ba382e0fd 100644 --- a/resources/images/openlp-2.qrc +++ b/resources/images/openlp-2.qrc @@ -1,5 +1,5 @@ - + topic_edit.png author_add.png author_delete.png @@ -17,7 +17,12 @@ song_topic_edit.png song_book_edit.png - + + plugin_alerts.png + plugin_remote.png + plugin_songusage.png + + general_preview.png general_live.png general_add.png @@ -29,7 +34,7 @@ general_open.png general_save.png - + slide_close.png slide_first.png slide_last.png @@ -42,7 +47,7 @@ media_playback_stop.png media_playback_pause.png - + openlp-logo-16x16.png openlp-logo-32x32.png openlp-logo-48x48.png @@ -50,27 +55,27 @@ openlp-logo-128x128.png openlp-logo-256x256.png - + openlp-about-logo.png openlp-splash-screen.png - + import_selectall.png import_move_to_list.png import_remove.png import_load.png - + export_selectall.png export_remove.png export_load.png export_move_to_list.png - + wizard_importsong.bmp wizard_importbible.bmp - + service_notes.png service_item_notes.png service_bottom.png @@ -78,7 +83,7 @@ service_top.png service_up.png - + system_close.png system_about.png system_help_contents.png @@ -89,7 +94,7 @@ system_exit.png system_settings.png - + media_custom.png media_presentation.png media_image.png @@ -100,16 +105,16 @@ media_stop.png image_clapperboard.png - + messagebox_critical.png messagebox_info.png messagebox_warning.png - + tools_add.png tools_alert.png - + theme_delete.png theme_new.png theme_edit.png diff --git a/resources/images/plugin_alerts.png b/resources/images/plugin_alerts.png new file mode 100644 index 0000000000000000000000000000000000000000..331aa268725a4edff3fa6cab7dfaf5af24708c2c GIT binary patch literal 762 zcmVz8xpUII{8&=iH{wnUDxx6o*XQpr9@S zFA7f~5wyArj)7engn2gzstbkiqQW4^o2U%CF~JzoO$Y@oEjOFGxwX#D=9!*z-Y(o0 zQwbk<`S`x?dETGrWkiIXV2m*U4FEj(r*8lvv=^C(b_IaeKp-$7%W^`Nt(9kFmQEb*nE7Psy^?IqR ztBayjPKwQXiHJy&qz3@_5)S~tZnyVDm%lIP5+5is35raDTrL;6T(06>jn7at{N)#b z6NTa?0O;-Qt@Qi-eRcKC_36+(fN|S~@H}|_-^lXUJE&`DvkeRkTqt;90$|BxGRLp` z`_FAAgHTsr1Ed20I-3=AHY>#hx%don>+f;v=GF56+8JZu1VM0DR8;s+oj!Xq`ROt= zB~%pnI#Td;q)OJLXMdu$eUO)BITH*9=a|Ri@x7aV`>56uZi>(Ll#p-S-98`QF5Pu? z_YC6M`lSYE%SBUFRn<|4v#}`^ewD>Op@g67c8A+32*R;4RaJ9_VQ3cj;Fel`NG<2K z4it!wpY0ZJYUYhH+a;BVtcGD|0MIfrGV&yqO2ufONT<`uv9Yli0FE#K41f(l8-N-B s|?9jsO4v literal 0 HcmV?d00001 diff --git a/resources/images/plugin_remote.png b/resources/images/plugin_remote.png new file mode 100644 index 0000000000000000000000000000000000000000..d70f0f6decbbe811a9e6df6116068284ecdbadb2 GIT binary patch literal 830 zcmV-E1Ht@>P)K~#9!rIUL|Q&Akpe|HbN+nh>dIi}`H)TEdBk4oepJ^ZI3 zRM4OKNQan0fA*I`|MdX%`d}G>&_a4)QV51ksBJhOn=>CQak$Mb^KP=;x$eBX_jIq} z(z3ria5(4p{r%3D59fCdh7f}N49Q+%U8h462d)$_I4j~1hcJHpU=3@8XwYvx! zyXTUl9P_Y9ld3DoRAO0&WFVwHWE5uIVf58Q5mIUVp1!^~`j3IGZBivqm6>mzSLdWD zlECT=3I`dU0y~oFFsxYhVadjs)v^a~ofe9YL+vF^9*$Tdfh`bJcTC-Q@!5wamcpotu)pTTEi&|H zh1OOis_C-5x4S6RXY`_K!d@ZhzX>o*D-CL(zhBm&`0B9I6|XPD1;0K!vL>KgF6NphH%H-(&BCgGCAqWK^dvn338!*RYv z-tyV*Mc{zQnXG)xkOY z3qgPL)!dEj4E*rUHgDB5oMZ1+=6XLl)_lur8*h4>P6u}Vg=bAggFx7VD}ku8zCz=M zJ;uu~E1r1|wZYeVc0QzCv!-)Ow!Jr*ObkH~Az}Z&x$p1%3#G4>BVCt-PXGV_07*qo IM6N<$f?XSWF#rGn literal 0 HcmV?d00001 diff --git a/resources/images/plugin_songusage.png b/resources/images/plugin_songusage.png new file mode 100644 index 0000000000000000000000000000000000000000..bf110aa6dff6cbe89fe174c5e1af42facfd1194d GIT binary patch literal 946 zcmV;j15NyiP)Z zy6Lv7N=dgY`2`^L53r~dDz)8rfhs{mg>0)tRxDcDlEmWx9>DRH@nt^GOwU*aMR}z& zGmCTH@0{m+!#R$F_r-CX2w;q2CK8Fb8~ZadwW~s z0PqwO|0mC_tgJjrCX=)2bUHpcIT=+h&3&P&>UR?p6C;|Yy%GUDd`ene zT)ZpGvcMQ~JAf#P5Cj1n&!f?C@b=n5V*CSXcz8ImzP^5s4wLfvyy6<@)6>%`vmD`A zyT->61@$&iG5P=;GI9_O$e0-)g3l|1y1Ku%w)S#$b#-=YYfIw+Tx2qt2smEn+? zi9aa>GE2<_@L?)TAHO|fv3@24W2tYJDGN0M6*ln`aSsUZV<5%A4Ew&xyEq# z`WnTn9wpm|$K#{XXw(x31RMZ^b)ng8{yQXCwnrBE{F^SuS`I!8`w$=VqGnjQsCUsY zOmw;?0)D?p9ENJOnmrf+80huYrQS$Jy|8SK=!?*sCQ6kayt0FbGd`qZ3Pyt>T5Sfu z-#=6?m#udVF8BBMk3&Q|M2ktsgLp6*fG7YbdI#B)Ci2B=^jII9%|P6wN~L1mGH^j2 z92^uxs?gr{kbBjFR_Q_wN^s!{ltpXCd9??<-b1NW5~|fI69rzly~?3b=xgoG`PMHl z8kinY;0%myjQ9nNha_~(K1u|#)#-qpK66xWk^A|l@BbP=yaCzmwC(7yhmWZWv2bu& zX`@_cIIFrWctq}qP!$J1?i5+4l97MSw!XPFa6z7(mYPhOy7T*S9qB|6$thYT57@R1 zSFKiy{c&`pXR^i;D2C8}1$^N@vq5d-pTkl^zs}z}fzScS% z>PW{r(MThm=vYTO)aKFC`yiyYcW;!1zdRlg3<4 ztl5=$QW!wFB!4JlnqrM}eosXTTtyJ3Jj#GRO|@za*QLP*AtjU)89WQ5*n;*Sb4Z7KEYjr!A>1robFOsq=|46%N{= z+Bh1t3lDShTydy&0zcT^1Pf0{UR5;6x zlU+#DaTJDM-P%UkY-CKckux@^Eh@yhX-x+~(T(B4+!kRMqJKhJUDQ>n7|X1S8niV< zLTW-J?8BNd4P0|uV30;%OqjAJmJLIlbN1i-|GLR5W!roIyyw7qP8KqV!SG0?R4Q9( zLLXaRURsJoA~v^sw9{nlUP%k9Yt=_)W~O5_O_PN`3&ixqn9%ApALWX&vP_2K>a`Z* z{O?~R9$zJ1?|)bfz!?BL0Av9`b{d`uKruTz3yPw^j5Z=LXoiO zfP&gTd+3sR|e+B_;LlcV4hK+u`x~F){H8f`38*a&x)7z*Jz}^4wzFvLJ6y zUiR>aOJAWVuhi7l!t3+n=wS)gs5LN{41_{I{?=c-WLR8W?Aru4H8skJ}+@P zog|q|5ZAD4wfb!JcU4uTjmP8N2A~4K+63$M9m0_j*QD8OBIOn3#53k0{rwg{fC>P+ z{$FM5w10QBowPfwkt;2i2|u4tjHbuLG3fXVK$y;z?AG>M*PmJXs5;Gg!sT*FLt_JZ z?R+&~P>?TAYueq;J2%ZeCZf}6i9{kHHRo!G)jklH$x1aFwxu+U&*wKqSC&B~k|YPlY}l5vfW>A95z7)DKOqN)!#gGp`(W?T(3|@Jl9~Jpb8hZuGeCDo oqtX1YU%tJtSsf1ntRlnw1491o=%O}YqW}N^07*qoM6N<$g1%xuXaE2J diff --git a/scripts/generate_resources.sh b/scripts/generate_resources.sh old mode 100644 new mode 100755 From 4767ec08a2031e6a4e247218aef48753112b2079 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Wed, 30 Jun 2010 05:52:52 +0100 Subject: [PATCH 36/49] Image display refactoring --- openlp/core/lib/serviceitem.py | 10 ++- openlp/core/ui/maindisplay.py | 106 ++++++++++++++++++++---------- openlp/core/ui/slidecontroller.py | 10 ++- 3 files changed, 88 insertions(+), 38 deletions(-) diff --git a/openlp/core/lib/serviceitem.py b/openlp/core/lib/serviceitem.py index dfcad984a..c107a1872 100644 --- a/openlp/core/lib/serviceitem.py +++ b/openlp/core/lib/serviceitem.py @@ -35,6 +35,7 @@ import uuid from PyQt4 import QtGui from openlp.core.lib import build_icon, resize_image +from openlp.core.utils import AppLocation log = logging.getLogger(__name__) @@ -92,6 +93,7 @@ class ServiceItem(object): self.is_valid = True self.cache = {} self.icon = None + self.serviceItemPath = AppLocation.get_section_data_path(u'serviceItems') def add_capability(self, capability): """ @@ -153,9 +155,12 @@ class ServiceItem(object): del self.cache[len(self._display_frames)] log.log(15, u'Formatting took %4s' % (time.time() - before)) elif self.service_item_type == ServiceItemType.Image: - for slide in self._raw_frames: + for count, slide in enumerate(self._raw_frames): slide[u'image'] = resize_image(slide[u'image'], self.render_manager.width, self.render_manager.height) + path = os.path.join(self.serviceItemPath, self._uuid + unicode(count) + u'.png') + slide[u'image'].save(path) + slide[u'display'] = path elif self.service_item_type == ServiceItemType.Command: pass else: @@ -371,7 +376,8 @@ class ServiceItem(object): if self.service_item_type == ServiceItemType.Text: return self.render_individual(row) else: - return {u'main':self._raw_frames[row][u'image'], u'trans':None} + return {u'main':self._raw_frames[row][u'image'], + u'trans':None, u'display':self._raw_frames[row][u'display']} def get_frame_title(self, row=0): """ diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 632178f87..4b571822c 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -26,14 +26,21 @@ import logging import os -from PyQt4 import QtCore, QtGui +from PyQt4 import QtCore, QtGui, QtWebKit from PyQt4.phonon import Phonon from openlp.core.lib import Receiver, resize_image from openlp.core.ui import HideMode +from openlp.core.utils import AppLocation log = logging.getLogger(__name__) +HTMLIMAGE = """ + + + + """ + class DisplayManager(QtGui.QWidget): """ Wrapper class to hold the display widgets. @@ -76,10 +83,16 @@ class DisplayManager(QtGui.QWidget): def addAlert(self, alertMessage, location): """ - Handles the add Alert Message to the Displays + Handles the addition of an Alert Message to the Displays """ self.mainDisplay.addAlert(alertMessage, location) + def displayImage(self, path): + """ + Handles the addition of a background Image to the displays + """ + self.mainDisplay.displayImage(path) + def onStartVideo(self, item): """ Handles the Starting of a Video and Display Management @@ -183,7 +196,7 @@ class MainDisplay(DisplayWidget): self.primary = True self.blankFrame = None self.frame = None - #Hide desktop for now untill we know where to put it + #Hide desktop for now until we know where to put it #and what size it should be. self.setVisible(False) @@ -198,6 +211,7 @@ class MainDisplay(DisplayWidget): #Sort out screen locations and sizes self.setGeometry(self.screen[u'size']) self.scene.setSceneRect(0,0,self.size().width(), self.size().height()) + self.imageDisplay.setGeometry(0, 0, self.size().width(), self.size().height()) #Build a custom splash screen self.InitialFrame = QtGui.QImage( self.screen[u'size'].width(), @@ -211,7 +225,7 @@ class MainDisplay(DisplayWidget): (self.screen[u'size'].width() - splash_image.width()) / 2, (self.screen[u'size'].height() - splash_image.height()) / 2, splash_image) - self.display_image.setPixmap(QtGui.QPixmap.fromImage(self.InitialFrame)) + #self.display_image.setPixmap(QtGui.QPixmap.fromImage(self.InitialFrame)) self.repaint() #Build a Black screen painter = QtGui.QPainter() @@ -241,9 +255,15 @@ class MainDisplay(DisplayWidget): self.setScene(self.scene) def setupImage(self): - self.display_image = QtGui.QGraphicsPixmapItem() - self.display_image.setZValue(2) - self.scene.addItem(self.display_image) +# self.display_image = QtGui.QGraphmaindisplay.pyicsPixmapItem() +# self.display_image.setZValue(2) +# self.scene.addItem(self.display_image) + self.imageDisplay = QtWebKit.QWebView() + self.proxy = QtGui.QGraphicsProxyWidget() + self.proxy.setWidget(self.imageDisplay) + self.proxy.setWindowFlags(QtCore.Qt.Window | QtCore.Qt.FramelessWindowHint) + self.proxy.setZValue(2) + self.scene.addItem(self.proxy) def setupText(self): #self.display_text = QtGui.QGraphicsTextItem() @@ -319,7 +339,7 @@ class MainDisplay(DisplayWidget): def addAlert(self, message, location): """ Places the Alert text on the display at the correct location - ``messgae`` + ``message`` Text to be displayed ``location`` Where on the screen the text should be. From the AlertTab @@ -334,7 +354,16 @@ class MainDisplay(DisplayWidget): self.alertText.setPos(0,self.size().height() - 76) self.alertText.setHtml(message) - def frameView(self, frame, transition=False, display=True): + def displayImage(self, path): + """ + Places the Image passed on the display screen + ``path`` + The path to the image to be displayed + """ + log.debug(u'adddisplayImage') + self.imageDisplay.setHtml(HTMLIMAGE % path) + + def frameView(self, frame, transition=False): """ Called from a slide controller to display a frame if the alert is in progress the alert is added on top @@ -343,33 +372,44 @@ class MainDisplay(DisplayWidget): ``transition`` Are transitions required. """ - log.debug(u'frameView %d' % display) - if display: - if transition: - if self.frame is not None: - self.display_text.setPixmap( - QtGui.QPixmap.fromImage(self.frame)) - self.update() - self.frame = None - if frame[u'trans'] is not None: - self.display_text.setPixmap( - QtGui.QPixmap.fromImage(frame[u'trans'])) - self.repaint() - self.frame = frame[u'trans'] + log.debug(u'frameView') + if transition: + if self.frame is not None: self.display_text.setPixmap( - QtGui.QPixmap.fromImage(frame[u'main'])) - self.display_frame = frame[u'main'] + QtGui.QPixmap.fromImage(self.frame)) + self.update() + self.frame = None + if frame[u'trans'] is not None: + self.display_text.setPixmap( + QtGui.QPixmap.fromImage(frame[u'trans'])) self.repaint() - else: - if isinstance(frame, QtGui.QPixmap): - self.display_text.setPixmap(frame) - else: - self.display_text.setPixmap(QtGui.QPixmap.fromImage(frame)) - self.display_frame = frame - if not self.isVisible() and self.screens.display: - self.setVisible(True) + self.frame = frame[u'trans'] + self.display_text.setPixmap( + QtGui.QPixmap.fromImage(frame[u'main'])) + self.display_frame = frame[u'main'] + self.repaint() else: - self.storeText = QtGui.QPixmap.fromImage(frame[u'main']) + if isinstance(frame, QtGui.QPixmap): + self.display_text.setPixmap(frame) + else: + self.display_text.setPixmap(QtGui.QPixmap.fromImage(frame)) + self.display_frame = frame + if not self.isVisible() and self.screens.display: + self.setVisible(True) + + def closeEvent(self, event): + """ + Shutting down cleans up background files + """ + serviceItemPath = AppLocation.get_section_data_path(u'serviceItems') + for file in os.listdir(serviceItemPath): + file_path = os.path.join(serviceItemPath, file) + try: + if os.path.isfile(file_path): + os.remove(file_path) + except OSError: + log.exception(u'Failed to clean up servicePath') + class VideoDisplay(Phonon.VideoWidget): """ diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 69019a696..5a34d09f8 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -105,6 +105,7 @@ class SlideController(QtGui.QWidget): self.isLive = isLive self.parent = parent self.mainDisplay = self.parent.displayManager.mainDisplay + self.displayManager = self.parent.displayManager self.loopList = [ u'Start Loop', u'Loop Separator', @@ -526,8 +527,8 @@ class SlideController(QtGui.QWidget): # blanked = self.blankButton.isChecked() # else: # blanked = False -# Receiver.send_message(u'%s_start' % serviceItem.name.lower(), -# [serviceItem, self.isLive, blanked, slideno]) + Receiver.send_message(u'%s_start' % serviceItem.name.lower(), + [serviceItem, self.isLive, True, slideno]) self.slideList = {} width = self.parent.ControlSplitter.sizes()[self.split] #Set pointing cursor when we have somthing to point at @@ -781,7 +782,10 @@ class SlideController(QtGui.QWidget): log.log( 15, u'Slide Rendering took %4s' % (time.time() - before)) if self.isLive: - self.mainDisplay.frameView(frame, True)#, self.canDisplay) + if self.serviceItem.is_text(): + self.mainDisplay.frameView(frame, True) + else: + self.displayManager.displayImage(frame[u'display']) self.selectedRow = row Receiver.send_message(u'slidecontroller_%s_changed' % self.typePrefix, row) From 912516e8f023ff9130d876011c9b91367fdf5e8d Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Wed, 30 Jun 2010 12:59:09 +0100 Subject: [PATCH 37/49] Really fix service loading! --- openlp/core/ui/mainwindow.py | 5 ++++- openlp/core/ui/servicemanager.py | 6 +++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 7f1c0408b..f4d573d20 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -845,7 +845,10 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): recentFileCount = QtCore.QSettings().value( self.generalSettingsSection + u'/max recent files', QtCore.QVariant(4)).toInt()[0] - if filename and filename not in self.recentFiles: + if filename: + position = self.recentFiles.indexOf(filename) + if position != -1: + self.recentFiles.removeAt(position) self.recentFiles.insert(0, QtCore.QString(filename)) while self.recentFiles.count() > recentFileCount: self.recentFiles.removeLast() diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index 1ee0d13a5..837415921 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -625,13 +625,13 @@ class ServiceManager(QtGui.QWidget): def onLoadService(self, lastService=False): if lastService: - filename = SettingsManager.get_last_dir( - self.parent.serviceSettingsSection) + filename = self.parent.recentFiles[0] else: filename = QtGui.QFileDialog.getOpenFileName( self, translate('ServiceManager', 'Open Service'), SettingsManager.get_last_dir( self.parent.serviceSettingsSection), u'Services (*.osz)') + filename = QtCore.QDir.toNativeSeparators(filename) self.loadService(filename) def loadService(self, filename=None): @@ -662,7 +662,7 @@ class ServiceManager(QtGui.QWidget): name = filename.split(os.path.sep) if filename: SettingsManager.set_last_dir(self.parent.serviceSettingsSection, - name[0]) + os.path.split(filename)[0]) zip = None file_to = None try: From 7198148a485dd73d595db65c3752777cc035e230 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Wed, 30 Jun 2010 17:10:54 +0100 Subject: [PATCH 38/49] Replaceable Backgound images now work --- openlp/core/ui/maindisplay.py | 13 +++++++------ openlp/plugins/images/lib/mediaitem.py | 12 ++++++------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 4b571822c..715228e21 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -211,7 +211,7 @@ class MainDisplay(DisplayWidget): #Sort out screen locations and sizes self.setGeometry(self.screen[u'size']) self.scene.setSceneRect(0,0,self.size().width(), self.size().height()) - self.imageDisplay.setGeometry(0, 0, self.size().width(), self.size().height()) + self.webView.setGeometry(0, 0, self.size().width(), self.size().height()) #Build a custom splash screen self.InitialFrame = QtGui.QImage( self.screen[u'size'].width(), @@ -255,12 +255,13 @@ class MainDisplay(DisplayWidget): self.setScene(self.scene) def setupImage(self): -# self.display_image = QtGui.QGraphmaindisplay.pyicsPixmapItem() -# self.display_image.setZValue(2) -# self.scene.addItem(self.display_image) - self.imageDisplay = QtWebKit.QWebView() + self.webView = QtWebKit.QWebView() + self.page = self.webView.page() + self.imageDisplay = self.page.mainFrame() + self.imageDisplay.setScrollBarPolicy(QtCore.Qt.Vertical, QtCore.Qt.ScrollBarAlwaysOff) + self.imageDisplay.setScrollBarPolicy(QtCore.Qt.Horizontal, QtCore.Qt.ScrollBarAlwaysOff) self.proxy = QtGui.QGraphicsProxyWidget() - self.proxy.setWidget(self.imageDisplay) + self.proxy.setWidget(self.webView) self.proxy.setWindowFlags(QtCore.Qt.Window | QtCore.Qt.FramelessWindowHint) self.proxy.setZValue(2) self.scene.addItem(self.proxy) diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py index bcc3a84c4..a1c2d03fe 100644 --- a/openlp/plugins/images/lib/mediaitem.py +++ b/openlp/plugins/images/lib/mediaitem.py @@ -175,12 +175,12 @@ class ImageMediaItem(MediaManagerItem): translate('ImagePlugin.MediaItem', 'No item selected'), translate('ImagePlugin.MediaItem', 'You must select one item')) - items = self.ListView.selectedIndexes() - for item in items: - bitem = self.ListView.item(item.row()) - filename = unicode(bitem.data(QtCore.Qt.UserRole).toString()) - frame = QtGui.QImage(unicode(filename)) - self.parent.maindisplay.addImageWithText(frame) + return + item = self.buildServiceItem() + item.render() + self.parent.live_controller.displayManager. \ + displayImage(item.get_rendered_frame(0)[u'display']) + def onPreviewClick(self): MediaManagerItem.onPreviewClick(self) From 8b5931d50cb059bd28bc30d428208d10c446079e Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Wed, 30 Jun 2010 17:30:25 +0100 Subject: [PATCH 39/49] Video and Image updates --- openlp/core/ui/maindisplay.py | 33 ++++++++++++++++++++ openlp/plugins/media/lib/mediaitem.py | 44 ++++++++++++++++----------- 2 files changed, 59 insertions(+), 18 deletions(-) diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 715228e21..ae6d400fe 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -41,6 +41,23 @@ HTMLIMAGE = """ """ +#http://www.steveheffernan.com/html5-video-player/demo-video-player.html +HTMLVIDEO = u""" + + \" + + + """ + class DisplayManager(QtGui.QWidget): """ Wrapper class to hold the display widgets. @@ -93,6 +110,12 @@ class DisplayManager(QtGui.QWidget): """ self.mainDisplay.displayImage(path) + def displayVideo(self, path): + """ + Handles the addition of a background Video to the displays + """ + self.mainDisplay.displayVideo(path) + def onStartVideo(self, item): """ Handles the Starting of a Video and Display Management @@ -364,6 +387,16 @@ class MainDisplay(DisplayWidget): log.debug(u'adddisplayImage') self.imageDisplay.setHtml(HTMLIMAGE % path) + def displayVideo(self, path): + """ + Places the Video passed on the display screen + ``path`` + The path to the image to be displayed + """ + log.debug(u'adddisplayVideo') + self.imageDisplay.setHtml(HTMLVIDEO % + (path, self.screen[u'size'].width(), self.screen[u'size'].height())) + def frameView(self, frame, transition=False): """ Called from a slide controller to display a frame diff --git a/openlp/plugins/media/lib/mediaitem.py b/openlp/plugins/media/lib/mediaitem.py index 6cd7b175b..938dc1297 100644 --- a/openlp/plugins/media/lib/mediaitem.py +++ b/openlp/plugins/media/lib/mediaitem.py @@ -29,7 +29,8 @@ import os from PyQt4 import QtCore, QtGui from openlp.core.lib import MediaManagerItem, BaseListWithDnD, build_icon, \ - ItemCapabilities, SettingsManager, translate, check_item_selected + ItemCapabilities, SettingsManager, translate, check_item_selected, \ + context_menu_action log = logging.getLogger(__name__) @@ -73,13 +74,13 @@ class MediaMediaItem(MediaManagerItem): self.hasNewIcon = False self.hasEditIcon = False -# def addListViewToToolBar(self): -# MediaManagerItem.addListViewToToolBar(self) -# self.ListView.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) -# self.ListView.addAction( -# context_menu_action(self.ListView, u':/slides/slide_blank.png', -# translate('MediaPlugin.MediaItem', 'Replace Live Background'), -# self.onReplaceClick)) + def addListViewToToolBar(self): + MediaManagerItem.addListViewToToolBar(self) + self.ListView.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) + self.ListView.addAction( + context_menu_action(self.ListView, u':/slides/slide_blank.png', + translate('MediaPlugin.MediaItem', 'Replace Live Background'), + self.onReplaceClick)) def addEndHeaderBar(self): self.ImageWidget = QtGui.QWidget(self) @@ -92,24 +93,31 @@ class MediaMediaItem(MediaManagerItem): self.ImageWidget.setSizePolicy(sizePolicy) self.ImageWidget.setObjectName(u'ImageWidget') #Replace backgrounds do not work at present so remove functionality. -# self.blankButton = self.Toolbar.addToolbarButton( -# u'Replace Background', u':/slides/slide_blank.png', -# translate('MediaPlugin.MediaItem', 'Replace Live Background'), -# self.onReplaceClick, False) + self.blankButton = self.Toolbar.addToolbarButton( + u'Replace Background', u':/slides/slide_blank.png', + translate('MediaPlugin.MediaItem', 'Replace Live Background'), + self.onReplaceClick, False) # Add the song widget to the page layout self.PageLayout.addWidget(self.ImageWidget) -# def onReplaceClick(self): + def onReplaceClick(self): # if self.background: # self.background = False # Receiver.send_message(u'videodisplay_stop') # else: # self.background = True -# if not self.ListView.selectedIndexes(): -# QtGui.QMessageBox.information(self, -# translate('MediaPlugin.MediaItem', 'No item selected'), -# translate('MediaPlugin.MediaItem', -# 'You must select one item')) + if not self.ListView.selectedIndexes(): + QtGui.QMessageBox.information(self, + translate('MediaPlugin.MediaItem', 'No item selected'), + translate('MediaPlugin.MediaItem', + 'You must select one item')) + return + item = self.ListView.currentItem() + if item is None: + return False + filename = unicode(item.data(QtCore.Qt.UserRole).toString()) + print filename + self.parent.live_controller.displayManager.displayVideo(filename) # items = self.ListView.selectedIndexes() # for item in items: # bitem = self.ListView.item(item.row()) From 9ebdc1e2d3fad3184fd086a4e21c9098d24542a2 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Wed, 30 Jun 2010 18:05:12 +0100 Subject: [PATCH 40/49] Update missing checks --- openlp/plugins/images/lib/mediaitem.py | 17 +++++++---------- openlp/plugins/media/lib/mediaitem.py | 18 ++++++------------ 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py index a1c2d03fe..ee7a22106 100644 --- a/openlp/plugins/images/lib/mediaitem.py +++ b/openlp/plugins/images/lib/mediaitem.py @@ -170,16 +170,13 @@ class ImageMediaItem(MediaManagerItem): return False def onReplaceClick(self): - if not self.ListView.selectedIndexes(): - QtGui.QMessageBox.information(self, - translate('ImagePlugin.MediaItem', 'No item selected'), - translate('ImagePlugin.MediaItem', - 'You must select one item')) - return - item = self.buildServiceItem() - item.render() - self.parent.live_controller.displayManager. \ - displayImage(item.get_rendered_frame(0)[u'display']) + if check_item_selected(self.ListView, + translate('ImagePlugin.MediaItem', + 'You must select an item to process.')): + item = self.buildServiceItem() + item.render() + self.parent.live_controller.displayManager. \ + displayImage(item.get_rendered_frame(0)[u'display']) def onPreviewClick(self): diff --git a/openlp/plugins/media/lib/mediaitem.py b/openlp/plugins/media/lib/mediaitem.py index 938dc1297..10c398912 100644 --- a/openlp/plugins/media/lib/mediaitem.py +++ b/openlp/plugins/media/lib/mediaitem.py @@ -106,18 +106,12 @@ class MediaMediaItem(MediaManagerItem): # Receiver.send_message(u'videodisplay_stop') # else: # self.background = True - if not self.ListView.selectedIndexes(): - QtGui.QMessageBox.information(self, - translate('MediaPlugin.MediaItem', 'No item selected'), - translate('MediaPlugin.MediaItem', - 'You must select one item')) - return - item = self.ListView.currentItem() - if item is None: - return False - filename = unicode(item.data(QtCore.Qt.UserRole).toString()) - print filename - self.parent.live_controller.displayManager.displayVideo(filename) + if check_item_selected(self.ListView, + translate('ImagePlugin.MediaItem', + 'You must select an item to process.')): + item = self.ListView.currentItem() + filename = unicode(item.data(QtCore.Qt.UserRole).toString()) + self.parent.live_controller.displayManager.displayVideo(filename) # items = self.ListView.selectedIndexes() # for item in items: # bitem = self.ListView.item(item.row()) From 568e80748cc9bb522cc28fcfa7e9e9824c6b9702 Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Wed, 30 Jun 2010 20:16:07 +0200 Subject: [PATCH 41/49] Change namespace of other plugin icons. --- openlp/plugins/bibles/bibleplugin.py | 4 ++-- openlp/plugins/custom/customplugin.py | 4 ++-- openlp/plugins/images/imageplugin.py | 4 ++-- openlp/plugins/media/mediaplugin.py | 2 +- openlp/plugins/presentations/presentationplugin.py | 2 +- openlp/plugins/songs/songsplugin.py | 2 +- resources/images/openlp-2.qrc | 12 ++++++------ .../images/{media_bible.png => plugin_bibles.png} | Bin .../images/{media_custom.png => plugin_custom.png} | Bin .../images/{media_image.png => plugin_images.png} | Bin .../images/{media_video.png => plugin_media.png} | Bin ...ia_presentation.png => plugin_presentations.png} | Bin .../images/{media_song.png => plugin_songs.png} | Bin 13 files changed, 15 insertions(+), 15 deletions(-) rename resources/images/{media_bible.png => plugin_bibles.png} (100%) rename resources/images/{media_custom.png => plugin_custom.png} (100%) rename resources/images/{media_image.png => plugin_images.png} (100%) rename resources/images/{media_video.png => plugin_media.png} (100%) rename resources/images/{media_presentation.png => plugin_presentations.png} (100%) rename resources/images/{media_song.png => plugin_songs.png} (100%) diff --git a/openlp/plugins/bibles/bibleplugin.py b/openlp/plugins/bibles/bibleplugin.py index 2398ead9c..b891b14ad 100644 --- a/openlp/plugins/bibles/bibleplugin.py +++ b/openlp/plugins/bibles/bibleplugin.py @@ -38,7 +38,7 @@ class BiblePlugin(Plugin): def __init__(self, plugin_helpers): Plugin.__init__(self, u'Bibles', u'1.9.2', plugin_helpers) self.weight = -9 - self.icon = build_icon(u':/media/media_bible.png') + self.icon = build_icon(u':/plugins/plugin_bibles.png') #Register the bible Manager self.status = PluginStatus.Active self.manager = None @@ -99,4 +99,4 @@ class BiblePlugin(Plugin): def can_delete_theme(self, theme): if self.settings_tab.bible_theme == theme: return False - return True \ No newline at end of file + return True diff --git a/openlp/plugins/custom/customplugin.py b/openlp/plugins/custom/customplugin.py index 362f8d64c..76d597f28 100644 --- a/openlp/plugins/custom/customplugin.py +++ b/openlp/plugins/custom/customplugin.py @@ -50,7 +50,7 @@ class CustomPlugin(Plugin): self.weight = -5 self.custommanager = Manager(u'custom', init_schema) self.edit_custom_form = EditCustomForm(self.custommanager) - self.icon = build_icon(u':/media/media_custom.png') + self.icon = build_icon(u':/plugins/plugin_custom.png') self.status = PluginStatus.Active def get_settings_tab(self): @@ -82,4 +82,4 @@ class CustomPlugin(Plugin): if not self.custommanager.get_all_objects_filtered(CustomSlide, filter_string): return True - return False \ No newline at end of file + return False diff --git a/openlp/plugins/images/imageplugin.py b/openlp/plugins/images/imageplugin.py index 8e9f9e220..9ebaa128f 100644 --- a/openlp/plugins/images/imageplugin.py +++ b/openlp/plugins/images/imageplugin.py @@ -36,7 +36,7 @@ class ImagePlugin(Plugin): def __init__(self, plugin_helpers): Plugin.__init__(self, u'Images', u'1.9.2', plugin_helpers) self.weight = -7 - self.icon = build_icon(u':/media/media_image.png') + self.icon = build_icon(u':/plugins/plugin_images.png') self.status = PluginStatus.Active def initialise(self): @@ -64,4 +64,4 @@ class ImagePlugin(Plugin): 'an image is selected any songs which are rendered will use the ' 'selected image from the background instead of the one provied by ' 'the theme.
') - return about_text \ No newline at end of file + return about_text diff --git a/openlp/plugins/media/mediaplugin.py b/openlp/plugins/media/mediaplugin.py index f7c2c998f..33261f1e2 100644 --- a/openlp/plugins/media/mediaplugin.py +++ b/openlp/plugins/media/mediaplugin.py @@ -38,7 +38,7 @@ class MediaPlugin(Plugin): def __init__(self, plugin_helpers): Plugin.__init__(self, u'Media', u'1.9.2', plugin_helpers) self.weight = -6 - self.icon = build_icon(u':/media/media_video.png') + self.icon = build_icon(u':/plugins/plugin_media.png') # passed with drag and drop messages self.dnd_id = u'Media' self.status = PluginStatus.Active diff --git a/openlp/plugins/presentations/presentationplugin.py b/openlp/plugins/presentations/presentationplugin.py index 9303d5921..d92483b88 100644 --- a/openlp/plugins/presentations/presentationplugin.py +++ b/openlp/plugins/presentations/presentationplugin.py @@ -40,7 +40,7 @@ class PresentationPlugin(Plugin): self.controllers = {} Plugin.__init__(self, u'Presentations', u'1.9.2', plugin_helpers) self.weight = -8 - self.icon = build_icon(u':/media/media_presentation.png') + self.icon = build_icon(u':/plugins/plugin_presentations.png') self.status = PluginStatus.Active def get_settings_tab(self): diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py index c24352a91..82a780fa9 100644 --- a/openlp/plugins/songs/songsplugin.py +++ b/openlp/plugins/songs/songsplugin.py @@ -57,7 +57,7 @@ class SongsPlugin(Plugin): Plugin.__init__(self, u'Songs', u'1.9.2', plugin_helpers) self.weight = -10 self.manager = SongManager() - self.icon = build_icon(u':/media/media_song.png') + self.icon = build_icon(u':/plugins/plugin_songs.png') self.status = PluginStatus.Active def get_settings_tab(self): diff --git a/resources/images/openlp-2.qrc b/resources/images/openlp-2.qrc index ba382e0fd..118a30eae 100644 --- a/resources/images/openlp-2.qrc +++ b/resources/images/openlp-2.qrc @@ -19,6 +19,12 @@
plugin_alerts.png + plugin_bibles.png + plugin_custom.png + plugin_images.png + plugin_media.png + plugin_presentations.png + plugin_songs.png plugin_remote.png plugin_songusage.png @@ -95,12 +101,6 @@ system_settings.png
- media_custom.png - media_presentation.png - media_image.png - media_song.png - media_bible.png - media_video.png media_time.png media_stop.png image_clapperboard.png diff --git a/resources/images/media_bible.png b/resources/images/plugin_bibles.png similarity index 100% rename from resources/images/media_bible.png rename to resources/images/plugin_bibles.png diff --git a/resources/images/media_custom.png b/resources/images/plugin_custom.png similarity index 100% rename from resources/images/media_custom.png rename to resources/images/plugin_custom.png diff --git a/resources/images/media_image.png b/resources/images/plugin_images.png similarity index 100% rename from resources/images/media_image.png rename to resources/images/plugin_images.png diff --git a/resources/images/media_video.png b/resources/images/plugin_media.png similarity index 100% rename from resources/images/media_video.png rename to resources/images/plugin_media.png diff --git a/resources/images/media_presentation.png b/resources/images/plugin_presentations.png similarity index 100% rename from resources/images/media_presentation.png rename to resources/images/plugin_presentations.png diff --git a/resources/images/media_song.png b/resources/images/plugin_songs.png similarity index 100% rename from resources/images/media_song.png rename to resources/images/plugin_songs.png From 6038d46a56d08966b0cfbc25b1cc3e45a0509526 Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Wed, 30 Jun 2010 20:36:57 +0200 Subject: [PATCH 42/49] Make ServiceItems use the plugin's icon instead of some arb image "prediction" that is prone to failure. --- openlp/core/lib/mediamanageritem.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py index 2983eaca2..322ce8cd0 100644 --- a/openlp/core/lib/mediamanageritem.py +++ b/openlp/core/lib/mediamanageritem.py @@ -525,8 +525,7 @@ class MediaManagerItem(QtGui.QWidget): if self.ServiceItemIconName: service_item.add_icon(self.ServiceItemIconName) else: - service_item.add_icon( - u':/media/media_' + self.PluginNameShort.lower() + u'.png') + service_item.add_icon(self.parent.icon) if self.generateSlideData(service_item, item): return service_item else: From 079d72f93fb86564a0c11c860095f04f431d124b Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Wed, 30 Jun 2010 23:05:51 +0100 Subject: [PATCH 43/49] Database refactoring --- openlp/core/lib/db.py | 19 ++- openlp/plugins/bibles/lib/db.py | 7 +- openlp/plugins/custom/customplugin.py | 3 +- openlp/plugins/songs/forms/songimportform.py | 2 +- openlp/plugins/songs/lib/__init__.py | 47 +++++++- openlp/plugins/songs/lib/manager.py | 116 ------------------- openlp/plugins/songs/lib/mediaitem.py | 15 ++- openlp/plugins/songs/lib/songimport.py | 12 +- openlp/plugins/songs/songsplugin.py | 11 +- 9 files changed, 84 insertions(+), 148 deletions(-) delete mode 100644 openlp/plugins/songs/lib/manager.py diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index b000fe918..a60521218 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -166,17 +166,17 @@ class Manager(object): else: return self.session.query(object_class).get(key) - def get_object_filtered(self, object_class, filter_string): + def get_object_filtered(self, object_class, filter_clause): """ Returns an object matching specified criteria ``object_class`` The type of object to return - ``filter_string`` + ``filter_clause`` The criteria to select the object by """ - return self.session.query(object_class).filter(filter_string).first() + return self.session.query(object_class).filter(filter_clause).first() def get_all_objects(self, object_class, order_by_ref=None): """ @@ -192,17 +192,24 @@ class Manager(object): return self.session.query(object_class).order_by(order_by_ref).all() return self.session.query(object_class).all() - def get_all_objects_filtered(self, object_class, filter_string): + def get_all_objects_filtered(self, object_class, filter_clause, + order_by_ref=None): """ Returns a selection of objects from the database ``object_class`` The type of objects to return - ``filter_string`` + ``filter_clause`` The filter governing selection of objects to return + + ``order_by_ref`` + Any parameters to order the returned objects by. Defaults to None. """ - return self.session.query(object_class).filter(filter_string).all() + if order_by_ref: + return self.session.query(object_class).filter(filter_clause) \ + .order_by(order_by_ref).all() + return self.session.query(object_class).filter(filter_clause).all() def delete_object(self, object_class, key): """ diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py index c799d71dd..a453d5bcc 100644 --- a/openlp/plugins/bibles/lib/db.py +++ b/openlp/plugins/bibles/lib/db.py @@ -299,11 +299,10 @@ class BibleDB(QtCore.QObject, Manager): The name of the book to return """ log.debug(u'BibleDb.get_book("%s")', book) - db_book = self.session.query(Book).filter( - Book.name.like(book + u'%')).first() + db_book = self.get_object_filtered(Book, Book.name.like(book + u'%')) if db_book is None: - db_book = self.session.query(Book).filter( - Book.abbreviation.like(book + u'%')).first() + db_book = self.get_object_filtered(Book, + Book.abbreviation.like(book + u'%')) return db_book def get_verses(self, reference_list): diff --git a/openlp/plugins/custom/customplugin.py b/openlp/plugins/custom/customplugin.py index 76d597f28..e65205351 100644 --- a/openlp/plugins/custom/customplugin.py +++ b/openlp/plugins/custom/customplugin.py @@ -78,8 +78,7 @@ class CustomPlugin(Plugin): return about_text def can_delete_theme(self, theme): - filter_string = u'theme_name=\'%s\'' % theme if not self.custommanager.get_all_objects_filtered(CustomSlide, - filter_string): + CustomSlide.theme_name == theme): return True return False diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index 8a830d720..09db3dcb8 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -30,7 +30,7 @@ from PyQt4 import QtCore, QtGui from songimportwizard import Ui_SongImportWizard from openlp.core.lib import Receiver, SettingsManager, translate #from openlp.core.utils import AppLocation -from openlp.plugins.songs.lib.manager import SongFormat +from openlp.plugins.songs.lib import SongFormat log = logging.getLogger(__name__) diff --git a/openlp/plugins/songs/lib/__init__.py b/openlp/plugins/songs/lib/__init__.py index dddb23b4e..8c07c31c7 100644 --- a/openlp/plugins/songs/lib/__init__.py +++ b/openlp/plugins/songs/lib/__init__.py @@ -25,6 +25,52 @@ from openlp.core.lib import translate +#from openlp.plugins.songs.lib import OpenLyricsSong, OpenSongSong, CCLISong, \ +# CSVSong + +class SongFormat(object): + """ + This is a special enumeration class that holds the various types of songs, + plus a few helper functions to facilitate generic handling of song types + for importing. + """ + Unknown = -1 + OpenLyrics = 0 + OpenSong = 1 + CCLI = 2 + CSV = 3 + + @staticmethod + def get_class(id): + """ + Return the appropriate imeplementation class. + + ``id`` + The song format. + """ +# if id == SongFormat.OpenLyrics: +# return OpenLyricsSong +# elif id == SongFormat.OpenSong: +# return OpenSongSong +# elif id == SongFormat.CCLI: +# return CCLISong +# elif id == SongFormat.CSV: +# return CSVSong +# else: + return None + + @staticmethod + def list(): + """ + Return a list of the supported song formats. + """ + return [ + SongFormat.OpenLyrics, + SongFormat.OpenSong, + SongFormat.CCLI, + SongFormat.CSV + ] + class VerseType(object): """ VerseType provides an enumeration for the tags that may be associated @@ -91,7 +137,6 @@ class VerseType(object): unicode(VerseType.to_string(VerseType.Other)).lower(): return VerseType.Other -from manager import SongManager from songstab import SongsTab from mediaitem import SongMediaItem from songimport import SongImport diff --git a/openlp/plugins/songs/lib/manager.py b/openlp/plugins/songs/lib/manager.py deleted file mode 100644 index 10ec5aa34..000000000 --- a/openlp/plugins/songs/lib/manager.py +++ /dev/null @@ -1,116 +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 openlp.core.lib.db import Manager -from openlp.plugins.songs.lib.db import init_schema, Song, Author -#from openlp.plugins.songs.lib import OpenLyricsSong, OpenSongSong, CCLISong, \ -# CSVSong - -log = logging.getLogger(__name__) - -class SongFormat(object): - """ - This is a special enumeration class that holds the various types of songs, - plus a few helper functions to facilitate generic handling of song types - for importing. - """ - Unknown = -1 - OpenLyrics = 0 - OpenSong = 1 - CCLI = 2 - CSV = 3 - - @staticmethod - def get_class(id): - """ - Return the appropriate imeplementation class. - - ``id`` - The song format. - """ -# if id == SongFormat.OpenLyrics: -# return OpenLyricsSong -# elif id == SongFormat.OpenSong: -# return OpenSongSong -# elif id == SongFormat.CCLI: -# return CCLISong -# elif id == SongFormat.CSV: -# return CSVSong -# else: - return None - - @staticmethod - def list(): - """ - Return a list of the supported song formats. - """ - return [ - SongFormat.OpenLyrics, - SongFormat.OpenSong, - SongFormat.CCLI, - SongFormat.CSV - ] - - -class SongManager(Manager): - """ - The Song Manager provides a central location for all database code. This - class takes care of connecting to the database and running all the queries. - """ - log.info(u'Song manager loaded') - - def __init__(self): - """ - Creates the connection to the database, and creates the tables if they - don't exist. - """ - log.debug(u'Song Initialising') - Manager.__init__(self, u'songs', init_schema) - log.debug(u'Song Initialised') - - def search_song_title(self, keywords): - """ - Searches the song title for keywords. - """ - return self.session.query(Song).filter( - Song.search_title.like(u'%' + keywords + u'%')).order_by( - Song.search_title.asc()).all() - - def search_song_lyrics(self, keywords): - """ - Searches the song lyrics for keywords. - """ - return self.session.query(Song).filter( - Song.search_lyrics.like(u'%' + keywords + u'%')).order_by( - Song.search_lyrics.asc()).all() - - def get_song_from_author(self, keywords): - """ - Searches the song authors for keywords. - """ - return self.session.query(Author).filter(Author.display_name.like( - u'%' + keywords + u'%')).order_by(Author.display_name.asc()).all() diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index 94002b6f4..7ed30e5e0 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -165,18 +165,21 @@ class SongMediaItem(MediaManagerItem): search_type = self.SearchTypeComboBox.currentIndex() if search_type == 0: log.debug(u'Titles Search') - search_results = self.parent.manager.search_song_title( - search_keywords) + search_results = self.parent.manager.get_all_objects_filtered(Song, + Song.search_title.like(u'%' + keywords + u'%'), + Song.search_title.asc()) self.displayResultsSong(search_results) elif search_type == 1: log.debug(u'Lyrics Search') - search_results = self.parent.manager.search_song_lyrics( - search_keywords) + search_results = self.parent.manager.get_all_objects_filtered(Song, + Song.search_lyrics.like(u'%' + keywords + u'%'), + Song.search_lyrics.asc()) self.displayResultsSong(search_results) elif search_type == 2: log.debug(u'Authors Search') - search_results = self.parent.manager.get_song_from_author( - search_keywords) + search_results = self.parent.manager.get_all_objects_filtered( + Author, Author.display_name.like(u'%' + search_keywords + u'%'), + Author.display_name.asc()) self.displayResultsAuthor(search_results) #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 diff --git a/openlp/plugins/songs/lib/songimport.py b/openlp/plugins/songs/lib/songimport.py index 08855f01a..115f52e58 100644 --- a/openlp/plugins/songs/lib/songimport.py +++ b/openlp/plugins/songs/lib/songimport.py @@ -302,8 +302,8 @@ class SongImport(object): song.theme_name = self.theme_name song.ccli_number = self.ccli_number for authortext in self.authors: - filter_string = u'display_name=%s' % authortext - author = self.manager.get_object_filtered(Author, filter_string) + author = self.manager.get_object_filtered(Author, + Author.display_name == authortext) if author is None: author = Author() author.display_name = authortext @@ -312,8 +312,8 @@ class SongImport(object): self.manager.save_object(author) song.authors.append(author) if self.song_book_name: - filter_string = u'name=%s' % self.song_book_name - song_book = self.manager.get_object_filtered(Book, filter_string) + song_book = self.manager.get_object_filtered(Book, + Book.name == self.song_book_name) if song_book is None: song_book = Book() song_book.name = self.song_book_name @@ -321,8 +321,8 @@ class SongImport(object): self.manager.save_object(song_book) song.song_book_id = song_book.id for topictext in self.topics: - filter_string = u'name=%s' % topictext - topic = self.manager.get_object_filtered(Topic, filter_string) + topic = self.manager.get_object_filtered(Topic, + Topic.name == topictext) if topic is None: topic = Topic() topic.name = topictext diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py index 82a780fa9..3567ff3a1 100644 --- a/openlp/plugins/songs/songsplugin.py +++ b/openlp/plugins/songs/songsplugin.py @@ -29,7 +29,8 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import Plugin, build_icon, PluginStatus, Receiver, \ translate -from openlp.plugins.songs.lib import SongManager, SongMediaItem, SongsTab +from openlp.core.lib.db import Manager +from openlp.plugins.songs.lib import SongMediaItem, SongsTab from openlp.plugins.songs.lib.db import Song try: @@ -56,7 +57,7 @@ class SongsPlugin(Plugin): """ Plugin.__init__(self, u'Songs', u'1.9.2', plugin_helpers) self.weight = -10 - self.manager = SongManager() + self.manager = Manager(u'songs', init_schema) self.icon = build_icon(u':/plugins/plugin_songs.png') self.status = PluginStatus.Active @@ -65,8 +66,6 @@ class SongsPlugin(Plugin): def initialise(self): log.info(u'Songs Initialising') - #if self.songmanager is None: - # self.songmanager = SongManager() Plugin.initialise(self) self.insert_toolbox_item() self.media_item.displayResultsSong( @@ -199,7 +198,7 @@ class SongsPlugin(Plugin): return about_text def can_delete_theme(self, theme): - filter_string = u'theme_name=\'%s\'' % theme - if not self.manager.get_all_objects_filtered(Song, filter_string): + if not self.manager.get_all_objects_filtered(Song, + Song.theme_name == theme): return True return False From c61121bb51ac620a59025be85e1a910981d4368d Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Thu, 1 Jul 2010 11:31:37 +0100 Subject: [PATCH 44/49] DB cleanups --- openlp/core/lib/db.py | 11 ++++++----- openlp/plugins/songs/songsplugin.py | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index a60521218..f20f3ab38 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -188,9 +188,10 @@ class Manager(object): ``order_by_ref`` Any parameters to order the returned objects by. Defaults to None. """ + query = self.session.query(object_class) if order_by_ref: - return self.session.query(object_class).order_by(order_by_ref).all() - return self.session.query(object_class).all() + return query.order_by(order_by_ref).all() + return query.all() def get_all_objects_filtered(self, object_class, filter_clause, order_by_ref=None): @@ -206,10 +207,10 @@ class Manager(object): ``order_by_ref`` Any parameters to order the returned objects by. Defaults to None. """ + query = self.session.query(object_class).filter(filter_clause) if order_by_ref: - return self.session.query(object_class).filter(filter_clause) \ - .order_by(order_by_ref).all() - return self.session.query(object_class).filter(filter_clause).all() + return query.order_by(order_by_ref).all() + return query.all() def delete_object(self, object_class, key): """ diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py index 3567ff3a1..e2740748b 100644 --- a/openlp/plugins/songs/songsplugin.py +++ b/openlp/plugins/songs/songsplugin.py @@ -31,7 +31,7 @@ from openlp.core.lib import Plugin, build_icon, PluginStatus, Receiver, \ translate from openlp.core.lib.db import Manager from openlp.plugins.songs.lib import SongMediaItem, SongsTab -from openlp.plugins.songs.lib.db import Song +from openlp.plugins.songs.lib.db import init_schema, Song try: from openlp.plugins.songs.lib import SofImport, OooImport From 254ac02561c936ccb087c9aab1996d6d47a096de Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Thu, 1 Jul 2010 13:56:02 +0100 Subject: [PATCH 45/49] Alerts: Import and long lines --- openlp/plugins/alerts/lib/alertsmanager.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/openlp/plugins/alerts/lib/alertsmanager.py b/openlp/plugins/alerts/lib/alertsmanager.py index 10565a3d1..aac3eccb9 100644 --- a/openlp/plugins/alerts/lib/alertsmanager.py +++ b/openlp/plugins/alerts/lib/alertsmanager.py @@ -25,7 +25,7 @@ import logging -from PyQt4 import QtCore, QtGui +from PyQt4 import QtCore from openlp.core.lib import Receiver, translate @@ -95,7 +95,8 @@ class AlertsManager(QtCore.QObject): alertTab = self.parent.alertsTab text = HTMLCODE % (alertTab.font_color, alertTab.bg_color, alertTab.font_face, alertTab.font_size, text) - self.parent.preview_controller.parent.displayManager.addAlert(text, alertTab.location) + self.parent.preview_controller.parent.displayManager.addAlert(text, + alertTab.location) # check to see if we have a timer running if self.timer_id == 0: self.timer_id = self.startTimer(int(alertTab.timeout) * 1000) @@ -111,7 +112,8 @@ class AlertsManager(QtCore.QObject): log.debug(u'timer event') alertTab = self.parent.alertsTab if event.timerId() == self.timer_id: - self.parent.preview_controller.parent.displayManager.addAlert(u'', alertTab.location) + self.parent.preview_controller.parent.displayManager.addAlert(u'', + alertTab.location) self.killTimer(self.timer_id) self.timer_id = 0 self.generateAlert() From d939a39895b47e29349db948ea40ff2962abe6ab Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Thu, 1 Jul 2010 16:46:51 +0100 Subject: [PATCH 46/49] Cleanup signals (Bug #599146) --- openlp/core/ui/amendthemedialog.py | 70 ++++---------- openlp/core/ui/amendthemeform.py | 85 ++++++++--------- openlp/core/ui/displaytab.py | 1 - openlp/core/ui/generaltab.py | 147 ++++++++++------------------- 4 files changed, 114 insertions(+), 189 deletions(-) diff --git a/openlp/core/ui/amendthemedialog.py b/openlp/core/ui/amendthemedialog.py index a75f5e686..2bb202964 100644 --- a/openlp/core/ui/amendthemedialog.py +++ b/openlp/core/ui/amendthemedialog.py @@ -178,13 +178,11 @@ class Ui_AmendThemeDialog(object): self.MainFontLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.FontMainSize) self.FontMainSizeSpinBox = QtGui.QSpinBox(self.FontMainGroupBox) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, + defaultSizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth( + defaultSizePolicy.setHeightForWidth( self.FontMainSizeSpinBox.sizePolicy().hasHeightForWidth()) - self.FontMainSizeSpinBox.setSizePolicy(sizePolicy) + self.FontMainSizeSpinBox.setSizePolicy(defaultSizePolicy) self.FontMainSizeSpinBox.setMinimumSize(QtCore.QSize(70, 0)) self.FontMainSizeSpinBox.setProperty(u'value', QtCore.QVariant(16)) self.FontMainSizeSpinBox.setMaximum(999) @@ -230,8 +228,7 @@ class Ui_AmendThemeDialog(object): self.FontMainLineSpacingSpinBox) self.FontMainLinesPageLabel = QtGui.QLabel(self.FontMainGroupBox) self.FontMainLinesPageLabel.setObjectName(u'FontMainLinesPageLabel') - self.MainFontLayout.setWidget(6, QtGui.QFormLayout.LabelRole, - self.FontMainLinesPageLabel) + self.MainFontLayout.addRow(self.FontMainLinesPageLabel) spacerItem1 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) self.MainLeftLayout.addItem(spacerItem1) @@ -275,13 +272,9 @@ class Ui_AmendThemeDialog(object): self.MainLocationLayout.setWidget(4, QtGui.QFormLayout.LabelRole, self.FontMainHeightLabel) self.FontMainXSpinBox = QtGui.QSpinBox(self.MainLocationGroupBox) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, - QtGui.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth( + defaultSizePolicy.setHeightForWidth( self.FontMainXSpinBox.sizePolicy().hasHeightForWidth()) - self.FontMainXSpinBox.setSizePolicy(sizePolicy) + self.FontMainXSpinBox.setSizePolicy(defaultSizePolicy) self.FontMainXSpinBox.setMinimumSize(QtCore.QSize(78, 0)) self.FontMainXSpinBox.setProperty(u'value', QtCore.QVariant(0)) self.FontMainXSpinBox.setMaximum(9999) @@ -289,39 +282,27 @@ class Ui_AmendThemeDialog(object): self.MainLocationLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.FontMainXSpinBox) self.FontMainYSpinBox = QtGui.QSpinBox(self.MainLocationGroupBox) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, - QtGui.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth( + defaultSizePolicy.setHeightForWidth( self.FontMainYSpinBox.sizePolicy().hasHeightForWidth()) - self.FontMainYSpinBox.setSizePolicy(sizePolicy) + self.FontMainYSpinBox.setSizePolicy(defaultSizePolicy) self.FontMainYSpinBox.setMinimumSize(QtCore.QSize(78, 0)) self.FontMainYSpinBox.setMaximum(9999) self.FontMainYSpinBox.setObjectName(u'FontMainYSpinBox') self.MainLocationLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.FontMainYSpinBox) self.FontMainWidthSpinBox = QtGui.QSpinBox(self.MainLocationGroupBox) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, - QtGui.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth( + defaultSizePolicy.setHeightForWidth( self.FontMainWidthSpinBox.sizePolicy().hasHeightForWidth()) - self.FontMainWidthSpinBox.setSizePolicy(sizePolicy) + self.FontMainWidthSpinBox.setSizePolicy(defaultSizePolicy) self.FontMainWidthSpinBox.setMinimumSize(QtCore.QSize(78, 0)) self.FontMainWidthSpinBox.setMaximum(9999) self.FontMainWidthSpinBox.setObjectName(u'FontMainWidthSpinBox') self.MainLocationLayout.setWidget(3, QtGui.QFormLayout.FieldRole, self.FontMainWidthSpinBox) self.FontMainHeightSpinBox = QtGui.QSpinBox(self.MainLocationGroupBox) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, - QtGui.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth( + defaultSizePolicy.setHeightForWidth( self.FontMainHeightSpinBox.sizePolicy().hasHeightForWidth()) - self.FontMainHeightSpinBox.setSizePolicy(sizePolicy) + self.FontMainHeightSpinBox.setSizePolicy(defaultSizePolicy) self.FontMainHeightSpinBox.setMinimumSize(QtCore.QSize(78, 0)) self.FontMainHeightSpinBox.setMaximum(9999) self.FontMainHeightSpinBox.setObjectName(u'FontMainHeightSpinBox') @@ -378,13 +359,9 @@ class Ui_AmendThemeDialog(object): self.FooterFontLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.FontFooterSizeLabel) self.FontFooterSizeSpinBox = QtGui.QSpinBox(self.FooterFontGroupBox) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, - QtGui.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth( + defaultSizePolicy.setHeightForWidth( self.FontFooterSizeSpinBox.sizePolicy().hasHeightForWidth()) - self.FontFooterSizeSpinBox.setSizePolicy(sizePolicy) + self.FontFooterSizeSpinBox.setSizePolicy(defaultSizePolicy) self.FontFooterSizeSpinBox.setMinimumSize(QtCore.QSize(70, 0)) self.FontFooterSizeSpinBox.setProperty(u'value', QtCore.QVariant(10)) self.FontFooterSizeSpinBox.setMaximum(999) @@ -453,13 +430,9 @@ class Ui_AmendThemeDialog(object): self.LocationFooterLayout.setWidget(4, QtGui.QFormLayout.LabelRole, self.FontFooterHeightLabel) self.FontFooterXSpinBox = QtGui.QSpinBox(self.LocationFooterGroupBox) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, - QtGui.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth( + defaultSizePolicy.setHeightForWidth( self.FontFooterXSpinBox.sizePolicy().hasHeightForWidth()) - self.FontFooterXSpinBox.setSizePolicy(sizePolicy) + self.FontFooterXSpinBox.setSizePolicy(defaultSizePolicy) self.FontFooterXSpinBox.setMinimumSize(QtCore.QSize(78, 0)) self.FontFooterXSpinBox.setProperty(u'value', QtCore.QVariant(0)) self.FontFooterXSpinBox.setMaximum(9999) @@ -467,13 +440,9 @@ class Ui_AmendThemeDialog(object): self.LocationFooterLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.FontFooterXSpinBox) self.FontFooterYSpinBox = QtGui.QSpinBox(self.LocationFooterGroupBox) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, - QtGui.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth( - self.FontFooterYSpinBox.sizePolicy().hasHeightForWidth()) - self.FontFooterYSpinBox.setSizePolicy(sizePolicy) + defaultSizePolicy.setHeightForWidth( + self.FontFooterXSpinBox.sizePolicy().hasHeightForWidth()) + self.FontFooterYSpinBox.setSizePolicy(defaultSizePolicy) self.FontFooterYSpinBox.setMinimumSize(QtCore.QSize(78, 0)) self.FontFooterYSpinBox.setProperty(u'value', QtCore.QVariant(0)) self.FontFooterYSpinBox.setMaximum(9999) @@ -901,4 +870,3 @@ class Ui_AmendThemeDialog(object): self.ThemeTabWidget.indexOf(self.OtherOptionsTab), translate('AmendThemeForm', '&Other Options')) self.PreviewGroupBox.setTitle(translate('AmendThemeForm', 'Preview')) - diff --git a/openlp/core/ui/amendthemeform.py b/openlp/core/ui/amendthemeform.py index c85eff4b8..6333d7146 100644 --- a/openlp/core/ui/amendthemeform.py +++ b/openlp/core/ui/amendthemeform.py @@ -43,8 +43,8 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog): self.path = None self.theme = ThemeXML() self.setupUi(self) - #define signals - #Buttons + # Define signals + # Buttons QtCore.QObject.connect(self.Color1PushButton, QtCore.SIGNAL(u'pressed()'), self.onColor1PushButtonClicked) QtCore.QObject.connect(self.Color2PushButton, @@ -60,7 +60,7 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog): QtCore.SIGNAL(u'pressed()'), self.onShadowColorPushButtonClicked) QtCore.QObject.connect(self.ImageToolButton, QtCore.SIGNAL(u'pressed()'), self.onImageToolButtonClicked) - #Combo boxes + # Combo boxes QtCore.QObject.connect(self.BackgroundComboBox, QtCore.SIGNAL(u'activated(int)'), self.onBackgroundComboBoxSelected) QtCore.QObject.connect(self.BackgroundTypeComboBox, @@ -82,57 +82,58 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog): QtCore.SIGNAL(u'activated(int)'), self.onHorizontalComboBoxSelected) QtCore.QObject.connect(self.VerticalComboBox, QtCore.SIGNAL(u'activated(int)'), self.onVerticalComboBoxSelected) - #Spin boxes + # Spin boxes QtCore.QObject.connect(self.FontMainSizeSpinBox, - QtCore.SIGNAL(u'editingFinished()'), + QtCore.SIGNAL(u'valueChanged(int)'), self.onFontMainSizeSpinBoxChanged) QtCore.QObject.connect(self.FontFooterSizeSpinBox, - QtCore.SIGNAL(u'editingFinished()'), + QtCore.SIGNAL(u'valueChanged(int)'), self.onFontFooterSizeSpinBoxChanged) + QtCore.QObject.connect(self.FontMainXSpinBox, + QtCore.SIGNAL(u'valueChanged(int)'), self.onFontMainXSpinBoxChanged) + QtCore.QObject.connect(self.FontMainYSpinBox, + QtCore.SIGNAL(u'valueChanged(int)'), self.onFontMainYSpinBoxChanged) + QtCore.QObject.connect(self.FontMainWidthSpinBox, + QtCore.SIGNAL(u'valueChanged(int)'), + self.onFontMainWidthSpinBoxChanged) + QtCore.QObject.connect(self.FontMainHeightSpinBox, + QtCore.SIGNAL(u'valueChanged(int)'), + self.onFontMainHeightSpinBoxChanged) + QtCore.QObject.connect(self.FontMainLineAdjustmentSpinBox, + QtCore.SIGNAL(u'valueChanged(int)'), + self.onFontMainLineAdjustmentSpinBoxChanged) + QtCore.QObject.connect(self.FontMainLineSpacingSpinBox, + QtCore.SIGNAL(u'valueChanged(int)'), + self.onFontMainLineSpacingSpinBoxChanged) + QtCore.QObject.connect(self.FontFooterXSpinBox, + QtCore.SIGNAL(u'valueChanged(int)'), + self.onFontFooterXSpinBoxChanged) + QtCore.QObject.connect(self.FontFooterYSpinBox, + QtCore.SIGNAL(u'valueChanged(int)'), + self.onFontFooterYSpinBoxChanged) + QtCore.QObject.connect(self.FontFooterWidthSpinBox, + QtCore.SIGNAL(u'valueChanged(int)'), + self.onFontFooterWidthSpinBoxChanged) + QtCore.QObject.connect(self.FontFooterHeightSpinBox, + QtCore.SIGNAL(u'valueChanged(int)'), + self.onFontFooterHeightSpinBoxChanged) + QtCore.QObject.connect(self.ShadowSpinBox, + QtCore.SIGNAL(u'valueChanged(int)'), + self.onShadowSpinBoxChanged) + QtCore.QObject.connect(self.ShadowCheckBox, + QtCore.SIGNAL(u'valueChanged(int)'), self.onShadowCheckBoxChanged) + QtCore.QObject.connect(self.OutlineSpinBox, + QtCore.SIGNAL(u'valueChanged(int)'), + self.onOutlineSpinBoxChanged) + # Checkboxes QtCore.QObject.connect(self.FontMainDefaultCheckBox, QtCore.SIGNAL(u'stateChanged(int)'), self.onFontMainDefaultCheckBoxChanged) - QtCore.QObject.connect(self.FontMainXSpinBox, - QtCore.SIGNAL(u'editingFinished()'), self.onFontMainXSpinBoxChanged) - QtCore.QObject.connect(self.FontMainYSpinBox, - QtCore.SIGNAL(u'editingFinished()'), self.onFontMainYSpinBoxChanged) - QtCore.QObject.connect(self.FontMainWidthSpinBox, - QtCore.SIGNAL(u'editingFinished()'), - self.onFontMainWidthSpinBoxChanged) - QtCore.QObject.connect(self.FontMainHeightSpinBox, - QtCore.SIGNAL(u'editingFinished()'), - self.onFontMainHeightSpinBoxChanged) - QtCore.QObject.connect(self.FontMainLineAdjustmentSpinBox, - QtCore.SIGNAL(u'editingFinished()'), - self.onFontMainLineAdjustmentSpinBoxChanged) - QtCore.QObject.connect(self.FontMainLineSpacingSpinBox, - QtCore.SIGNAL(u'editingFinished()'), - self.onFontMainLineSpacingSpinBoxChanged) QtCore.QObject.connect(self.FontFooterDefaultCheckBox, QtCore.SIGNAL(u'stateChanged(int)'), self.onFontFooterDefaultCheckBoxChanged) - QtCore.QObject.connect(self.FontFooterXSpinBox, - QtCore.SIGNAL(u'editingFinished()'), - self.onFontFooterXSpinBoxChanged) - QtCore.QObject.connect(self.FontFooterYSpinBox, - QtCore.SIGNAL(u'editingFinished()'), - self.onFontFooterYSpinBoxChanged) - QtCore.QObject.connect(self.FontFooterWidthSpinBox, - QtCore.SIGNAL(u'editingFinished()'), - self.onFontFooterWidthSpinBoxChanged) - QtCore.QObject.connect(self.FontFooterHeightSpinBox, - QtCore.SIGNAL(u'editingFinished()'), - self.onFontFooterHeightSpinBoxChanged) QtCore.QObject.connect(self.OutlineCheckBox, QtCore.SIGNAL(u'stateChanged(int)'), self.onOutlineCheckBoxChanged) - QtCore.QObject.connect(self.ShadowSpinBox, - QtCore.SIGNAL(u'editingFinished()'), - self.onShadowSpinBoxChanged) - QtCore.QObject.connect(self.ShadowCheckBox, - QtCore.SIGNAL(u'stateChanged(int)'), self.onShadowCheckBoxChanged) - QtCore.QObject.connect(self.OutlineSpinBox, - QtCore.SIGNAL(u'editingFinished()'), - self.onOutlineSpinBoxChanged) QtCore.QObject.connect(self.SlideTransitionCheckedBox, QtCore.SIGNAL(u'stateChanged(int)'), self.onSlideTransitionCheckedBoxChanged) diff --git a/openlp/core/ui/displaytab.py b/openlp/core/ui/displaytab.py index 8a028bbc8..0fb16a9f7 100644 --- a/openlp/core/ui/displaytab.py +++ b/openlp/core/ui/displaytab.py @@ -242,4 +242,3 @@ class DisplayTab(SettingsTab): if self.amend_display_start != self.amend_display: self.amend_display_start = self.amend_display Receiver.send_message(u'config_screen_changed') - diff --git a/openlp/core/ui/generaltab.py b/openlp/core/ui/generaltab.py index 4c42bf90c..340753707 100644 --- a/openlp/core/ui/generaltab.py +++ b/openlp/core/ui/generaltab.py @@ -32,13 +32,16 @@ class GeneralTab(SettingsTab): GeneralTab is the general settings tab in the settings dialog. """ def __init__(self, screens): + """ + Initialise the general settings tab + """ self.screens = screens + self.MonitorNumber = 0 SettingsTab.__init__(self, u'General') def preLoad(self): """ - Set up the display screen and set correct screen - values. + Set up the display screen and set correct screen values. If not set before default to last screen. """ settings = QtCore.QSettings() @@ -47,12 +50,14 @@ class GeneralTab(SettingsTab): QtCore.QVariant(self.screens.display_count - 1)).toInt()[0] self.screens.set_current_display(self.MonitorNumber) self.screens.monitor_number = self.MonitorNumber - self.DisplayOnMonitor = settings.value( + self.screens.display = settings.value( u'display on monitor', QtCore.QVariant(True)).toBool() - self.screens.display = self.DisplayOnMonitor settings.endGroup() def setupUi(self): + """ + Create the user interface for the general settings tab + """ self.setObjectName(u'GeneralTab') self.tabTitleVisible = translate('GeneralTab', 'General') self.GeneralLayout = QtGui.QHBoxLayout(self) @@ -152,31 +157,11 @@ class GeneralTab(SettingsTab): QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) self.GeneralRightLayout.addItem(self.GeneralRightSpacer) self.GeneralLayout.addWidget(self.GeneralRightWidget) - QtCore.QObject.connect(self.MonitorComboBox, - QtCore.SIGNAL(u'activated(int)'), self.onMonitorComboBoxChanged) - QtCore.QObject.connect(self.DisplayOnMonitorCheck, - QtCore.SIGNAL(u'stateChanged(int)'), - self.onDisplayOnMonitorCheckChanged) - QtCore.QObject.connect(self.WarningCheckBox, - QtCore.SIGNAL(u'stateChanged(int)'), self.onWarningCheckBoxChanged) - QtCore.QObject.connect(self.AutoOpenCheckBox, - QtCore.SIGNAL(u'stateChanged(int)'), self.onAutoOpenCheckBoxChanged) - QtCore.QObject.connect(self.ShowSplashCheckBox, - QtCore.SIGNAL(u'stateChanged(int)'), - self.onShowSplashCheckBoxChanged) - QtCore.QObject.connect(self.SaveCheckServiceCheckBox, - QtCore.SIGNAL(u'stateChanged(int)'), - self.onSaveCheckServiceCheckBox) - QtCore.QObject.connect(self.AutoPreviewCheckBox, - QtCore.SIGNAL(u'stateChanged(int)'), self.onAutoPreviewCheckBox) - QtCore.QObject.connect(self.NumberEdit, - QtCore.SIGNAL(u'editingFinished()'), self.onNumberEditLostFocus) - QtCore.QObject.connect(self.UsernameEdit, - QtCore.SIGNAL(u'editingFinished()'), self.onUsernameEditLostFocus) - QtCore.QObject.connect(self.PasswordEdit, - QtCore.SIGNAL(u'editingFinished()'), self.onPasswordEditLostFocus) def retranslateUi(self): + """ + Translate the general settings tab to the currently selected language + """ self.MonitorGroupBox.setTitle(translate('GeneralTab', 'Monitors')) self.MonitorLabel.setText( translate('GeneralTab', 'Select monitor for output display:')) @@ -204,37 +189,10 @@ class GeneralTab(SettingsTab): self.PasswordLabel.setText( translate('GeneralTab', 'SongSelect Password:')) - def onMonitorComboBoxChanged(self): - self.MonitorNumber = self.MonitorComboBox.currentIndex() - - def onDisplayOnMonitorCheckChanged(self, value): - self.DisplayOnMonitor = (value == QtCore.Qt.Checked) - - def onAutoOpenCheckBoxChanged(self, value): - self.AutoOpen = (value == QtCore.Qt.Checked) - - def onShowSplashCheckBoxChanged(self, value): - self.ShowSplash = (value == QtCore.Qt.Checked) - - def onWarningCheckBoxChanged(self, value): - self.Warning = (value == QtCore.Qt.Checked) - - def onSaveCheckServiceCheckBox(self, value): - self.PromptSaveService = (value == QtCore.Qt.Checked) - - def onAutoPreviewCheckBox(self, value): - self.AutoPreview = (value == QtCore.Qt.Checked) - - def onNumberEditLostFocus(self): - self.CCLINumber = self.NumberEdit.displayText() - - def onUsernameEditLostFocus(self): - self.Username = self.UsernameEdit.displayText() - - def onPasswordEditLostFocus(self): - self.Password = self.PasswordEdit.displayText() - def load(self): + """ + Load the settings to populate the form + """ settings = QtCore.QSettings() settings.beginGroup(self.settingsSection) for screen in self.screens.screen_list: @@ -244,55 +202,54 @@ class GeneralTab(SettingsTab): screen_name = u'%s (%s)' % (screen_name, translate('GeneralTab', 'primary')) self.MonitorComboBox.addItem(screen_name) - # Get the configs - self.Warning = settings.value( - u'blank warning', QtCore.QVariant(False)).toBool() - self.AutoOpen = settings.value( - u'auto open', QtCore.QVariant(False)).toBool() - self.ShowSplash = settings.value( - u'show splash', QtCore.QVariant(True)).toBool() - self.PromptSaveService = settings.value( - u'save prompt', QtCore.QVariant(False)).toBool() - self.AutoPreview = settings.value( - u'auto preview', QtCore.QVariant(False)).toBool() - self.CCLINumber = unicode(settings.value( - u'ccli number', QtCore.QVariant(u'')).toString()) - self.Username = unicode(settings.value( - u'songselect username', QtCore.QVariant(u'')).toString()) - self.Password = unicode(settings.value( - u'songselect password', QtCore.QVariant(u'')).toString()) - settings.endGroup() - self.SaveCheckServiceCheckBox.setChecked(self.PromptSaveService) - # Set a few things up + self.NumberEdit.setText(unicode(settings.value( + u'ccli number', QtCore.QVariant(u'')).toString())) + self.UsernameEdit.setText(unicode(settings.value( + u'songselect username', QtCore.QVariant(u'')).toString())) + self.PasswordEdit.setText(unicode(settings.value( + u'songselect password', QtCore.QVariant(u'')).toString())) + self.SaveCheckServiceCheckBox.setChecked(settings.value(u'save prompt', + QtCore.QVariant(False)).toBool()) self.MonitorComboBox.setCurrentIndex(self.MonitorNumber) - self.DisplayOnMonitorCheck.setChecked(self.DisplayOnMonitor) - self.WarningCheckBox.setChecked(self.Warning) - self.AutoOpenCheckBox.setChecked(self.AutoOpen) - self.ShowSplashCheckBox.setChecked(self.ShowSplash) - self.AutoPreviewCheckBox.setChecked(self.AutoPreview) - self.NumberEdit.setText(self.CCLINumber) - self.UsernameEdit.setText(self.Username) - self.PasswordEdit.setText(self.Password) + self.DisplayOnMonitorCheck.setChecked(self.screens.display) + self.WarningCheckBox.setChecked(settings.value(u'blank warning', + QtCore.QVariant(False)).toBool()) + self.AutoOpenCheckBox.setChecked(settings.value(u'auto open', + QtCore.QVariant(False)).toBool()) + self.ShowSplashCheckBox.setChecked(settings.value(u'show splash', + QtCore.QVariant(True)).toBool()) + self.AutoPreviewCheckBox.setChecked(settings.value(u'auto preview', + QtCore.QVariant(False)).toBool()) + settings.endGroup() def save(self): + """ + Save the settings from the form + """ + self.MonitorNumber = self.MonitorComboBox.currentIndex() settings = QtCore.QSettings() settings.beginGroup(self.settingsSection) settings.setValue(u'monitor', QtCore.QVariant(self.MonitorNumber)) settings.setValue(u'display on monitor', - QtCore.QVariant(self.DisplayOnMonitor)) - settings.setValue(u'blank warning', QtCore.QVariant(self.Warning)) - settings.setValue(u'auto open', QtCore.QVariant(self.AutoOpen)) - settings.setValue(u'show splash', QtCore.QVariant(self.ShowSplash)) + QtCore.QVariant(self.DisplayOnMonitorCheck.isChecked())) + settings.setValue(u'blank warning', + QtCore.QVariant(self.WarningCheckBox.isChecked())) + settings.setValue(u'auto open', + QtCore.QVariant(self.AutoOpenCheckBox.isChecked())) + settings.setValue(u'show splash', + QtCore.QVariant(self.ShowSplashCheckBox.isChecked())) settings.setValue(u'save prompt', - QtCore.QVariant(self.PromptSaveService)) - settings.setValue(u'auto preview', QtCore.QVariant(self.AutoPreview)) - settings.setValue(u'ccli number', QtCore.QVariant(self.CCLINumber)) + QtCore.QVariant(self.SaveCheckServiceCheckBox.isChecked())) + settings.setValue(u'auto preview', + QtCore.QVariant(self.AutoPreviewCheckBox.isChecked())) + settings.setValue(u'ccli number', + QtCore.QVariant(self.NumberEdit.displayText())) settings.setValue(u'songselect username', - QtCore.QVariant(self.Username)) + QtCore.QVariant(self.UsernameEdit.displayText())) settings.setValue(u'songselect password', - QtCore.QVariant(self.Password)) + QtCore.QVariant(self.PasswordEdit.displayText())) settings.endGroup() - self.screens.display = self.DisplayOnMonitor + self.screens.display = self.DisplayOnMonitorCheck.isChecked() #Monitor Number has changed. if self.screens.monitor_number != self.MonitorNumber: self.screens.monitor_number = self.MonitorNumber From f67457c3785bd3e809b23bcc1dcb576cd94b016a Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Thu, 1 Jul 2010 20:34:48 +0100 Subject: [PATCH 47/49] Revert bug fix --- openlp/core/ui/amendthemeform.py | 85 ++++++++++++++++---------------- 1 file changed, 42 insertions(+), 43 deletions(-) diff --git a/openlp/core/ui/amendthemeform.py b/openlp/core/ui/amendthemeform.py index 6333d7146..c85eff4b8 100644 --- a/openlp/core/ui/amendthemeform.py +++ b/openlp/core/ui/amendthemeform.py @@ -43,8 +43,8 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog): self.path = None self.theme = ThemeXML() self.setupUi(self) - # Define signals - # Buttons + #define signals + #Buttons QtCore.QObject.connect(self.Color1PushButton, QtCore.SIGNAL(u'pressed()'), self.onColor1PushButtonClicked) QtCore.QObject.connect(self.Color2PushButton, @@ -60,7 +60,7 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog): QtCore.SIGNAL(u'pressed()'), self.onShadowColorPushButtonClicked) QtCore.QObject.connect(self.ImageToolButton, QtCore.SIGNAL(u'pressed()'), self.onImageToolButtonClicked) - # Combo boxes + #Combo boxes QtCore.QObject.connect(self.BackgroundComboBox, QtCore.SIGNAL(u'activated(int)'), self.onBackgroundComboBoxSelected) QtCore.QObject.connect(self.BackgroundTypeComboBox, @@ -82,58 +82,57 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog): QtCore.SIGNAL(u'activated(int)'), self.onHorizontalComboBoxSelected) QtCore.QObject.connect(self.VerticalComboBox, QtCore.SIGNAL(u'activated(int)'), self.onVerticalComboBoxSelected) - # Spin boxes + #Spin boxes QtCore.QObject.connect(self.FontMainSizeSpinBox, - QtCore.SIGNAL(u'valueChanged(int)'), + QtCore.SIGNAL(u'editingFinished()'), self.onFontMainSizeSpinBoxChanged) QtCore.QObject.connect(self.FontFooterSizeSpinBox, - QtCore.SIGNAL(u'valueChanged(int)'), + QtCore.SIGNAL(u'editingFinished()'), self.onFontFooterSizeSpinBoxChanged) - QtCore.QObject.connect(self.FontMainXSpinBox, - QtCore.SIGNAL(u'valueChanged(int)'), self.onFontMainXSpinBoxChanged) - QtCore.QObject.connect(self.FontMainYSpinBox, - QtCore.SIGNAL(u'valueChanged(int)'), self.onFontMainYSpinBoxChanged) - QtCore.QObject.connect(self.FontMainWidthSpinBox, - QtCore.SIGNAL(u'valueChanged(int)'), - self.onFontMainWidthSpinBoxChanged) - QtCore.QObject.connect(self.FontMainHeightSpinBox, - QtCore.SIGNAL(u'valueChanged(int)'), - self.onFontMainHeightSpinBoxChanged) - QtCore.QObject.connect(self.FontMainLineAdjustmentSpinBox, - QtCore.SIGNAL(u'valueChanged(int)'), - self.onFontMainLineAdjustmentSpinBoxChanged) - QtCore.QObject.connect(self.FontMainLineSpacingSpinBox, - QtCore.SIGNAL(u'valueChanged(int)'), - self.onFontMainLineSpacingSpinBoxChanged) - QtCore.QObject.connect(self.FontFooterXSpinBox, - QtCore.SIGNAL(u'valueChanged(int)'), - self.onFontFooterXSpinBoxChanged) - QtCore.QObject.connect(self.FontFooterYSpinBox, - QtCore.SIGNAL(u'valueChanged(int)'), - self.onFontFooterYSpinBoxChanged) - QtCore.QObject.connect(self.FontFooterWidthSpinBox, - QtCore.SIGNAL(u'valueChanged(int)'), - self.onFontFooterWidthSpinBoxChanged) - QtCore.QObject.connect(self.FontFooterHeightSpinBox, - QtCore.SIGNAL(u'valueChanged(int)'), - self.onFontFooterHeightSpinBoxChanged) - QtCore.QObject.connect(self.ShadowSpinBox, - QtCore.SIGNAL(u'valueChanged(int)'), - self.onShadowSpinBoxChanged) - QtCore.QObject.connect(self.ShadowCheckBox, - QtCore.SIGNAL(u'valueChanged(int)'), self.onShadowCheckBoxChanged) - QtCore.QObject.connect(self.OutlineSpinBox, - QtCore.SIGNAL(u'valueChanged(int)'), - self.onOutlineSpinBoxChanged) - # Checkboxes QtCore.QObject.connect(self.FontMainDefaultCheckBox, QtCore.SIGNAL(u'stateChanged(int)'), self.onFontMainDefaultCheckBoxChanged) + QtCore.QObject.connect(self.FontMainXSpinBox, + QtCore.SIGNAL(u'editingFinished()'), self.onFontMainXSpinBoxChanged) + QtCore.QObject.connect(self.FontMainYSpinBox, + QtCore.SIGNAL(u'editingFinished()'), self.onFontMainYSpinBoxChanged) + QtCore.QObject.connect(self.FontMainWidthSpinBox, + QtCore.SIGNAL(u'editingFinished()'), + self.onFontMainWidthSpinBoxChanged) + QtCore.QObject.connect(self.FontMainHeightSpinBox, + QtCore.SIGNAL(u'editingFinished()'), + self.onFontMainHeightSpinBoxChanged) + QtCore.QObject.connect(self.FontMainLineAdjustmentSpinBox, + QtCore.SIGNAL(u'editingFinished()'), + self.onFontMainLineAdjustmentSpinBoxChanged) + QtCore.QObject.connect(self.FontMainLineSpacingSpinBox, + QtCore.SIGNAL(u'editingFinished()'), + self.onFontMainLineSpacingSpinBoxChanged) QtCore.QObject.connect(self.FontFooterDefaultCheckBox, QtCore.SIGNAL(u'stateChanged(int)'), self.onFontFooterDefaultCheckBoxChanged) + QtCore.QObject.connect(self.FontFooterXSpinBox, + QtCore.SIGNAL(u'editingFinished()'), + self.onFontFooterXSpinBoxChanged) + QtCore.QObject.connect(self.FontFooterYSpinBox, + QtCore.SIGNAL(u'editingFinished()'), + self.onFontFooterYSpinBoxChanged) + QtCore.QObject.connect(self.FontFooterWidthSpinBox, + QtCore.SIGNAL(u'editingFinished()'), + self.onFontFooterWidthSpinBoxChanged) + QtCore.QObject.connect(self.FontFooterHeightSpinBox, + QtCore.SIGNAL(u'editingFinished()'), + self.onFontFooterHeightSpinBoxChanged) QtCore.QObject.connect(self.OutlineCheckBox, QtCore.SIGNAL(u'stateChanged(int)'), self.onOutlineCheckBoxChanged) + QtCore.QObject.connect(self.ShadowSpinBox, + QtCore.SIGNAL(u'editingFinished()'), + self.onShadowSpinBoxChanged) + QtCore.QObject.connect(self.ShadowCheckBox, + QtCore.SIGNAL(u'stateChanged(int)'), self.onShadowCheckBoxChanged) + QtCore.QObject.connect(self.OutlineSpinBox, + QtCore.SIGNAL(u'editingFinished()'), + self.onOutlineSpinBoxChanged) QtCore.QObject.connect(self.SlideTransitionCheckedBox, QtCore.SIGNAL(u'stateChanged(int)'), self.onSlideTransitionCheckedBoxChanged) From 9e1474e851bee30888410a5c91768b4410d28c3e Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Fri, 2 Jul 2010 11:29:36 +0100 Subject: [PATCH 48/49] Fix songs and wildcard import --- openlp/plugins/presentations/lib/pptviewcontroller.py | 2 +- openlp/plugins/songs/lib/mediaitem.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/openlp/plugins/presentations/lib/pptviewcontroller.py b/openlp/plugins/presentations/lib/pptviewcontroller.py index 10ab41fd0..e8f0d9390 100644 --- a/openlp/plugins/presentations/lib/pptviewcontroller.py +++ b/openlp/plugins/presentations/lib/pptviewcontroller.py @@ -27,7 +27,7 @@ import os import logging if os.name == u'nt': - from ctypes import * + from ctypes import cdll from ctypes.wintypes import RECT from presentationcontroller import PresentationController, PresentationDocument diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index 7ed30e5e0..c3aef65fd 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -371,7 +371,8 @@ class SongMediaItem(MediaManagerItem): author_list = author_list + unicode(author.display_name) author_audit.append(unicode(author.display_name)) if song.ccli_number is None or len(song.ccli_number) == 0: - ccli = self.parent.settings_form.GeneralTab.CCLINumber + ccli = QtCore.QSettings().value(u'general/ccli number', + QtCore.QVariant(u'')).toString() else: ccli = unicode(song.ccli_number) raw_footer.append(song.title) From 45375e74422522c82d546dd130f22a21760bfda6 Mon Sep 17 00:00:00 2001 From: Jon Tibble Date: Fri, 2 Jul 2010 13:13:46 +0100 Subject: [PATCH 49/49] Cleanup plugins (Bug #600996) --- openlp/core/lib/plugin.py | 9 ++++++--- openlp/plugins/alerts/alertsplugin.py | 2 +- openlp/plugins/bibles/bibleplugin.py | 2 -- openlp/plugins/custom/customplugin.py | 9 --------- openlp/plugins/images/imageplugin.py | 9 --------- openlp/plugins/media/mediaplugin.py | 9 --------- openlp/plugins/presentations/presentationplugin.py | 2 +- openlp/plugins/remotes/remoteplugin.py | 2 +- openlp/plugins/songs/lib/mediaitem.py | 4 ++-- openlp/plugins/songs/songsplugin.py | 6 ------ 10 files changed, 11 insertions(+), 43 deletions(-) diff --git a/openlp/core/lib/plugin.py b/openlp/core/lib/plugin.py index a5d712dfb..1450ef1fe 100644 --- a/openlp/core/lib/plugin.py +++ b/openlp/core/lib/plugin.py @@ -242,19 +242,22 @@ class Plugin(QtCore.QObject): """ if self.media_item: self.media_item.initialise() + self.insert_toolbox_item() def finalise(self): """ Called by the plugin Manager to cleanup things. """ - pass + self.remove_toolbox_item() def remove_toolbox_item(self): """ Called by the plugin to remove toolbar """ - self.mediadock.remove_dock(self.name) - self.settings_form.removeTab(self.name) + if self.media_item: + self.mediadock.remove_dock(self.name) + if self.settings_tab: + self.settings_form.removeTab(self.name) def insert_toolbox_item(self): """ diff --git a/openlp/plugins/alerts/alertsplugin.py b/openlp/plugins/alerts/alertsplugin.py index 46d4e8cb7..57388c538 100644 --- a/openlp/plugins/alerts/alertsplugin.py +++ b/openlp/plugins/alerts/alertsplugin.py @@ -85,8 +85,8 @@ class alertsPlugin(Plugin): def finalise(self): log.info(u'Plugin Finalise') + Plugin.finalise(self) self.toolsAlertItem.setVisible(False) - #stop any events being processed def togglealertsState(self): self.alertsActive = not self.alertsActive diff --git a/openlp/plugins/bibles/bibleplugin.py b/openlp/plugins/bibles/bibleplugin.py index b891b14ad..9f4f034ab 100644 --- a/openlp/plugins/bibles/bibleplugin.py +++ b/openlp/plugins/bibles/bibleplugin.py @@ -48,14 +48,12 @@ class BiblePlugin(Plugin): if self.manager is None: self.manager = BibleManager(self) Plugin.initialise(self) - self.insert_toolbox_item() self.ImportBibleItem.setVisible(True) self.ExportBibleItem.setVisible(True) def finalise(self): log.info(u'Plugin Finalise') Plugin.finalise(self) - self.remove_toolbox_item() self.ImportBibleItem.setVisible(False) self.ExportBibleItem.setVisible(False) diff --git a/openlp/plugins/custom/customplugin.py b/openlp/plugins/custom/customplugin.py index e65205351..60a0b312c 100644 --- a/openlp/plugins/custom/customplugin.py +++ b/openlp/plugins/custom/customplugin.py @@ -60,15 +60,6 @@ class CustomPlugin(Plugin): # Create the CustomManagerItem object return CustomMediaItem(self, self.icon, self.name) - def initialise(self): - log.info(u'Plugin Initialising') - Plugin.initialise(self) - self.insert_toolbox_item() - - def finalise(self): - log.info(u'Plugin Finalise') - self.remove_toolbox_item() - def about(self): about_text = translate('CustomPlugin', 'Custom Plugin
This plugin ' diff --git a/openlp/plugins/images/imageplugin.py b/openlp/plugins/images/imageplugin.py index 9ebaa128f..be3863bda 100644 --- a/openlp/plugins/images/imageplugin.py +++ b/openlp/plugins/images/imageplugin.py @@ -39,15 +39,6 @@ class ImagePlugin(Plugin): self.icon = build_icon(u':/plugins/plugin_images.png') self.status = PluginStatus.Active - def initialise(self): - log.info(u'Plugin Initialising') - Plugin.initialise(self) - self.insert_toolbox_item() - - def finalise(self): - log.info(u'Plugin Finalise') - self.remove_toolbox_item() - def get_settings_tab(self): return ImageTab(self.name) diff --git a/openlp/plugins/media/mediaplugin.py b/openlp/plugins/media/mediaplugin.py index 33261f1e2..24138a0f5 100644 --- a/openlp/plugins/media/mediaplugin.py +++ b/openlp/plugins/media/mediaplugin.py @@ -67,15 +67,6 @@ class MediaPlugin(Plugin): type = u'' return list, type - def initialise(self): - log.info(u'Plugin Initialising') - Plugin.initialise(self) - self.insert_toolbox_item() - - def finalise(self): - log.info(u'Plugin Finalise') - self.remove_toolbox_item() - def get_media_manager_item(self): # Create the MediaManagerItem object return MediaMediaItem(self, self.icon, self.name) diff --git a/openlp/plugins/presentations/presentationplugin.py b/openlp/plugins/presentations/presentationplugin.py index d92483b88..22c7c554e 100644 --- a/openlp/plugins/presentations/presentationplugin.py +++ b/openlp/plugins/presentations/presentationplugin.py @@ -64,7 +64,7 @@ class PresentationPlugin(Plugin): controller = self.controllers[key] if controller.enabled: controller.kill() - self.remove_toolbox_item() + Plugin.finalise(self) def get_media_manager_item(self): """ diff --git a/openlp/plugins/remotes/remoteplugin.py b/openlp/plugins/remotes/remoteplugin.py index fad7ecbe8..808714fb3 100644 --- a/openlp/plugins/remotes/remoteplugin.py +++ b/openlp/plugins/remotes/remoteplugin.py @@ -56,7 +56,7 @@ class RemotesPlugin(Plugin): Tidy up and close down the http server """ log.debug(u'finalise') - self.remove_toolbox_item() + Plugin.finalise(self) if self.server: self.server.close() diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index c3aef65fd..4557f53fa 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -166,13 +166,13 @@ class SongMediaItem(MediaManagerItem): if search_type == 0: log.debug(u'Titles Search') search_results = self.parent.manager.get_all_objects_filtered(Song, - Song.search_title.like(u'%' + keywords + u'%'), + Song.search_title.like(u'%' + search_keywords + u'%'), Song.search_title.asc()) self.displayResultsSong(search_results) elif search_type == 1: log.debug(u'Lyrics Search') search_results = self.parent.manager.get_all_objects_filtered(Song, - Song.search_lyrics.like(u'%' + keywords + u'%'), + Song.search_lyrics.like(u'%' + search_keywords + u'%'), Song.search_lyrics.asc()) self.displayResultsSong(search_results) elif search_type == 2: diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py index e2740748b..d9f9bb95f 100644 --- a/openlp/plugins/songs/songsplugin.py +++ b/openlp/plugins/songs/songsplugin.py @@ -67,15 +67,9 @@ class SongsPlugin(Plugin): def initialise(self): log.info(u'Songs Initialising') Plugin.initialise(self) - self.insert_toolbox_item() self.media_item.displayResultsSong( self.manager.get_all_objects(Song, Song.title)) - def finalise(self): - log.info(u'Plugin Finalise') - Plugin.finalise(self) - self.remove_toolbox_item() - def get_media_manager_item(self): """ Create the MediaManagerItem object, which is displaed in the