diff --git a/copyright.txt b/copyright.txt index a78b7d0d7..1a348a0df 100644 --- a/copyright.txt +++ b/copyright.txt @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/plugins/plugin.txt b/documentation/plugin.txt similarity index 100% rename from openlp/plugins/plugin.txt rename to documentation/plugin.txt diff --git a/documentation/pyqt-sql-py2exe.txt b/documentation/pyqt-sql-py2exe.txt deleted file mode 100644 index 33de23b6e..000000000 --- a/documentation/pyqt-sql-py2exe.txt +++ /dev/null @@ -1,58 +0,0 @@ -This content can be found at this URL: -http://netsuperbrain.com/Postmodern%20PostgreSQL%20Application%20Development.pdf - -Page 11-15: QtDesigner -Page 18-20: SQLAlchemy -Page 21-23: PyQt - widget -Page 24 : main -Page 28 : py2exe and release - - -============================== -This is the destilled content. -============================== - ----------------- -** sqlalchemy ** ----------------- -from sqlalchemy import create_engine, MetaData, Table -from sqlalchemy.orm import sessionmaker, mapper -engine = create_engine( 'postgres://postgres@localhost/customers' ) -metadata = MetaData( bind=engine, reflect=True) -Session = sessionmaker(bind=engine, autoflush=True, - transactional=True) - -class Customer(object): pass -mapper( Customer, Table('customers', metadata ) ) - -session = Session() -customer = Customer( businessName=“Jamb Safety”, - website=“www.jamb.com” ) -session.save( customer ) -for customer in Session.query(Customer).filter( - Customer.businessName.like(“Jamb%”)): - print customer.businessName -session.commit() - ------------------------- -** release and py2exe ** ------------------------- - -from distutils.core import setup -import py2exe -import glob -setup( - name="Customers", - author="Sankel Software", - author_email="david@sankelsoftware.com", - url="http://sankelsoftware.com", - license=“GPL", - version=“1.0.0", - windows=[ { "script":"main.py“,}], - options={"py2exe":{"includes":["sip”]}}, - data_files=[ - ("forms",glob.glob("forms/*.ui")), - ] ) - -release: -python setup.py py2exe --quiet --dist-dir=dist diff --git a/openlp.pyw b/openlp.pyw index c4a5fb428..528923862 100755 --- a/openlp.pyw +++ b/openlp.pyw @@ -7,8 +7,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -34,7 +34,6 @@ from PyQt4 import QtCore, QtGui log = logging.getLogger() -import openlp from openlp.core.lib import Receiver, str_to_bool from openlp.core.resources import qInitResources from openlp.core.ui import MainWindow, SplashScreen, ScreenList @@ -79,9 +78,7 @@ class OpenLP(QtGui.QApplication): Run the OpenLP application. """ #Load and store current Application Version - filepath = AppLocation.get_directory(AppLocation.AppDir) - if not hasattr(sys, u'frozen'): - filepath = os.path.join(filepath, u'openlp') + filepath = AppLocation.get_directory(AppLocation.VersionDir) filepath = os.path.join(filepath, u'.version') fversion = None try: @@ -93,16 +90,23 @@ class OpenLP(QtGui.QApplication): app_version = { u'full': full_version, u'version': bits[0], - u'build': bits[1] + u'build': bits[1] if len(bits) > 1 else None } - log.info(u'Openlp version %s build %s' % ( - app_version[u'version'], app_version[u'build'])) + if app_version[u'build']: + log.info( + u'Openlp version %s build %s', + app_version[u'version'], + app_version[u'build'] + ) + else: + log.info(u'Openlp version %s' % app_version[u'version']) except: - app_version = { - u'full': u'1.9.0-bzr000', - u'version': u'1.9.0', - u'build': u'bzr000' - } + log.exception('Error in version file.') + app_version = { + u'full': u'1.9.0-bzr000', + u'version': u'1.9.0', + u'build': u'bzr000' + } finally: if fversion: fversion.close() diff --git a/openlp/.version b/openlp/.version index 4489023a7..f8e233b27 100644 --- a/openlp/.version +++ b/openlp/.version @@ -1 +1 @@ -1.9.0-bzr722 +1.9.0 diff --git a/openlp/__init__.py b/openlp/__init__.py index bc50edda3..1a348a0df 100644 --- a/openlp/__init__.py +++ b/openlp/__init__.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -21,4 +21,4 @@ # 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 # -############################################################################### \ No newline at end of file +############################################################################### diff --git a/openlp/core/__init__.py b/openlp/core/__init__.py index bc50edda3..1a348a0df 100644 --- a/openlp/core/__init__.py +++ b/openlp/core/__init__.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -21,4 +21,4 @@ # 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 # -############################################################################### \ No newline at end of file +############################################################################### diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py index 899b5cf73..38bcd127c 100644 --- a/openlp/core/lib/__init__.py +++ b/openlp/core/lib/__init__.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -144,8 +144,9 @@ def resize_image(image, width, height): The image to resize. """ preview = QtGui.QImage(image) - preview = preview.scaled(width, height, QtCore.Qt.KeepAspectRatio, - QtCore.Qt.SmoothTransformation) + if not preview.isNull(): + preview = preview.scaled(width, height, QtCore.Qt.KeepAspectRatio, + QtCore.Qt.SmoothTransformation) realw = preview.width() realh = preview.height() # and move it to the centre of the preview space @@ -171,7 +172,7 @@ from mediamanageritem import MediaManagerItem from xmlrootclass import XmlRootClass from serviceitem import ServiceItem from serviceitem import ServiceItemType -from serviceitem import ServiceItem +from serviceitem import ItemCapabilities from toolbar import OpenLPToolbar from dockwidget import OpenLPDockWidget from songxmlhandler import SongXMLBuilder, SongXMLParser diff --git a/openlp/core/lib/baselistwithdnd.py b/openlp/core/lib/baselistwithdnd.py index f7095550a..bc043082c 100644 --- a/openlp/core/lib/baselistwithdnd.py +++ b/openlp/core/lib/baselistwithdnd.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/core/lib/dockwidget.py b/openlp/core/lib/dockwidget.py index ce8302b43..fcee02af8 100644 --- a/openlp/core/lib/dockwidget.py +++ b/openlp/core/lib/dockwidget.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/core/lib/eventreceiver.py b/openlp/core/lib/eventreceiver.py index be7dff67a..2e1cf9d39 100644 --- a/openlp/core/lib/eventreceiver.py +++ b/openlp/core/lib/eventreceiver.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -109,6 +109,15 @@ class EventReceiver(QtCore.QObject): ``presentation types`` Informs all components of the presentation types supported. + ``blank_check`` + Check to see if th eblank display message is required + + ``version_check`` + Version has changed so pop up window. + + ``mainDisplay_active`` + Version has changed so pop up window. + """ def __init__(self): """ diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py index fd6d37ca6..7ac2a6f0a 100644 --- a/openlp/core/lib/mediamanageritem.py +++ b/openlp/core/lib/mediamanageritem.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -114,6 +114,8 @@ class MediaManagerItem(QtGui.QWidget): self.Toolbar = None self.remoteTriggered = None self.ServiceItemIconName = None + self.singleServiceItem = True + self.addToServiceItem = False self.PageLayout = QtGui.QVBoxLayout(self) self.PageLayout.setSpacing(0) self.PageLayout.setContentsMargins(4, 0, 4, 0) @@ -131,6 +133,7 @@ class MediaManagerItem(QtGui.QWidget): It provides a default set and the plugin is able to override the if required. """ + self.hasImportIcon = False self.hasNewIcon = True self.hasEditIcon = True self.hasFileIcon = False @@ -207,48 +210,54 @@ class MediaManagerItem(QtGui.QWidget): def addMiddleHeaderBar(self): # Create buttons for the toolbar + ## Import Button ## + if self.hasImportIcon: + self.addToolbarButton( + u'Import %s' % self.PluginNameShort, + u'%s %s' % (self.trUtf8('Import a'), self.PluginNameVisible), + u':/general/general_import.png', self.onImportClick) ## File Button ## if self.hasFileIcon: self.addToolbarButton( u'Load %s' % self.PluginNameShort, u'%s %s' % (self.trUtf8('Load a new'), self.PluginNameVisible), - u':/%s_load.png' % self.IconPath, self.onFileClick) + u':/general/general_open.png', self.onFileClick) ## New Button ## if self.hasNewIcon: self.addToolbarButton( u'New %s' % self.PluginNameShort, u'%s %s' % (self.trUtf8('Add a new'), self.PluginNameVisible), - u':/%s_new.png' % self.IconPath, self.onNewClick) + u':/general/general_new.png', self.onNewClick) ## Edit Button ## if self.hasEditIcon: self.addToolbarButton( u'Edit %s' % self.PluginNameShort, u'%s %s' % (self.trUtf8('Edit the selected'), self.PluginNameVisible), - u':/%s_edit.png' % self.IconPath, self.onEditClick) + u':/general/general_edit.png', self.onEditClick) ## Delete Button ## if self.hasDeleteIcon: self.addToolbarButton( u'Delete %s' % self.PluginNameShort, self.trUtf8('Delete the selected item'), - u':/%s_delete.png' % self.IconPath, self.onDeleteClick) + u':/general/general_delete.png', self.onDeleteClick) ## Separator Line ## self.addToolbarSeparator() ## Preview ## self.addToolbarButton( u'Preview %s' % self.PluginNameShort, self.trUtf8('Preview the selected item'), - u':/system/system_preview.png', self.onPreviewClick) + u':/general/general_preview.png', self.onPreviewClick) ## Live Button ## self.addToolbarButton( u'Go Live', self.trUtf8('Send the selected item live'), - u':/system/system_live.png', self.onLiveClick) + u':/general/general_live.png', self.onLiveClick) ## Add to service Button ## self.addToolbarButton( u'Add %s to Service' % self.PluginNameShort, self.trUtf8('Add the selected item(s) to the service'), - u':/system/system_add.png', self.onAddClick) + u':/general/general_add.png', self.onAddClick) def addListViewToToolBar(self): #Add the List widget @@ -268,23 +277,36 @@ class MediaManagerItem(QtGui.QWidget): if self.hasEditIcon: self.ListView.addAction( contextMenuAction( - self.ListView, u':/%s_new.png' % self.IconPath, + self.ListView, u':/general/general_edit.png', u'%s %s' % (self.trUtf8('&Edit'), self.PluginNameVisible), self.onEditClick)) self.ListView.addAction(contextMenuSeparator(self.ListView)) + if self.hasDeleteIcon: + self.ListView.addAction( + contextMenuAction( + self.ListView, u':/general/general_delete.png', + u'%s %s' % (self.trUtf8('&Delete'), self.PluginNameVisible), + self.onDeleteClick)) + self.ListView.addAction(contextMenuSeparator(self.ListView)) self.ListView.addAction( contextMenuAction( - self.ListView, u':/system/system_preview.png', + self.ListView, u':/general/general_preview.png', u'%s %s' % (self.trUtf8('&Preview'), self.PluginNameVisible), self.onPreviewClick)) self.ListView.addAction( contextMenuAction( - self.ListView, u':/system/system_live.png', + self.ListView, u':/general/general_live.png', self.trUtf8('&Show Live'), self.onLiveClick)) self.ListView.addAction( contextMenuAction( - self.ListView, u':/system/system_add.png', + self.ListView, u':/general/general_add.png', self.trUtf8('&Add to Service'), self.onAddClick)) + if self.addToServiceItem: + self.ListView.addAction( + contextMenuAction( + self.ListView, u':/general/general_add.png', + self.trUtf8('&Add to selected Service Item'), + self.onAddEditClick)) QtCore.QObject.connect( self.ListView, QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), self.onPreviewClick) @@ -313,7 +335,7 @@ class MediaManagerItem(QtGui.QWidget): files = QtGui.QFileDialog.getOpenFileNames( self, self.OnNewPrompt, self.parent.config.get_last_dir(), self.OnNewFileMasks) - log.info(u'New files(s)%s', unicode(files)) + log.info(u'New files(s) %s', unicode(files)) if files: self.loadList(files) dir, filename = os.path.split(unicode(files[0])) @@ -330,6 +352,24 @@ class MediaManagerItem(QtGui.QWidget): count += 1 return filelist + def validate(self, file, thumb): + """ + Validates to see if the file still exists or + thumbnail is up to date + """ + filedate = os.stat(file).st_mtime + thumbdate = os.stat(thumb).st_mtime + #if file updated rebuild icon + if filedate > thumbdate: + self.IconFromFile(file, thumb) + + def IconFromFile(self, file, thumb): + icon = build_icon(unicode(file)) + pixmap = icon.pixmap(QtCore.QSize(88,50)) + ext = os.path.splitext(thumb)[1].lower() + pixmap.save(thumb, ext[1:]) + return icon + def loadList(self, list): raise NotImplementedError(u'MediaManagerItem.loadList needs to be ' u'defined by the plugin') @@ -346,47 +386,79 @@ class MediaManagerItem(QtGui.QWidget): raise NotImplementedError(u'MediaManagerItem.onDeleteClick needs to ' u'be defined by the plugin') - def generateSlideData(self, item): + def generateSlideData(self, service_item, item): raise NotImplementedError(u'MediaManagerItem.generateSlideData needs ' u'to be defined by the plugin') def onPreviewClick(self): if not self.ListView.selectedIndexes() and not self.remoteTriggered: QtGui.QMessageBox.information(self, - self.trUtf8('No items selected...'), - self.trUtf8('You must select one or more items')) + self.trUtf8('No Items Selected'), + self.trUtf8('You must select one or more items.')) else: log.debug(self.PluginNameShort + u' Preview requested') service_item = self.buildServiceItem() if service_item: - service_item.fromPlugin = True + service_item.from_plugin = True self.parent.preview_controller.addServiceItem(service_item) def onLiveClick(self): if not self.ListView.selectedIndexes(): QtGui.QMessageBox.information(self, - self.trUtf8('No items selected...'), - self.trUtf8('You must select one or more items')) + self.trUtf8('No Items Selected'), + self.trUtf8('You must select one or more items.')) else: log.debug(self.PluginNameShort + u' Live requested') service_item = self.buildServiceItem() if service_item: - service_item.fromPlugin = True + service_item.from_plugin = True self.parent.live_controller.addServiceItem(service_item) def onAddClick(self): if not self.ListView.selectedIndexes() and not self.remoteTriggered: QtGui.QMessageBox.information(self, - self.trUtf8('No items selected...'), + self.trUtf8('No Items Selected'), + self.trUtf8('You must select one or more items.')) + else: + #Is it posssible to process multiple list items to generate multiple + #service items? + if self.singleServiceItem: + log.debug(self.PluginNameShort + u' Add requested') + service_item = self.buildServiceItem() + if service_item: + service_item.from_plugin = False + self.parent.service_manager.addServiceItem(service_item) + else: + items = self.ListView.selectedIndexes() + for item in items: + service_item = self.buildServiceItem(item) + if service_item: + service_item.from_plugin = False + self.parent.service_manager.addServiceItem(service_item) + + def onAddEditClick(self): + if not self.ListView.selectedIndexes() and not self.remoteTriggered: + QtGui.QMessageBox.information(self, + self.trUtf8('No items selected'), self.trUtf8('You must select one or more items')) else: log.debug(self.PluginNameShort + u' Add requested') - service_item = self.buildServiceItem() - if service_item: - service_item.fromPlugin = False + service_item = self.parent.service_manager.getServiceItem() + if not service_item: + QtGui.QMessageBox.information(self, + self.trUtf8('No Service Item Selected'), + self.trUtf8('You must select a existing service item to add to.')) + elif self.title.lower() == service_item.name.lower(): + self.generateSlideData(service_item) self.parent.service_manager.addServiceItem(service_item) + else: + #Turn off the remote edit update message indicator + self.parent.service_manager.remoteEditTriggered = False + QtGui.QMessageBox.information(self, + self.trUtf8('Invalid Service Item'), + self.trUtf8(unicode('You must select a %s service item.' % self.title))) - def buildServiceItem(self): + def buildServiceItem(self, item=None): """ Common method for generating a service item """ @@ -396,7 +468,7 @@ class MediaManagerItem(QtGui.QWidget): else: service_item.addIcon( u':/media/media_' + self.PluginNameShort.lower() + u'.png') - if self.generateSlideData(service_item): + if self.generateSlideData(service_item, item): return service_item else: - return None + return None \ No newline at end of file diff --git a/openlp/core/lib/plugin.py b/openlp/core/lib/plugin.py index e98c789d0..57dd984c3 100644 --- a/openlp/core/lib/plugin.py +++ b/openlp/core/lib/plugin.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/core/lib/pluginconfig.py b/openlp/core/lib/pluginconfig.py index 41b902bbc..e27b86669 100644 --- a/openlp/core/lib/pluginconfig.py +++ b/openlp/core/lib/pluginconfig.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -139,8 +139,9 @@ class PluginConfig(object): list = [] if list_count > 0: for counter in range(0, list_count): - item = unicode(self.get_config(u'%s %d' % (name, counter))) - list.append(item) + item = self.get_config(u'%s %d' % (name, counter)) + if item: + list.append(item) return list def set_list(self, name, list): @@ -190,4 +191,4 @@ class PluginConfig(object): name = u'last directory %d' % num else: name = u'last directory' - self.set_config(name, directory) \ No newline at end of file + self.set_config(name, directory) diff --git a/openlp/core/lib/pluginmanager.py b/openlp/core/lib/pluginmanager.py index 2518f88be..fe48ccf0a 100644 --- a/openlp/core/lib/pluginmanager.py +++ b/openlp/core/lib/pluginmanager.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/core/lib/renderer.py b/openlp/core/lib/renderer.py index f0da82b0e..f574ed6a8 100644 --- a/openlp/core/lib/renderer.py +++ b/openlp/core/lib/renderer.py @@ -1,4 +1,4 @@ - # -*- coding: utf-8 -*- +# -*- coding: utf-8 -*- # vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 ############################################################################### @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -43,7 +43,6 @@ class Renderer(object): """ self._rect = None self._debug = False - self._right_margin = 64 # the amount of right indent self._display_shadow_size_footer = 0 self._display_outline_size_footer = 0 self.theme_name = None @@ -149,7 +148,7 @@ class Renderer(object): def pre_render_text(self, text): metrics = QtGui.QFontMetrics(self.mainFont) #work out line width - line_width = self._rect.width() - self._right_margin + line_width = self._rect.width() #number of lines on a page - adjust for rounding up. line_height = metrics.height() if self._theme.display_shadow: @@ -224,6 +223,7 @@ class Renderer(object): ``rect_footer`` The footer text block. """ + log.debug(u'set_text_rectangle %s , %s' %(rect_main, rect_footer) ) self._rect = rect_main self._rect_footer = rect_footer @@ -447,8 +447,7 @@ class Renderer(object): rightextent = x + w # shift right from last line's rh edge if self._theme.display_wrapStyle == 1 and linenum != 0: - rightextent = self._first_line_right_extent + \ - self._right_margin + rightextent = self._first_line_right_extent if rightextent > maxx: rightextent = maxx x = rightextent - w @@ -467,8 +466,7 @@ class Renderer(object): tlcorner=(x + display_shadow_size, y + display_shadow_size), draw=True, color = self._theme.display_shadow_color) self._get_extent_and_render(line, footer, tlcorner=(x, y), draw=True, - outline_size=display_outline_size, - outline_color=self._theme.display_outline_color) + outline_size=display_outline_size) y += h if linenum == 0: self._first_line_right_extent = rightextent @@ -506,7 +504,7 @@ class Renderer(object): self.mainFont.setPixelSize(self._theme.font_main_proportion) def _get_extent_and_render(self, line, footer, tlcorner=(0, 0), draw=False, - color=None, outline_size=None, outline_color=None): + color=None, outline_size=0): """ Find bounding box of text - as render_single_line. If draw is set, actually draw the text to the current DC as well return width and @@ -545,21 +543,23 @@ class Renderer(object): else: pen = QtGui.QColor(color) x, y = tlcorner - if outline_size: + if self._theme.display_outline and outline_size != 0 and not footer: path = QtGui.QPainterPath() path.addText(QtCore.QPointF(x, y + metrics.ascent()), font, line) self.painter.setBrush(self.painter.pen().brush()) - self.painter.setPen(QtGui.QPen(QtGui.QColor(outline_color), outline_size)) + self.painter.setPen(QtGui.QPen( + QtGui.QColor(self._theme.display_outline_color), outline_size)) self.painter.drawPath(path) self.painter.setPen(pen) self.painter.drawText(x, y + metrics.ascent(), line) if self._theme.display_slideTransition: # Print 2nd image with 70% weight - if outline_size: + if self._theme.display_outline and outline_size != 0 and not footer: path = QtGui.QPainterPath() path.addText(QtCore.QPointF(x, y + metrics.ascent()), font, line) self.painter2.setBrush(self.painter2.pen().brush()) - self.painter2.setPen(QtGui.QPen(QtGui.QColor(outline_color), outline_size)) + self.painter2.setPen(QtGui.QPen( + QtGui.QColor(self._theme.display_outline_color), outline_size)) self.painter2.drawPath(path) self.painter2.setFont(font) self.painter2.setPen(pen) diff --git a/openlp/core/lib/rendermanager.py b/openlp/core/lib/rendermanager.py index edab3d309..e811529db 100644 --- a/openlp/core/lib/rendermanager.py +++ b/openlp/core/lib/rendermanager.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -49,7 +49,7 @@ class RenderManager(object): """ log.info(u'RenderManager Loaded') - def __init__(self, theme_manager, screens, screen_number=0): + def __init__(self, theme_manager, screens): """ Initialise the render manager. """ @@ -57,7 +57,6 @@ class RenderManager(object): self.screens = screens self.theme_manager = theme_manager self.renderer = Renderer() - self.screens.set_current_display(screen_number) self.calculate_default(self.screens.current[u'size']) self.theme = u'' self.service_theme = u'' @@ -65,12 +64,9 @@ class RenderManager(object): self.override_background = None self.themedata = None - def update_display(self, screen_number): + def update_display(self): """ Updates the render manager's information about the current screen. - - ``screen_number`` - The updated index of the output/display screen. """ log.debug(u'Update Display') self.calculate_default(self.screens.current[u'size']) @@ -146,13 +142,13 @@ class RenderManager(object): footer_rect = None if not theme.font_main_override: main_rect = QtCore.QRect(10, 0, - self.width - 1, self.footer_start) + self.width - 20, self.footer_start) else: main_rect = QtCore.QRect(theme.font_main_x, theme.font_main_y, theme.font_main_width - 1, theme.font_main_height - 1) if not theme.font_footer_override: footer_rect = QtCore.QRect(10, self.footer_start, - self.width - 1, self.height - self.footer_start) + self.width - 20, self.height - self.footer_start) else: footer_rect = QtCore.QRect(theme.font_footer_x, theme.font_footer_y, theme.font_footer_width - 1, diff --git a/openlp/core/lib/serviceitem.py b/openlp/core/lib/serviceitem.py index 7d869a610..8601e818e 100644 --- a/openlp/core/lib/serviceitem.py +++ b/openlp/core/lib/serviceitem.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -42,6 +42,14 @@ class ServiceItemType(object): Image = 2 Command = 3 +class ItemCapabilities(object): + AllowsPreview = 1 + AllowsEdit = 2 + AllowsMaintain = 3 + RequiresMedia = 4 + AllowsLoop = 5 + + class ServiceItem(object): """ The service item is a base class for the plugins to use to interact with @@ -66,14 +74,19 @@ class ServiceItem(object): self.iconic_representation = None self.raw_footer = None self.theme = None - self.service_item_path = None self.service_item_type = None - self.edit_enabled = False self._raw_frames = [] self._display_frames = [] self._uuid = unicode(uuid.uuid1()) - self.autoPreviewAllowed = False self.notes = u'' + self.from_plugin = False + self.capabilities = [] + + def add_capability(self, capability): + self.capabilities.append(capability) + + def is_capable(self, capability): + return capability in self.capabilities def addIcon(self, icon): """ @@ -156,9 +169,8 @@ class ServiceItem(object): The actual image file name. """ self.service_item_type = ServiceItemType.Image - self.service_item_path = path self._raw_frames.append( - {u'title': title, u'image': image}) + {u'title': title, u'image': image, u'path': path}) def add_from_text(self, title, raw_slide, verseTag=None): """ @@ -189,9 +201,8 @@ class ServiceItem(object): The command of/for the slide. """ self.service_item_type = ServiceItemType.Command - self.service_item_path = path self._raw_frames.append( - {u'title': file_name, u'image': image}) + {u'title': file_name, u'image': image, u'path': path}) def get_service_repr(self): """ @@ -208,7 +219,8 @@ class ServiceItem(object): u'type':self.service_item_type, u'audit':self.audit, u'notes':self.notes, - u'preview':self.autoPreviewAllowed + u'from_plugin':self.from_plugin, + u'capabilities':self.capabilities } service_data = [] if self.service_item_type == ServiceItemType.Text: @@ -242,8 +254,9 @@ class ServiceItem(object): self.addIcon(header[u'icon']) self.raw_footer = header[u'footer'] self.audit = header[u'audit'] - self.autoPreviewAllowed = header[u'preview'] self.notes = header[u'notes'] + self.from_plugin = header[u'from_plugin'] + self.capabilities = header[u'capabilities'] if self.service_item_type == ServiceItemType.Text: for slide in serviceitem[u'serviceitem'][u'data']: self._raw_frames.append(slide) @@ -279,11 +292,8 @@ class ServiceItem(object): """ return self._uuid != other._uuid - def is_song(self): - return self.name == u'Songs' - def is_media(self): - return self.name.lower() == u'media' + return ItemCapabilities.RequiresMedia in self.capabilities def is_command(self): return self.service_item_type == ServiceItemType.Command @@ -320,6 +330,12 @@ class ServiceItem(object): """ return self._raw_frames[row][u'title'] + def get_frame_path(self, row=0): + """ + Returns the title of the raw frame + """ + return self._raw_frames[row][u'path'] + def request_audit(self): if self.audit: Receiver.send_message(u'songusage_live', self.audit) diff --git a/openlp/core/lib/settingsmanager.py b/openlp/core/lib/settingsmanager.py index be5c14af1..fe2858cd0 100644 --- a/openlp/core/lib/settingsmanager.py +++ b/openlp/core/lib/settingsmanager.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/core/lib/settingstab.py b/openlp/core/lib/settingstab.py index f9d4aa8a0..930ce6bc8 100644 --- a/openlp/core/lib/settingstab.py +++ b/openlp/core/lib/settingstab.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -54,6 +54,7 @@ class SettingsTab(QtGui.QWidget): self.config = PluginConfig(title) else: self.config = PluginConfig(section) + self.preLoad() self.load() def setupUi(self): @@ -62,6 +63,12 @@ class SettingsTab(QtGui.QWidget): """ pass + def preLoad(self): + """ + Setup the tab's interface. + """ + pass + def retranslateUi(self): """ Setup the interface translation strings. @@ -90,4 +97,4 @@ class SettingsTab(QtGui.QWidget): """ Changes which need to be made after setup of application """ - pass \ No newline at end of file + pass diff --git a/openlp/core/lib/songxmlhandler.py b/openlp/core/lib/songxmlhandler.py index 7a532970d..4b0a26d7b 100644 --- a/openlp/core/lib/songxmlhandler.py +++ b/openlp/core/lib/songxmlhandler.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -148,6 +148,8 @@ class SongXMLParser(object): verse_list = [] for element in iter: if element.tag == u'verse': + if element.text is None: + element.text = u'' verse_list.append([element.attrib, unicode(element.text).decode('unicode-escape')]) return verse_list diff --git a/openlp/core/lib/themexmlhandler.py b/openlp/core/lib/themexmlhandler.py index cbd46d597..c30184328 100644 --- a/openlp/core/lib/themexmlhandler.py +++ b/openlp/core/lib/themexmlhandler.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -53,7 +53,7 @@ blankthemexml=\ Normal False 0 - + Arial @@ -62,7 +62,7 @@ blankthemexml=\ Normal False 0 - + True diff --git a/openlp/core/lib/toolbar.py b/openlp/core/lib/toolbar.py index 3753fedc0..e50459943 100644 --- a/openlp/core/lib/toolbar.py +++ b/openlp/core/lib/toolbar.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/core/lib/xmlrootclass.py b/openlp/core/lib/xmlrootclass.py index c56474d17..78682c5a3 100644 --- a/openlp/core/lib/xmlrootclass.py +++ b/openlp/core/lib/xmlrootclass.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/core/test/data_for_tests/render_theme.xml b/openlp/core/test/data_for_tests/render_theme.xml deleted file mode 100644 index 63dfddc02..000000000 --- a/openlp/core/test/data_for_tests/render_theme.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - openlp.org Packaged Theme - 0 - clWhite - - - Tahoma - $00007F - 53 - pixels - 0 - $000000 - 0 - $000000 - 0 - 0 - 1 - diff --git a/openlp/core/test/data_for_tests/snowbig.jpg b/openlp/core/test/data_for_tests/snowbig.jpg deleted file mode 100644 index f1d041927..000000000 Binary files a/openlp/core/test/data_for_tests/snowbig.jpg and /dev/null differ diff --git a/openlp/core/test/data_for_tests/snowsmall.jpg b/openlp/core/test/data_for_tests/snowsmall.jpg deleted file mode 100644 index 3fd506415..000000000 Binary files a/openlp/core/test/data_for_tests/snowsmall.jpg and /dev/null differ diff --git a/openlp/core/test/data_for_tests/sunset1.jpg b/openlp/core/test/data_for_tests/sunset1.jpg deleted file mode 100644 index 75e819c6e..000000000 Binary files a/openlp/core/test/data_for_tests/sunset1.jpg and /dev/null differ diff --git a/openlp/core/test/data_for_tests/treesbig.jpg b/openlp/core/test/data_for_tests/treesbig.jpg deleted file mode 100644 index 9454b3a68..000000000 Binary files a/openlp/core/test/data_for_tests/treesbig.jpg and /dev/null differ diff --git a/openlp/core/test/data_for_tests/treessmall.jpg b/openlp/core/test/data_for_tests/treessmall.jpg deleted file mode 100644 index d52ec6e80..000000000 Binary files a/openlp/core/test/data_for_tests/treessmall.jpg and /dev/null differ diff --git a/openlp/core/test/golden_bitmaps/test_bg_shrink_x.bmp b/openlp/core/test/golden_bitmaps/test_bg_shrink_x.bmp deleted file mode 100644 index c7261c100..000000000 Binary files a/openlp/core/test/golden_bitmaps/test_bg_shrink_x.bmp and /dev/null differ diff --git a/openlp/core/test/golden_bitmaps/test_bg_shrink_y.bmp b/openlp/core/test/golden_bitmaps/test_bg_shrink_y.bmp deleted file mode 100644 index 91adf0188..000000000 Binary files a/openlp/core/test/golden_bitmaps/test_bg_shrink_y.bmp and /dev/null differ diff --git a/openlp/core/test/golden_bitmaps/test_bg_stretch_x.bmp b/openlp/core/test/golden_bitmaps/test_bg_stretch_x.bmp deleted file mode 100644 index 9741a266b..000000000 Binary files a/openlp/core/test/golden_bitmaps/test_bg_stretch_x.bmp and /dev/null differ diff --git a/openlp/core/test/golden_bitmaps/test_bg_stretch_y.bmp b/openlp/core/test/golden_bitmaps/test_bg_stretch_y.bmp deleted file mode 100644 index a05a930d8..000000000 Binary files a/openlp/core/test/golden_bitmaps/test_bg_stretch_y.bmp and /dev/null differ diff --git a/openlp/core/test/golden_bitmaps/test_gradient_h.bmp b/openlp/core/test/golden_bitmaps/test_gradient_h.bmp deleted file mode 100644 index f968fe8b7..000000000 Binary files a/openlp/core/test/golden_bitmaps/test_gradient_h.bmp and /dev/null differ diff --git a/openlp/core/test/golden_bitmaps/test_gradient_v.bmp b/openlp/core/test/golden_bitmaps/test_gradient_v.bmp deleted file mode 100644 index 1b9b434e3..000000000 Binary files a/openlp/core/test/golden_bitmaps/test_gradient_v.bmp and /dev/null differ diff --git a/openlp/core/test/golden_bitmaps/test_theme_basic.bmp b/openlp/core/test/golden_bitmaps/test_theme_basic.bmp deleted file mode 100644 index b156ac762..000000000 Binary files a/openlp/core/test/golden_bitmaps/test_theme_basic.bmp and /dev/null differ diff --git a/openlp/core/test/golden_bitmaps/test_theme_font.bmp b/openlp/core/test/golden_bitmaps/test_theme_font.bmp deleted file mode 100644 index c0f6f3aa5..000000000 Binary files a/openlp/core/test/golden_bitmaps/test_theme_font.bmp and /dev/null differ diff --git a/openlp/core/test/golden_bitmaps/test_theme_horizontal_align_centre.bmp b/openlp/core/test/golden_bitmaps/test_theme_horizontal_align_centre.bmp deleted file mode 100644 index 2c10be95e..000000000 Binary files a/openlp/core/test/golden_bitmaps/test_theme_horizontal_align_centre.bmp and /dev/null differ diff --git a/openlp/core/test/golden_bitmaps/test_theme_horizontal_align_left.bmp b/openlp/core/test/golden_bitmaps/test_theme_horizontal_align_left.bmp deleted file mode 100644 index c7245748e..000000000 Binary files a/openlp/core/test/golden_bitmaps/test_theme_horizontal_align_left.bmp and /dev/null differ diff --git a/openlp/core/test/golden_bitmaps/test_theme_horizontal_align_left_lyric.bmp b/openlp/core/test/golden_bitmaps/test_theme_horizontal_align_left_lyric.bmp deleted file mode 100644 index 8e3fc877a..000000000 Binary files a/openlp/core/test/golden_bitmaps/test_theme_horizontal_align_left_lyric.bmp and /dev/null differ diff --git a/openlp/core/test/golden_bitmaps/test_theme_horizontal_align_right.bmp b/openlp/core/test/golden_bitmaps/test_theme_horizontal_align_right.bmp deleted file mode 100644 index 7d404a85e..000000000 Binary files a/openlp/core/test/golden_bitmaps/test_theme_horizontal_align_right.bmp and /dev/null differ diff --git a/openlp/core/test/golden_bitmaps/test_theme_shadow_outline.bmp b/openlp/core/test/golden_bitmaps/test_theme_shadow_outline.bmp deleted file mode 100644 index daa1e07dd..000000000 Binary files a/openlp/core/test/golden_bitmaps/test_theme_shadow_outline.bmp and /dev/null differ diff --git a/openlp/core/test/golden_bitmaps/test_theme_vertical_align_bot.bmp b/openlp/core/test/golden_bitmaps/test_theme_vertical_align_bot.bmp deleted file mode 100644 index d43698b9f..000000000 Binary files a/openlp/core/test/golden_bitmaps/test_theme_vertical_align_bot.bmp and /dev/null differ diff --git a/openlp/core/test/golden_bitmaps/test_theme_vertical_align_cen.bmp b/openlp/core/test/golden_bitmaps/test_theme_vertical_align_cen.bmp deleted file mode 100644 index be19a7288..000000000 Binary files a/openlp/core/test/golden_bitmaps/test_theme_vertical_align_cen.bmp and /dev/null differ diff --git a/openlp/core/test/golden_bitmaps/test_theme_vertical_align_top.bmp b/openlp/core/test/golden_bitmaps/test_theme_vertical_align_top.bmp deleted file mode 100644 index c7245748e..000000000 Binary files a/openlp/core/test/golden_bitmaps/test_theme_vertical_align_top.bmp and /dev/null differ diff --git a/openlp/core/test/test_mediamanageritem.py b/openlp/core/test/test_mediamanageritem.py deleted file mode 100644 index f9539174c..000000000 --- a/openlp/core/test/test_mediamanageritem.py +++ /dev/null @@ -1,85 +0,0 @@ -import logging -import os -import sys - -from PyQt4 import QtCore, QtGui - -from openlp.core.lib import MediaManagerItem - -logging.basicConfig(level=logging.DEBUG, - format='%(asctime)s %(name)-30s %(levelname)-8s %(message)s', - datefmt='%m-%d %H:%M', - filename='plugins.log', - filemode='w') - -console=logging.StreamHandler() -# set a format which is simpler for console use -formatter = logging.Formatter(u'%(name)24s: %(levelname)-8s %(message)s') -# tell the handler to use this format -console.setFormatter(formatter) -logging.getLogger(u'').addHandler(console) -log = logging.getLogger(u'') -logging.info(u'Logging started') -mypath = os.path.split(os.path.abspath(__file__))[0] -sys.path.insert(0,(os.path.join(mypath, '..' ,'..', '..'))) - -class TestMediaManager: - def setup_class(self): - self.app = QtGui.QApplication([]) - logging.info (u'App is ' + unicode(self.app)) - self.main_window = QtGui.QMainWindow() - self.main_window.resize(200, 600) - self.MediaManagerDock = QtGui.QDockWidget(self.main_window) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, - QtGui.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth( - self.MediaManagerDock.sizePolicy().hasHeightForWidth()) - self.MediaManagerDock.setSizePolicy(sizePolicy) - icon = QtGui.QIcon() - icon.addPixmap(QtGui.QPixmap(u':/system/system_mediamanager.png'), - QtGui.QIcon.Normal, QtGui.QIcon.Off) - self.MediaManagerDock.setWindowIcon(icon) - self.MediaManagerDock.setFloating(False) - self.MediaManagerContents = QtGui.QWidget() - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, - QtGui.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth( - self.MediaManagerContents.sizePolicy().hasHeightForWidth()) - self.MediaManagerContents.setSizePolicy(sizePolicy) - self.MediaManagerLayout = QtGui.QHBoxLayout(self.MediaManagerContents) - self.MediaManagerLayout.setContentsMargins(0, 2, 0, 0) - self.MediaToolBox = QtGui.QToolBox(self.MediaManagerContents) - self.MediaManagerDock.setWidget(self.MediaManagerContents) - self.main_window.addDockWidget(QtCore.Qt.DockWidgetArea(1), - self.MediaManagerDock) - self.MediaManagerLayout.addWidget(self.MediaToolBox) - def test1(self): - log=logging.getLogger(u'test1') - log.info(u'Start') - i1=MediaManagerItem(self.MediaToolBox) - i2=MediaManagerItem(self.MediaToolBox) - log.info(u'i1'+unicode(i1)) - log.info(u'i2'+unicode(i2)) - i1.addToolbar() - i1.addToolbarButton(u'Test1', u'Test1', None) - i2.addToolbar() - i2.addToolbarButton(u'Test2', u'Test2', None) - self.MediaToolBox.setItemText( - self.MediaToolBox.indexOf(i1), self.trUtf8('Item1')) - self.MediaToolBox.setItemText( - self.MediaToolBox.indexOf(i2), self.trUtf8('Item2')) - log.info(u'Show window') - self.main_window.show() - log.info(u'End') - return 1 - -if __name__ == "__main__": - t=TestMediaManager() - t.setup_class() - t.test1() - log.info(u'exec') - sys.exit(t.app.exec_()) diff --git a/openlp/core/test/test_plugin_manager.py b/openlp/core/test/test_plugin_manager.py deleted file mode 100644 index 1bc47d6d2..000000000 --- a/openlp/core/test/test_plugin_manager.py +++ /dev/null @@ -1,49 +0,0 @@ -import logging -import os -import sys - -from openlp.core.lib.pluginmanager import PluginManager - -logging.basicConfig(level=logging.DEBUG, - format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s', - datefmt='%m-%d %H:%M', - filename='plugins.log', - filemode='w') - -console=logging.StreamHandler() -# set a format which is simpler for console use -formatter = logging.Formatter(u'%(name)-12s: %(levelname)-8s %(message)s') -# tell the handler to use this format -console.setFormatter(formatter) -logging.getLogger(u'').addHandler(console) -log = logging.getLogger(u'') -logging.info(u'Logging started') -mypath = os.path.split(os.path.abspath(__file__))[0] -sys.path.insert(0,(os.path.join(mypath, '..' ,'..', '..'))) - -# test the plugin manager with some plugins in the test_plugins directory -class TestPluginManager: - def test_init(self): - self.p = PluginManager(u'./testplugins') - p = self.p - p.find_plugins(u'./testplugins', None, None) - assert(len(p.plugins) == 2) - # get list of the names of the plugins - names = [plugin.name for plugin in p.plugins] - # see which ones we've got - assert(u'testplugin1' in names) - assert(u'testplugin2' in names) - # and not got - it's too deep in the hierarchy! - assert(u'testplugin3' not in names) - # test that the weighting is done right - assert(p.plugins[0].name == "testplugin2") - assert(p.plugins[1].name == "testplugin1") - -if __name__ == "__main__": - log.debug(u'Starting') - t = TestPluginManager() - t.test_init() - log.debug(u'List of plugins found:') - for plugin in t.p.plugins: - log.debug(u'Plugin %s, name=%s (version=%d)' %(unicode(plugin), - plugin.name, plugin.version)) diff --git a/openlp/core/test/test_render.py b/openlp/core/test/test_render.py deleted file mode 100644 index 36052a6e9..000000000 --- a/openlp/core/test/test_render.py +++ /dev/null @@ -1,234 +0,0 @@ -""" -OpenLP - Open Source Lyrics Projection -Copyright (c) 2008 Raoul Snyman -Portions copyright (c) 2008 Martin Thompson, Tim Bentley - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free Software -Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place, Suite 330, Boston, MA 02111-1307 USA -""" - -import sys -import os -import os.path - -from PyQt4 import QtGui, QtCore - -from openlp.core.theme import Theme -from openlp.core.lib import Renderer - -mypath = os.path.split(os.path.abspath(__file__))[0] -sys.path.insert(0, (os.path.join(mypath, '..', '..', '..'))) - -# from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66062 -def whoami(depth=1): - return sys._getframe(depth).f_code.co_name - -class TstFrame: - # {{{ init - - def __init__(self, size): - """Create the DemoPanel.""" - self.width = size.width(); - self.height = size.height(); - # create something to be painted into - self._Buffer = QtGui.QPixmap(self.width, self.height) - def GetPixmap(self): - return self._Buffer - - # }}} - -class TestRender_base: - def __init__(self): - if not os.path.exists(u'test_results'): - os.mkdir(u'test_results') - self.app = None - def write_to_file(self, pixmap, name): - im=pixmap.toImage() - testpathname = os.path.join(u'test_results', name+'.bmp') - if os.path.exists(testpathname): - os.unlink(testpathname) - im.save(testpathname, 'bmp') - return im - # xxx quitting the app still leaves it hanging aroudn so we die - # when trying to start another one. Not quitting doesn't help - # though This means that the py.test runs both test modules in - # sequence and the second one tries to create another application - # which gives us errors :( - - def setup_class(self): - print "class setup", self - try: - if self.app is None: - pass - except AttributeError: # didn't have one - print "No app" - self.app = None - - print "Test app (should be None)" - if self.app is None: - print "App is None" - self.app = QtGui.QApplication([]) - else: - print "class setup, app is", app -# self.app = QtGui.QApplication([]) - - def teardown_class(self): - print "class quit", self, self.app - self.app.quit() - - def setup_method(self, method): - print "SSsetup", method - if not hasattr(self, 'app'): - self.app = None - try: # see if we already have an app for some reason. - # have to try and so something, cant just test against None - print "app", self.app, ";;;" - print self.app.quit() - print "quitted" - except RuntimeError: # not valid app, create one - print "Runtime error" - except AttributeError: # didn't have one - print "Attribute error" -# print "App", self.app -# self.app = QtGui.QApplication([]) - print "Application created and sorted" - self.size = QtCore.QSize(800,600) - frame = TstFrame(size = self.size) - self.frame = frame - self.paintdest = frame.GetPixmap() - self.renderer = Renderer() - self.renderer.set_paint_dest(self.paintdest) - self.expected_answer = "Don't know yet" - self.answer = None - print "--------------- Setup Done -------------" - - def teardown_method(self, method): - self.write_to_file(self.frame.GetPixmap(), 'test_render') - -class TestRender(TestRender_base): - def __init__(self): - TestRender_base.__init__(self) - - def setup_method(self, method): - TestRender_base.setup_method(self, method) - self.renderer.set_debug(1) - themefile = os.path.abspath(u'data_for_tests/render_theme.xml') - self.renderer.set_theme(Theme(themefile)) # set default theme - self.renderer._render_background() - self.renderer.set_text_rectangle(QtCore.QRect( - 0,0, self.size.width()-1, self.size.height()-1)) - self.msg = None - - def test_easy(self): - answer = self.renderer._render_single_line( - u'Test line', tlcorner = (0,100)) - assert(answer == (219,163)) - - def test_longer(self): - answer = self.renderer._render_single_line( - u'Test line with more words than fit on one line', - tlcorner = (10,10)) - assert(answer == (753,136)) - - def test_even_longer(self): - answer = self.renderer._render_single_line( - u'Test line with more words than fit on either one or two lines', - tlcorner = (10,10)) - assert(answer == (753,199)) - def test_lines(self): - lines = [] - lines.append(u'Line One') - lines.append(u'Line Two') - lines.append(u'Line Three and should be long enough to wrap') - lines.append(u'Line Four and should be long enough to wrap also') - answer = self.renderer._render_lines(lines) - assert(answer == QtCore.QRect(0,0,741,378)) - - def test_set_words_openlp(self): - words=""" -Verse 1: Line 1 -Line 2 - -Verse 2: Line 1 -Line 2 - -Verse 3: Line 1 -Line 2 -Line 3""" - expected_answer = ["Verse 1: Line 1\nLine 2","Verse 2: Line 1\nLine 2","Verse 3: Line 1\nLine 2\nLine 3"] - answer = self.renderer.set_words_openlp(words) - assert(answer == expected_answer) - - def test_render_screens(self): - words=""" -Verse 1: Line 1 -Line 2 - -Verse 2: Line 1 -Line 2 - -Verse 3: Line 1 -Line 2 -Line 3""" - verses = self.renderer.set_words_openlp(words) - expected_answer = ["Verse 1: Line 1\nLine 2","Verse 2: Line 1\nLine 2","Verse 3: Line 1\nLine 2\nLine 3"] - assert(verses == expected_answer) - - expected_answer = [QtCore.QRect(0,0,397,126), QtCore.QRect(0,0,397,126), - QtCore.QRect(0,0,397,189)] - for v in range(len(verses)): - answer=self.renderer.render_screen(v) -# print v, answer.x(), answer.y(), answer.width(), answer.height() - assert(answer == expected_answer[v]) - - def split_test(self, number, answer, expected_answers): - lines=[] - print "Split test", number, answer - for i in range(number): - extra="" - if i == 51: # make an extra long line on line 51 to test wrapping - extra = "Some more words to make it wrap around don't you know until it wraps so many times we don't know what to do" - lines.append(u'Line %d %s' % (i, extra)) - result = self.renderer.split_set_of_lines(lines) - print "results---------------__", result - for i in range(len(result)): - self.setup_method(None) - answer = self.renderer._render_lines(result[i]) - print answer - self.write_to_file(self.frame.GetPixmap(), "split_test_%03d"% i) - print number, i, answer.x(), answer.y(), answer.width(), \ - answer.height() - e = expected_answers[i] - assert(answer == QtCore.QRect(e[0],e[1],e[2],e[3])) - - - def test_splits(self): - print "Test splits" - self.split_test(100, 11, [(0,0,180,567), (0,0,214,567), (0,0,214,567), - (0,0,214,567), (0,0,214,567), (0,0,214,378), (0,0,759,567), - (0,0,214,567), (0,0,214,567), (0,0,214,567), (0,0,214,567), - (0,0,214,567), (0,0,214,567)]) - self.split_test(30, 4, [ (0,0,180,441), (0,0,214,441), (0,0,214,441), - (0,0,214,441)]) - self.split_test(20, 3, [(0,0,180,378), (0,0,214,378), (0,0,214,378)]) - self.split_test(12, 2, [(0,0,180,378), (0,0,214,378)]) - self.split_test(4, 1, [(0,0,180,252)]) - self.split_test(6, 1, [(0,0,180,378)]) - self.split_test(8, 1, [(0,0,180,504)]) - -if __name__ == "__main__": - t = TestRender() - t.setup_class() - t.setup_method(None) - t.test_easy() - t.test_splits() - t.teardown_method(None) diff --git a/openlp/core/test/test_render_theme.py b/openlp/core/test/test_render_theme.py deleted file mode 100644 index 05f692393..000000000 --- a/openlp/core/test/test_render_theme.py +++ /dev/null @@ -1,312 +0,0 @@ -""" -OpenLP - Open Source Lyrics Projection -Copyright (c) 2008 Raoul Snyman -Portions copyright (c) 2008 Martin Thompson, Tim Bentley - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free Software -Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place, Suite 330, Boston, MA 02111-1307 USA -""" - -import sys -import os - -from PyQt4 import QtGui, QtCore - -from openlp.core.theme import Theme -from test_render import TestRender_base, whoami - -pypath = os.path.split(os.path.abspath(__file__))[0] -sys.path.insert(0, (os.path.join(mypath, '..', '..', '..'))) - -def compare_images(goldenim, testim, threshold=0.01): - # easy test first - if goldenim == testim: - return 1 - # how close are they? Calculated the sum of absolute differences in - # each channel of each pixel and divide by the number of pixels in the image - # if this sum is < threshold, the images are deemed to be "close enough" - sad = 0; - for x in range(goldenim.width()): - for y in range(goldenim.height()): - p1=goldenim.pixel(x,y) - p2=testim.pixel(x,y) - sad += abs((p1&0xFF)-(p2&0xFF)) - sad += abs((p1>>8&0xFF)-(p2>>8&0xFF)) - sad += abs((p1>>16&0xFF)-(p2>>16&0xFF)) - sad /= float(goldenim.width()*goldenim.height()) - if (sad < threshold): - return 1 - return 0 - -class TestRenderTheme(TestRender_base): - # {{{ Basics - - def __init__(self): - TestRender_base.__init__(self) - - def setup_method(self, method): - TestRender_base.setup_method(self, method) - print "Theme setup", method -# print "setup theme" - self.renderer.set_theme(Theme(u'blank_theme.xml')) # set "blank" theme - self.renderer.set_text_rectangle(QtCore.QRect(0,0, self.size.width(), - self.size.height())) - words = """How sweet the name of Jesus sounds -In a believer's ear! -It soothes his sorrows, heals his wounds, -And drives away his fear. -""" - verses = self.renderer.set_words_openlp(words) -# usually the same - self.expected_answer = QtCore.QRect(0, 0, 559, 342) - self.msg = None - self.bmpname = "Not set a bitmap yet" - print "------------- setup done --------------" - - def teardown_method(self, method): - print "============ teardown =============", method, self.bmpname - if self.bmpname is not None: - assert (self.compare_DC_to_file(self.bmpname)) - if self.expected_answer is not None: # result=None => Nothing to check - assert self.expected_answer == self.answer - print "============ teardown done =========" - - def compare_DC_to_file(self, name): - """writes DC out to a bitmap file and then compares it with a golden - one returns True if OK, False if not (so you can assert on it) - - """ - print "--- compare DC to file --- ", name - p = self.frame.GetPixmap() - im = self.write_to_file(p, name) - print "Compare" - goldenfilename=os.path.join(u'golden_bitmaps",name+".bmp') - if os.path.exists(goldenfilename): - goldenim = QtGui.QImage(goldenfilename) - else: - print "File", goldenfilename, "not found" - return False - if (compare_images(goldenim, im)): - print name, "Images match" - return True - else: - print name, goldenfilename, "Images don't match" - return False - - def test_theme_basic(self): - self.answer = self.renderer.render_screen(0) - self.bmpname = whoami() - print self.renderer._theme.FontProportion - print self.answer, self.expected_answer, \ - self.answer == self.expected_answer -# self.msg=self.bmpname - - # }}} - - # {{{ Gradients - def test_gradient_h(self): - # normally we wouldn't hack with these directly! - self.renderer._theme.BackgroundType = 1 - self.renderer._theme.BackgroundParameter1 = QtGui.QColor(255,0,0) - self.renderer._theme.BackgroundParameter2 = QtGui.QColor(255,255,0) - self.renderer._theme.BackgroundParameter3 = 1 - self.answer = self.renderer.render_screen(0) - self.bmpname = whoami() - - def test_gradient_v(self): - # normally we wouldn't hack with these directly! - self.renderer._theme.BackgroundType = 1 - self.renderer._theme.BackgroundParameter1 = QtGui.QColor(255,0,0) - self.renderer._theme.BackgroundParameter2 = QtGui.QColor(255,255,0) - self.renderer._theme.BackgroundParameter3 = 0 - self.answer = self.renderer.render_screen(0) - self.bmpname = whoami() - # }}} - - # {{{ backgrounds - def test_bg_stretch_y(self): - t = Theme(u'blank_theme.xml') - t.BackgroundType = 2 - t.BackgroundParameter1 = os.path.join(u'data_for_tests', - 'snowsmall.jpg') - t.BackgroundParameter2 = QtGui.QColor(0,0,64) - t.BackgroundParameter3 = 0 - t.Name = "stretch y" - self.renderer.set_theme(t) - print "render" - self.answer = self.renderer.render_screen(0) - print "whoami" - self.bmpname = whoami() - print "fone" - - def test_bg_shrink_y(self): - t = Theme(u'blank_theme.xml') - t.BackgroundType = 2 - t.BackgroundParameter1 = os.path.join(u'data_for_tests', 'snowbig.jpg') - t.BackgroundParameter2 = QtGui.QColor(0,0,64) - t.BackgroundParameter3 = 0 - t.Name = "shrink y" - self.renderer.set_theme(t) - self.answer = self.renderer.render_screen(0) - self.bmpname = whoami() - - def test_bg_stretch_x(self): - t = Theme(u'blank_theme.xml') - t.BackgroundType = 2 - t.BackgroundParameter1 = os.path.join(u'data_for_tests', - 'treessmall.jpg') - t.BackgroundParameter2 = QtGui.QColor(0,0,64) - t.BackgroundParameter3 = 0 - t.VerticalAlign = 2 - t.Name = "stretch x" - self.renderer.set_theme(t) - self.answer = self.renderer.render_screen(0) - self.expected_answer = QtCore.QRect(0, 129, 559, 342) - self.bmpname = whoami() - - def test_bg_shrink_x(self): - t = Theme(u'blank_theme.xml') - t.BackgroundType = 2 - t.BackgroundParameter1 = os.path.join(u'data_for_tests', - 'treesbig.jpg') - t.BackgroundParameter2 = QtGui.QColor(0,0,64) - t.BackgroundParameter3 = 0 - t.VerticalAlign = 2 - t.Name = "shrink x" - self.renderer.set_theme(t) - self.expected_answer = QtCore.QRect(0, 129, 559, 342) - self.answer = self.renderer.render_screen(0) - self.bmpname = whoami() - # }}} - - # {{{ Vertical alignment - def test_theme_vertical_align_top(self): - t = Theme(u'blank_theme.xml') - t.BackgroundType = 0 - t.BackgroundParameter1 = QtGui.QColor(0,0,64) - t.VerticalAlign = 0 - t.Name = "valign top" - self.renderer.set_theme(t) - self.answer = self.renderer.render_screen(0) - self.bmpname = whoami() - - def test_theme_vertical_align_bot(self): - t = Theme(u'blank_theme.xml') - t.BackgroundType = 0 - t.BackgroundParameter1 = QtGui.QColor(0,0,64) - t.VerticalAlign = 1 - t.Name = "valign bot" - self.renderer.set_theme(t) - self.answer = self.renderer.render_screen(0) - self.expected_answer = QtCore.QRect(0, 257, 559, 342) - self.bmpname = whoami() - - def test_theme_vertical_align_cen(self): - t = Theme(u'blank_theme.xml') - t.BackgroundType = 0 - t.BackgroundParameter1 = QtGui.QColor(0,0,64) - t.VerticalAlign = 2 - t.Name = "valign cen" - self.renderer.set_theme(t) - self.answer = self.renderer.render_screen(0) - self.expected_answer = QtCore.QRect(0, 129, 559, 342) - self.bmpname = whoami() - # }}} - - # {{{ Horzontal alignment - def test_theme_horizontal_align_left(self): - t = Theme(u'blank_theme.xml') - t.BackgroundType = 0 - t.BackgroundParameter1 = QtGui.QColor(0,0,64) - t.VerticalAlign = 0 - t.HorizontalAlign = 0 - t.Name = "halign left" - self.renderer.set_theme(t) - self.answer = self.renderer.render_screen(0) - self.bmpname = whoami() - - def test_theme_horizontal_align_right(self): - t = Theme(u'blank_theme.xml') - t.BackgroundType = 0 - t.BackgroundParameter1 = QtGui.QColor(0,0,64) - t.VerticalAlign = 0 - t.HorizontalAlign = 1 - t.Name = "halign right" - self.renderer.set_theme(t) - self.expected_answer = QtCore.QRect(0, 0, 800, 342) - self.answer = self.renderer.render_screen(0) - self.bmpname = whoami() - - def test_theme_horizontal_align_centre(self): - t = Theme(u'blank_theme.xml') - t.BackgroundType = 0 - t.BackgroundParameter1 = QtGui.QColor(0,0,64) - t.VerticalAlign = 0 - t.HorizontalAlign = 2 - t.Name = "halign centre" - self.renderer.set_theme(t) - self.answer = self.renderer.render_screen(0) - self.expected_answer = QtCore.QRect(0, 0, 679, 342) - self.bmpname = whoami() - - def test_theme_horizontal_align_left_lyric(self): - t = Theme(u'blank_theme.xml') - t.BackgroundType = 0 - t.BackgroundParameter1 = QtGui.QColor(0,0,64) - t.VerticalAlign = 0 - t.HorizontalAlign = 0 - t.WrapStyle = 1 - t.Name = "halign left lyric" - self.renderer.set_theme(t) - self.answer = self.renderer.render_screen(0) - self.expected_answer = QtCore.QRect(0, 0, 778, 342) - self.bmpname = whoami() - # }}} - - # {{{ Shadows and outlines - def test_theme_shadow_outline(self): - t = Theme(u'blank_theme.xml') - - t.BackgroundType = 0 - t.BackgroundParameter1 = QtGui.QColor(0,0,0); - t.Name="shadow/outline" - t.Shadow = 1 - t.Outline = 1 - t.ShadowColor = QtGui.QColor(64,128,0) - t.OutlineColor = QtGui.QColor(128,0,0) - self.renderer.set_debug(1) - self.renderer.set_theme(t) - self.answer = self.renderer.render_screen(0) - hoffset = self.renderer._shadow_offset+2*(self.renderer._outline_offset) - voffset = hoffset * (len(self.renderer.words[0])+1) - - self.expected_answer = QtCore.QRect(0, 0, 559+hoffset, 342+voffset) - self.bmpname = whoami() - # }}} - - def test_theme_font(self): - t = Theme(u'blank_theme.xml') - t.BackgroundType = 0 - t.BackgroundParameter1 = QtGui.QColor(0,0,64) - t.Name = "font" - t.FontName = "Times New Roman" - self.renderer.set_theme(t) - self.answer = self.renderer.render_screen(0) - self.expected_answer = QtCore.QRect(0, 0, 499, 336) - self.bmpname=whoami() - -if __name__ == "__main__": - test_render_theme = TestRenderTheme() - test_render_theme.setup_class() - test_render_theme.setup_method(None) - test_render_theme.test_bg_stretch_y() - test_render_theme.teardown_method(None) diff --git a/openlp/core/test/testplugins/deeper/__init__.py b/openlp/core/test/testplugins/deeper/__init__.py deleted file mode 100644 index 8b1378917..000000000 --- a/openlp/core/test/testplugins/deeper/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/openlp/core/test/testplugins/deeper/toodeep/__init__.py b/openlp/core/test/testplugins/deeper/toodeep/__init__.py deleted file mode 100644 index 8b1378917..000000000 --- a/openlp/core/test/testplugins/deeper/toodeep/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/openlp/core/test/testplugins/deeper/toodeep/plugin3toodeep.py b/openlp/core/test/testplugins/deeper/toodeep/plugin3toodeep.py deleted file mode 100644 index 9746dbdd2..000000000 --- a/openlp/core/test/testplugins/deeper/toodeep/plugin3toodeep.py +++ /dev/null @@ -1,13 +0,0 @@ -from openlp.core.lib import Plugin -import logging - -class testplugin3toodeep(Plugin): - name="testplugin3" - version=0 - global log - log=logging.getLogger(u'testplugin1') - log.info(u'Started') - weight=10 - def __init__(self): - pass - \ No newline at end of file diff --git a/openlp/core/test/testplugins/testplugin1.py b/openlp/core/test/testplugins/testplugin1.py deleted file mode 100644 index 01ae468e6..000000000 --- a/openlp/core/test/testplugins/testplugin1.py +++ /dev/null @@ -1,13 +0,0 @@ -from openlp.core.lib import Plugin -import logging - -class testplugin1(Plugin): - name="testplugin1" - version=0 - global log - log=logging.getLogger(u'testplugin1') - log.info(u'Started') - weight=10 - def __init__(self): - pass - \ No newline at end of file diff --git a/openlp/core/test/testplugins/testplugin2/__init__.py b/openlp/core/test/testplugins/testplugin2/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/openlp/core/test/testplugins/testplugin2/testplugin2.py b/openlp/core/test/testplugins/testplugin2/testplugin2.py deleted file mode 100644 index c1687d2d9..000000000 --- a/openlp/core/test/testplugins/testplugin2/testplugin2.py +++ /dev/null @@ -1,8 +0,0 @@ -from openlp.core.lib import Plugin - -class testplugin2(Plugin): - name="testplugin2" - version=1 - weight=1 - def __init__(self): - pass diff --git a/openlp/core/theme/__init__.py b/openlp/core/theme/__init__.py index b6b37022f..0975e977b 100644 --- a/openlp/core/theme/__init__.py +++ b/openlp/core/theme/__init__.py @@ -5,8 +5,9 @@ # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Martin Thompson, Tim Bentley, Carsten # -# Tinggaard, Jon Tibble, Jonathan Corwin, Maikel Stuivenberg, Scott Guerrieri # +# 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 # @@ -22,4 +23,4 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from theme import Theme \ No newline at end of file +from theme import Theme diff --git a/openlp/core/theme/test/test_theme.py b/openlp/core/theme/test/test_theme.py deleted file mode 100644 index 024142508..000000000 --- a/openlp/core/theme/test/test_theme.py +++ /dev/null @@ -1,57 +0,0 @@ -import os -import os.path -import sys - -from PyQt4 import QtGui - -from openlp.core.theme import Theme - -mypath = os.path.split(os.path.abspath(__file__))[0] -sys.path.insert(0, (os.path.join(mypath, '..', '..', '..', '..'))) - -print sys.path - -def test_read_theme(): - dir = os.path.split(__file__)[0] - # test we can read a theme - theme = Theme(os.path.join(dir, 'test_theme.xml')) - print theme - assert(theme.BackgroundParameter1 == 'sunset1.jpg') - assert(theme.BackgroundParameter2 is None) - assert(theme.BackgroundParameter3 is None) - assert(theme.BackgroundType == 2) - assert(theme.FontColor == QtGui.QColor(255,255,255)) - assert(theme.FontName == 'Tahoma') - assert(theme.FontProportion == 16) - assert(theme.FontUnits == 'pixels') - assert(theme.HorizontalAlign == 2) - assert(theme.Name == 'openlp.org Packaged Theme') - assert(theme.Outline == -1) - assert(theme.OutlineColor == QtGui.QColor(255,0,0)) - assert(theme.Shadow == -1) - assert(theme.ShadowColor == QtGui.QColor(0,0,1)) - assert(theme.VerticalAlign == 0) - -def test_theme(): - # test we create a "blank" theme correctly - theme = Theme() - print theme - assert(theme.BackgroundParameter1 == QtGui.QColor(0,0,0)) - assert(theme.BackgroundParameter2 is None) - assert(theme.BackgroundParameter3 is None) - assert(theme.BackgroundType == 0) - assert(theme.FontColor == QtGui.QColor(255,255,255)) - assert(theme.FontName == 'Arial') - assert(theme.FontProportion == 30) - assert(theme.HorizontalAlign == 0) - assert(theme.FontUnits == 'pixels') - assert(theme.Name == 'BlankStyle') - assert(theme.Outline == 0) - assert(theme.Shadow == 0) - assert(theme.VerticalAlign == 0) - - print "Tests passed" - -if __name__ == "__main__": - test_read_theme() - test_theme() diff --git a/openlp/core/theme/test/test_theme.xml b/openlp/core/theme/test/test_theme.xml deleted file mode 100644 index 79bc2107f..000000000 --- a/openlp/core/theme/test/test_theme.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - openlp.org Packaged Theme - 2 - sunset1.jpg - - - Tahoma - clWhite - 16 - pixels - -1 - $00000001 - -1 - clRed - 2 - 0 - diff --git a/openlp/core/theme/theme.py b/openlp/core/theme/theme.py index 27969c9d9..b01126564 100644 --- a/openlp/core/theme/theme.py +++ b/openlp/core/theme/theme.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -149,4 +149,4 @@ class Theme(object): for key in dir(self): if key[0:1] != u'_': theme_strings.append(u'%30s : %s' % (key, getattr(self, key))) - return u'\n'.join(theme_strings) \ No newline at end of file + return u'\n'.join(theme_strings) diff --git a/openlp/core/ui/__init__.py b/openlp/core/ui/__init__.py index c2f571c3b..675c57476 100644 --- a/openlp/core/ui/__init__.py +++ b/openlp/core/ui/__init__.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -23,9 +23,13 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from serviceitemform import ServiceItemNoteForm +from slidecontroller import HideMode +from servicenoteform import ServiceNoteForm +from serviceitemeditform import ServiceItemEditForm from screen import ScreenList from maindisplay import MainDisplay +from maindisplay import VideoDisplay +from maindisplay import DisplayManager from amendthemeform import AmendThemeForm from slidecontroller import SlideController from splashscreen import SplashScreen @@ -41,4 +45,4 @@ from mainwindow import MainWindow __all__ = ['SplashScreen', 'AboutForm', 'SettingsForm', 'MainWindow', 'MainDisplay', 'SlideController', 'ServiceManager', 'ThemeManager', - 'AmendThemeForm', 'MediaDockManager', 'ServiceItemNoteForm'] + 'AmendThemeForm', 'MediaDockManager', 'ServiceItemEditForm'] diff --git a/openlp/core/ui/aboutdialog.py b/openlp/core/ui/aboutdialog.py index c93c1f176..7d8d27103 100644 --- a/openlp/core/ui/aboutdialog.py +++ b/openlp/core/ui/aboutdialog.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -115,7 +115,7 @@ class Ui_AboutDialog(object): def retranslateUi(self, AboutDialog): AboutDialog.setWindowTitle(self.trUtf8('About OpenLP')) self.AboutTextEdit.setPlainText(self.trUtf8( - 'OpenLP build - Open Source Lyrics ' + 'OpenLP - Open Source Lyrics ' 'Projection\n' '\n' 'OpenLP is free church presentation software, or lyrics ' @@ -142,24 +142,36 @@ class Ui_AboutDialog(object): ' Michael "cocooncrash" Gorven\n' ' Scott "sguerrieri" Guerrieri\n' ' Raoul "superfly" Snyman\n' - ' Maikel Stuivenberg\n' ' Martin "mijiti" Thompson\n' ' Jon "Meths" Tibble\n' + '\n' + 'Contributors\n' + ' Meinert "m2j" Jordan\n' + ' Christian "crichter" Richter\n' + ' Maikel Stuivenberg\n' ' Carsten "catini" Tingaard\n' '\n' 'Testers\n' - ' Wesley "wrst" Stout' + ' Philip "Phill" Ridout\n' + ' Wesley "wrst" Stout (lead)\n' + '\n' + 'Packagers\n' + ' Thomas "tabthorpe" Abthorpe (FreeBSD)\n' + ' Tim "TRB143" Bentley (Fedora)\n' + ' Michael "cocooncrash" Gorven (Ubuntu)\n' + ' Matthias "matthub" Hub (Mac OS X)\n' + ' Raoul "superfly" Snyman (Windows)\n' )) self.AboutNotebook.setTabText( self.AboutNotebook.indexOf(self.CreditsTab), self.trUtf8('Credits')) self.LicenseTextEdit.setPlainText(self.trUtf8( - 'Copyright ' + u'\u00a9'.encode('utf8') + ' 2004-2009 Raoul ' + 'Copyright ' + u'\u00a9'.encode('utf8') + ' 2004-2010 Raoul ' 'Snyman\n' - 'Portions copyright ' + u'\u00a9'.encode('utf8') + ' 2004-2009 ' + 'Portions copyright ' + u'\u00a9'.encode('utf8') + ' 2004-2010 ' 'Tim Bentley, Jonathan Corwin, Michael Gorven, Scott Guerrieri, ' - 'Maikel Stuivenberg, Martin Thompson, Jon Tibble, Carsten ' - 'Tinggaard\n' + 'Christian Richter, Maikel Stuivenberg, Martin Thompson, Jon ' + 'Tibble, Carsten Tinggaard\n' '\n' 'This program is free software; you can redistribute it and/or ' 'modify it under the terms of the GNU General Public License as ' diff --git a/openlp/core/ui/aboutform.py b/openlp/core/ui/aboutform.py index c3eb7bdcb..c79324515 100644 --- a/openlp/core/ui/aboutform.py +++ b/openlp/core/ui/aboutform.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -39,11 +39,16 @@ class AboutForm(QtGui.QDialog, Ui_AboutDialog): QtGui.QDialog.__init__(self, parent) self.applicationVersion = applicationVersion self.setupUi(self) - self.AboutTextEdit.setPlainText( - self.AboutTextEdit.toPlainText()\ - .replace(u'', self.applicationVersion[u'version'])\ - .replace(u'', self.applicationVersion[u'build']) - ) + about_text = self.AboutTextEdit.toPlainText() + about_text = about_text.replace(u'', + self.applicationVersion[u'version']) + if self.applicationVersion[u'build']: + build_text = u' %s %s' % (self.trUtf8('build'), + self.applicationVersion[u'build']) + else: + build_text = u'' + about_text = about_text.replace(u'', build_text) + self.AboutTextEdit.setPlainText(about_text) QtCore.QObject.connect(self.ContributeButton, QtCore.SIGNAL(u'clicked()'), self.onContributeButtonClicked) @@ -53,4 +58,4 @@ class AboutForm(QtGui.QDialog, Ui_AboutDialog): """ import webbrowser url = u'http://www.openlp.org/en/documentation/introduction/contributing.html' - webbrowser.open_new(url) \ No newline at end of file + webbrowser.open_new(url) diff --git a/openlp/core/ui/amendthemedialog.py b/openlp/core/ui/amendthemedialog.py index 4cf8528f1..65d675cd1 100644 --- a/openlp/core/ui/amendthemedialog.py +++ b/openlp/core/ui/amendthemedialog.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -116,7 +116,7 @@ class Ui_AmendThemeDialog(object): self.ImageLineEdit.setObjectName(u'ImageLineEdit') self.horizontalLayout_2.addWidget(self.ImageLineEdit) self.ImageToolButton = QtGui.QToolButton(self.ImageFilenameWidget) - icon1 = build_icon(u':/images/image_load.png') + icon1 = build_icon(u':/general/general_open.png') self.ImageToolButton.setIcon(icon1) self.ImageToolButton.setObjectName(u'ImageToolButton') self.horizontalLayout_2.addWidget(self.ImageToolButton) @@ -685,4 +685,4 @@ class Ui_AmendThemeDialog(object): self.ThemeTabWidget.setTabText( self.ThemeTabWidget.indexOf(self.OtherOptionsTab), self.trUtf8('Other Options')) - self.PreviewGroupBox.setTitle(self.trUtf8('Preview')) \ No newline at end of file + self.PreviewGroupBox.setTitle(self.trUtf8('Preview')) diff --git a/openlp/core/ui/amendthemeform.py b/openlp/core/ui/amendthemeform.py index 97eecd1e8..03c2df3f5 100644 --- a/openlp/core/ui/amendthemeform.py +++ b/openlp/core/ui/amendthemeform.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -393,6 +393,7 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog): self.theme.background_type = u'solid' if self.theme.background_color is None : self.theme.background_color = u'#000000' + self.ImageLineEdit.setText(u'') elif background == 1: # Gradient self.theme.background_type = u'gradient' if gradient == 0: # Horizontal @@ -405,6 +406,7 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog): self.theme.background_startColor = u'#000000' if self.theme.background_endColor is None : self.theme.background_endColor = u'#ff0000' + self.ImageLineEdit.setText(u'') else: self.theme.background_type = u'image' self.stateChanging(self.theme) @@ -422,7 +424,6 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog): self.Color1PushButton.setStyleSheet( u'background-color: %s' % \ unicode(self.theme.background_startColor)) - self.previewTheme() def onColor2PushButtonClicked(self): @@ -561,22 +562,18 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog): u'background-color: %s' % unicode(theme.font_main_color)) self.FontFooterColorPushButton.setStyleSheet( u'background-color: %s' % unicode(theme.font_footer_color)) - if not self.theme.font_main_override: self.FontMainDefaultCheckBox.setChecked(True) else: self.FontMainDefaultCheckBox.setChecked(False) - if not self.theme.font_footer_override: self.FontFooterDefaultCheckBox.setChecked(True) else: self.FontFooterDefaultCheckBox.setChecked(False) - self.OutlineColorPushButton.setStyleSheet( u'background-color: %s' % unicode(theme.display_outline_color)) self.ShadowColorPushButton.setStyleSheet( u'background-color: %s' % unicode(theme.display_shadow_color)) - if self.theme.display_outline: self.OutlineCheckBox.setChecked(True) self.OutlineColorPushButton.setEnabled(True) @@ -584,7 +581,6 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog): self.OutlineCheckBox.setChecked(False) self.OutlineColorPushButton.setEnabled(False) self.OutlineSpinBox.setValue(int(self.theme.display_outline_size)) - if self.theme.display_shadow: self.ShadowCheckBox.setChecked(True) self.ShadowColorPushButton.setEnabled(True) @@ -592,12 +588,10 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog): self.ShadowCheckBox.setChecked(False) self.ShadowColorPushButton.setEnabled(False) self.ShadowSpinBox.setValue(int(self.theme.display_shadow_size)) - if self.theme.display_slideTransition: self.SlideTransitionCheckedBox.setCheckState(QtCore.Qt.Checked) else: self.SlideTransitionCheckedBox.setCheckState(QtCore.Qt.Unchecked) - self.HorizontalComboBox.setCurrentIndex( self.theme.display_horizontalAlign) self.VerticalComboBox.setCurrentIndex(self.theme.display_verticalAlign) @@ -657,7 +651,6 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog): self.ImageFilenameWidget.setVisible(True) self.GradientLabel.setVisible(False) self.GradientComboBox.setVisible(False) - if not theme.font_main_override: self.FontMainXSpinBox.setEnabled(False) self.FontMainYSpinBox.setEnabled(False) diff --git a/openlp/core/ui/generaltab.py b/openlp/core/ui/generaltab.py index c65ea3dd0..ec20650cf 100644 --- a/openlp/core/ui/generaltab.py +++ b/openlp/core/ui/generaltab.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -25,16 +25,29 @@ from PyQt4 import QtCore, QtGui -from openlp.core.lib import SettingsTab, str_to_bool +from openlp.core.lib import SettingsTab, str_to_bool, Receiver class GeneralTab(SettingsTab): """ GeneralTab is the general settings tab in the settings dialog. """ - def __init__(self, screen_list): - self.screen_list = screen_list + def __init__(self, screens): + self.screens = screens SettingsTab.__init__(self, u'General') + def preLoad(self): + """ + Set up the display screen and set correct screen + values. + If not set before default to last screen. + """ + self.MonitorNumber = int(self.config.get_config(u'monitor', + self.screens.monitor_number)) + self.screens.set_current_display(self.MonitorNumber) + self.screens.monitor_number = self.MonitorNumber + self.DisplayOnMonitor = str_to_bool(self.config.get_config(u'display on monitor', u'True')) + self.screens.display = self.DisplayOnMonitor + def setupUi(self): self.setObjectName(u'GeneralTab') self.tabTitleVisible = self.trUtf8('General') @@ -60,6 +73,10 @@ class GeneralTab(SettingsTab): self.MonitorComboBox = QtGui.QComboBox(self.MonitorGroupBox) self.MonitorComboBox.setObjectName(u'MonitorComboBox') self.MonitorLayout.addWidget(self.MonitorComboBox) + self.MonitorLayout.addWidget(self.MonitorComboBox) + self.DisplayOnMonitorCheck = QtGui.QCheckBox(self.MonitorGroupBox) + self.DisplayOnMonitorCheck.setObjectName(u'MonitorComboBox') + self.MonitorLayout.addWidget(self.DisplayOnMonitorCheck) self.GeneralLeftLayout.addWidget(self.MonitorGroupBox) self.StartupGroupBox = QtGui.QGroupBox(self.GeneralLeftWidget) self.StartupGroupBox.setObjectName(u'StartupGroupBox') @@ -133,6 +150,8 @@ class GeneralTab(SettingsTab): 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, @@ -153,6 +172,7 @@ class GeneralTab(SettingsTab): def retranslateUi(self): self.MonitorGroupBox.setTitle(self.trUtf8('Monitors')) self.MonitorLabel.setText(self.trUtf8('Select monitor for output display:')) + self.DisplayOnMonitorCheck.setText(self.trUtf8('Display if in single screen')) self.StartupGroupBox.setTitle(self.trUtf8('Application Startup')) self.WarningCheckBox.setText(self.trUtf8('Show blank screen warning')) self.AutoOpenCheckBox.setText(self.trUtf8('Automatically open the last service')) @@ -168,6 +188,9 @@ class GeneralTab(SettingsTab): 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) @@ -193,13 +216,12 @@ class GeneralTab(SettingsTab): self.Password = self.PasswordEdit.displayText() def load(self): - for screen in self.screen_list.screen_list: + for screen in self.screens.screen_list: screen_name = u'%s %d' % (self.trUtf8('Screen'), screen[u'number'] + 1) if screen[u'primary']: screen_name = u'%s (%s)' % (screen_name, self.trUtf8('primary')) self.MonitorComboBox.addItem(screen_name) # Get the configs - self.MonitorNumber = int(self.config.get_config(u'monitor', u'0')) self.Warning = str_to_bool(self.config.get_config(u'blank warning', u'False')) self.AutoOpen = str_to_bool(self.config.get_config(u'auto open', u'False')) self.ShowSplash = str_to_bool(self.config.get_config(u'show splash', u'True')) @@ -211,6 +233,7 @@ class GeneralTab(SettingsTab): self.SaveCheckServiceCheckBox.setChecked(self.PromptSaveService) # Set a few things up 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) @@ -221,6 +244,7 @@ class GeneralTab(SettingsTab): def save(self): self.config.set_config(u'monitor', self.MonitorNumber) + self.config.set_config(u'display on monitor', self.DisplayOnMonitor) self.config.set_config(u'blank warning', self.Warning) self.config.set_config(u'auto open', self.AutoOpen) self.config.set_config(u'show splash', self.ShowSplash) @@ -229,3 +253,9 @@ class GeneralTab(SettingsTab): self.config.set_config(u'ccli number', self.CCLINumber) self.config.set_config(u'songselect username', self.Username) self.config.set_config(u'songselect password', self.Password) + self.screens.display = self.DisplayOnMonitor + #Monitor Number has changed. + if self.screens.monitor_number != self.MonitorNumber: + self.screens.monitor_number = self.MonitorNumber + self.screens.set_current_display(self.MonitorNumber) + Receiver.send_message(u'screen_changed') diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 510b0ecc7..15fc29650 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -30,9 +30,32 @@ from PyQt4 import QtCore, QtGui from PyQt4.phonon import Phonon from openlp.core.lib import Receiver, resize_image +from openlp.core.ui import HideMode log = logging.getLogger(__name__) + +class DisplayManager(QtGui.QWidget): + """ + Wrapper class to hold the display widgets. + I will provide API's in future to access the screens allow for + extra displays to be added. + """ + def __init__(self, screens): + QtGui.QWidget.__init__(self) + self.screens = screens + self.videoDisplay = VideoDisplay(self, screens) + self.mainDisplay = MainDisplay(self, screens) + + def setup(self): + self.videoDisplay.setup() + self.mainDisplay.setup() + + def close(self): + self.videoDisplay.close() + self.mainDisplay.close() + + class DisplayWidget(QtGui.QWidget): """ Customised version of QTableWidget which can respond to keyboard @@ -41,7 +64,7 @@ class DisplayWidget(QtGui.QWidget): log.info(u'MainDisplay loaded') def __init__(self, parent=None, name=None): - QtGui.QWidget.__init__(self, parent) + QtGui.QWidget.__init__(self, None) self.parent = parent self.hotkey_map = {QtCore.Qt.Key_Return: 'servicemanager_next_item', QtCore.Qt.Key_Space: 'live_slidecontroller_next_noloop', @@ -91,16 +114,11 @@ class MainDisplay(DisplayWidget): The list of screens. """ log.debug(u'Initilisation started') - DisplayWidget.__init__(self, None) + DisplayWidget.__init__(self, parent) self.parent = parent self.setWindowTitle(u'OpenLP Display') + self.setAttribute(QtCore.Qt.WA_TranslucentBackground) self.screens = screens - self.mediaObject = Phonon.MediaObject(self) - self.video = Phonon.VideoWidget() - self.video.setVisible(False) - self.audio = Phonon.AudioOutput(Phonon.VideoCategory, self.mediaObject) - Phonon.createPath(self.mediaObject, self.video) - Phonon.createPath(self.mediaObject, self.audio) self.display_image = QtGui.QLabel(self) self.display_image.setScaledContents(True) self.display_text = QtGui.QLabel(self) @@ -112,36 +130,26 @@ class MainDisplay(DisplayWidget): self.blankFrame = None self.frame = None self.firstTime = True - self.mediaLoaded = False self.hasTransition = False self.mediaBackground = False QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'live_slide_hide'), self.hideDisplay) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'live_slide_show'), self.showDisplay) - QtCore.QObject.connect(self.mediaObject, - QtCore.SIGNAL(u'finished()'), self.onMediaFinish) QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'media_start'), self.onMediaQueue) - QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'media_play'), self.onMediaPlay) - QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'media_pause'), self.onMediaPause) - QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'media_stop'), self.onMediaStop) + QtCore.SIGNAL(u'media_start'), self.hideDisplay) - def setup(self, screenNumber): + def setup(self): """ Sets up the screen on a particular screen. - @param (integer) screen This is the screen number. """ - log.debug(u'Setup %s for %s ' %(self.screens, screenNumber)) + log.debug(u'Setup %s for %s ' %(self.screens, + self.screens.monitor_number)) self.setVisible(False) self.screen = self.screens.current #Sort out screen locations and sizes self.setGeometry(self.screen[u'size']) self.display_alert.setGeometry(self.screen[u'size']) - self.video.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(), @@ -168,13 +176,13 @@ class MainDisplay(DisplayWidget): self.screen[u'size'].height(), QtGui.QImage.Format_ARGB32_Premultiplied) painter.begin(self.blankFrame) - #TODO make black when testing finished - painter.fillRect(self.blankFrame.rect(), QtCore.Qt.red) + painter.fillRect(self.blankFrame.rect(), QtCore.Qt.black) #build a blank transparent image 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? if not self.screen[u'primary']: @@ -183,9 +191,9 @@ class MainDisplay(DisplayWidget): else: self.setVisible(False) self.primary = True - Receiver.send_message(u'screen_changed') def resetDisplay(self): + log.debug(u'resetDisplay') Receiver.send_message(u'stop_display_loop') if self.primary: self.setVisible(False) @@ -193,32 +201,46 @@ class MainDisplay(DisplayWidget): self.showFullScreen() def hideDisplay(self): - self.mediaLoaded = True - self.setVisible(False) + log.debug(u'hideDisplay') + self.display_image.setPixmap(self.transparent) + self.display_alert.setPixmap(self.transparent) + self.display_text.setPixmap(self.transparent) + 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): - self.mediaLoaded = False + log.debug(u'showDisplay') if not self.primary: self.setVisible(True) self.showFullScreen() Receiver.send_message(u'flush_alert') def addImageWithText(self, frame): + log.debug(u'addImageWithText') 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') self.display_alert.setGeometry( QtCore.QRect(0, top, self.screen[u'size'].width(), height)) def addAlertImage(self, frame, blank=False): + log.debug(u'addAlertImage') if blank: self.display_alert.setPixmap(self.transparent) else: self.display_alert.setPixmap(frame) + self.moveToTop() def frameView(self, frame, transition=False): """ @@ -227,6 +249,7 @@ class MainDisplay(DisplayWidget): ``frame`` Image frame to be rendered """ + log.debug(u'frameView %d' % (self.displayBlank)) if not self.displayBlank: if transition: if self.frame is not None: @@ -246,63 +269,123 @@ class MainDisplay(DisplayWidget): else: self.display_text.setPixmap(QtGui.QPixmap.fromImage(frame)) self.display_frame = frame - if not self.isVisible(): + if not self.isVisible() and self.screens.display: self.setVisible(True) self.showFullScreen() + else: + self.waitingFrame = frame + self.waitingFrameTrans = transition - def blankDisplay(self, blanked=True): + def blankDisplay(self, blankType=HideMode.Blank, blanked=True): + log.debug(u'Blank main Display %d' % blanked) if blanked: self.displayBlank = True - self.display_text.setPixmap(QtGui.QPixmap.fromImage(self.blankFrame)) + if blankType == HideMode.Blank: + self.display_text.setPixmap(QtGui.QPixmap.fromImage(self.blankFrame)) + elif blankType == HideMode.Theme: + theme = self.parent.RenderManager.renderer.bg_frame + if not theme: + theme = self.blankFrame + self.display_text.setPixmap(QtGui.QPixmap.fromImage(theme)) + self.waitingFrame = None + self.waitingFrameTrans = False else: self.displayBlank = False - if self.display_frame: + if self.waitingFrame: + self.frameView(self.waitingFrame, self.waitingFrameTrans) + elif self.display_frame: self.frameView(self.display_frame) - def onMediaQueue(self, message): - log.debug(u'Queue new media message %s' % message) - self.display_image.close() - self.display_text.close() - self.display_alert.close() - file = os.path.join(message[1], message[2]) - if self.firstTime: - self.mediaObject.setCurrentSource(Phonon.MediaSource(file)) - self.firstTime = False + +class VideoDisplay(Phonon.VideoWidget): + """ + This is the form that is used to display videos on the projector. + """ + log.info(u'VideoDisplay Loaded') + + def __init__(self, parent, screens, + aspect=Phonon.VideoWidget.AspectRatioWidget): + """ + The constructor for the display form. + + ``parent`` + The parent widget. + + ``screens`` + The list of screens. + """ + log.debug(u'VideoDisplay Initilisation started') + Phonon.VideoWidget.__init__(self) + self.setWindowTitle(u'OpenLP Video Display') + self.parent = parent + self.screens = screens + self.mediaObject = Phonon.MediaObject() + self.setAspectRatio(aspect) + self.audioObject = Phonon.AudioOutput(Phonon.VideoCategory) + Phonon.createPath(self.mediaObject, self) + Phonon.createPath(self.mediaObject, self.audioObject) + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'media_start'), self.onMediaQueue) + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'media_play'), self.onMediaPlay) + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'media_pause'), self.onMediaPause) + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'media_stop'), self.onMediaStop) + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'update_config'), self.setup) + + def keyPressEvent(self, event): + if type(event) == QtGui.QKeyEvent: + #here accept the event and do something + if event.key() == QtCore.Qt.Key_Escape: + self.onMediaStop() + event.accept() + event.ignore() else: - self.mediaObject.enqueue(Phonon.MediaSource(file)) + event.ignore() + + def setup(self): + """ + Sets up the screen on a particular screen. + """ + log.debug(u'VideoDisplay Setup %s for %s ' %(self.screens, + self.screens.monitor_number)) + self.setVisible(False) + self.screen = self.screens.current + #Sort out screen locations and sizes + self.setGeometry(self.screen[u'size']) + # To display or not to display? + if not self.screen[u'primary']: + self.showFullScreen() + self.primary = False + else: + self.setVisible(False) + self.primary = True + + def onMediaQueue(self, message): + log.debug(u'VideoDisplay Queue new media message %s' % message) + file = os.path.join(message[1], message[2]) + source = self.mediaObject.setCurrentSource(Phonon.MediaSource(file)) self.onMediaPlay() def onMediaPlay(self): - log.debug(u'Play the new media, Live ') - if not self.mediaLoaded and not self.displayBlank: - self.blankDisplay() - self.display_frame = self.blankFrame - self.firstTime = True - self.mediaLoaded = True - self.display_image.hide() - self.display_text.hide() - self.display_alert.hide() - self.video.setFullScreen(True) - self.video.setVisible(True) + log.debug(u'VideoDisplay Play the new media, Live ') self.mediaObject.play() self.setVisible(True) - self.hide() + self.showFullScreen() def onMediaPause(self): - log.debug(u'Media paused by user') + log.debug(u'VideoDisplay Media paused by user') self.mediaObject.pause() + self.show() def onMediaStop(self): - log.debug(u'Media stopped by user') + log.debug(u'VideoDisplay Media stopped by user') self.mediaObject.stop() self.onMediaFinish() def onMediaFinish(self): - log.debug(u'Reached end of media playlist') - self.mediaObject.stop() + log.debug(u'VideoDisplay Reached end of media playlist') self.mediaObject.clearQueue() - self.mediaLoaded = False - self.video.setVisible(False) - self.display_text.show() - self.display_image.show() - self.blankDisplay(False) + self.setVisible(False) diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 41b6d245f..e0e8465f5 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -23,15 +23,14 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -import os import logging import time from PyQt4 import QtCore, QtGui from openlp.core.ui import AboutForm, SettingsForm, \ - ServiceManager, ThemeManager, MainDisplay, SlideController, \ - PluginForm, MediaDockManager + ServiceManager, ThemeManager, SlideController, \ + PluginForm, MediaDockManager, DisplayManager from openlp.core.lib import RenderManager, PluginConfig, build_icon, \ OpenLPDockWidget, SettingsManager, PluginManager, Receiver, str_to_bool from openlp.core.utils import check_latest_version, AppLocation @@ -68,13 +67,13 @@ class VersionThread(QtCore.QThread): """ Run the thread. """ - time.sleep(2) + time.sleep(1) + Receiver.send_message(u'blank_check') version = check_latest_version(self.generalConfig, self.app_version) #new version has arrived - if version != self.app_version: + if version != self.app_version[u'full']: Receiver.send_message(u'version_check', u'%s' % version) - class Ui_MainWindow(object): def setupUi(self, MainWindow): """ @@ -419,7 +418,7 @@ class Ui_MainWindow(object): self.LanguageEnglishItem.setText(self.trUtf8('English')) self.LanguageEnglishItem.setStatusTip( self.trUtf8('Set the interface language to English')) - self.ToolsAddToolItem.setText(self.trUtf8('&Add Tool...')) + self.ToolsAddToolItem.setText(self.trUtf8('Add &Tool...')) self.ToolsAddToolItem.setStatusTip( self.trUtf8('Add an application to the list of tools')) self.action_Preview_Panel.setText(self.trUtf8('&Preview Pane')) @@ -443,7 +442,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): self.serviceNotSaved = False self.settingsmanager = SettingsManager(screens) self.generalConfig = PluginConfig(u'General') - self.mainDisplay = MainDisplay(self, screens) + self.displayManager = DisplayManager(screens) self.aboutForm = AboutForm(self, applicationVersion) self.settingsForm = SettingsForm(self.screens, self, self) # Set up the path with plugins @@ -494,6 +493,12 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): QtCore.SIGNAL(u'update_global_theme'), self.defaultThemeChanged) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'version_check'), self.versionCheck) + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'blank_check'), self.blankCheck) + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'screen_changed'), self.screenChanged) + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'status_message'), self.showStatusMessage) QtCore.QObject.connect(self.FileNewItem, QtCore.SIGNAL(u'triggered()'), self.ServiceManagerContents.onNewService) @@ -510,7 +515,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): #RenderManager needs to call ThemeManager and #ThemeManager needs to call RenderManager self.RenderManager = RenderManager(self.ThemeManagerContents, - self.screens, self.getMonitorNumber()) + self.screens) #Define the media Dock Manager self.mediaDockManager = MediaDockManager(self.MediaToolBox) log.info(u'Load Plugins') @@ -521,7 +526,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): self.plugin_helpers[u'service'] = self.ServiceManagerContents self.plugin_helpers[u'settings'] = self.settingsForm self.plugin_helpers[u'toolbox'] = self.mediaDockManager - self.plugin_helpers[u'maindisplay'] = self.mainDisplay + self.plugin_helpers[u'maindisplay'] = self.displayManager.mainDisplay self.plugin_manager.find_plugins(pluginpath, self.plugin_helpers) # hook methods have to happen after find_plugins. Find plugins needs # the controllers hence the hooks have moved from setupUI() to here @@ -550,39 +555,36 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): def versionCheck(self, version): """ Checks the version of the Application called from openlp.pyw + Triggered by delay thread. """ app_version = self.applicationVersion[u'full'] - version_text = unicode(self.trUtf8('OpenLP version %s has been updated ' - 'to version %s\n\nYou can obtain the latest version from http://openlp.org')) + version_text = unicode(self.trUtf8('Version %s of OpenLP is now ' + 'available for download (you are currently running version %s).' + '\n\nYou can download the latest version from http://openlp.org')) QtGui.QMessageBox.question(self, self.trUtf8('OpenLP Version Updated'), - version_text % (app_version, version), + version_text % (version, app_version), QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok), QtGui.QMessageBox.Ok) - def getMonitorNumber(self): - """ - Set up the default behaviour of the monitor configuration in - here. Currently it is set to default to monitor 0 if the saved - monitor number does not exist. - """ - screen_number = int(self.generalConfig.get_config(u'monitor', 0)) - if not self.screens.screen_exists(screen_number): - screen_number = 0 - return screen_number - def show(self): """ Show the main form, as well as the display form """ self.showMaximized() - screen_number = self.getMonitorNumber() - self.mainDisplay.setup(screen_number) - if self.mainDisplay.isVisible(): - self.mainDisplay.setFocus() + #screen_number = self.getMonitorNumber() + self.displayManager.setup() + if self.displayManager.mainDisplay.isVisible(): + self.displayManager.mainDisplay.setFocus() self.activateWindow() if str_to_bool(self.generalConfig.get_config(u'auto open', False)): self.ServiceManagerContents.onLoadService(True) + + def blankCheck(self): + """ + Check and display message if screen blank on setup. + Triggered by delay thread. + """ if str_to_bool(self.generalConfig.get_config(u'screen blank', False)) \ and str_to_bool(self.generalConfig.get_config(u'blank warning', False)): self.LiveController.onBlankDisplay(True) @@ -593,8 +595,10 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): QtGui.QMessageBox.Ok) def versionThread(self): - app_version = self.applicationVersion[u'full'] - vT = VersionThread(self, app_version, self.generalConfig) + """ + Start an initial setup thread to delay notifications + """ + vT = VersionThread(self, self.applicationVersion, self.generalConfig) vT.start() def onHelpAboutItemClicked(self): @@ -616,11 +620,15 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): Show the Settings dialog """ self.settingsForm.exec_() - updated_display = self.getMonitorNumber() - if updated_display != self.screens.current_display: - self.screens.set_current_display(updated_display) - self.RenderManager.update_display(updated_display) - self.mainDisplay.setup(updated_display) + + def screenChanged(self): + """ + The screen has changed to so tell the displays to update_display + their locations + """ + self.RenderManager.update_display() + self.displayManager.setup() + self.setFocus() self.activateWindow() def closeEvent(self, event): @@ -638,17 +646,14 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): QtGui.QMessageBox.Save) if ret == QtGui.QMessageBox.Save: self.ServiceManagerContents.onSaveService() - self.mainDisplay.close() self.cleanUp() event.accept() elif ret == QtGui.QMessageBox.Discard: - self.mainDisplay.close() self.cleanUp() event.accept() else: event.ignore() else: - self.mainDisplay.close() self.cleanUp() event.accept() @@ -661,10 +666,12 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): # Call the cleanup method to shutdown plugins. log.info(u'cleanup plugins') self.plugin_manager.finalise_plugins() + #Close down the displays + self.displayManager.close() def serviceChanged(self, reset=False, serviceName=None): """ - Hook to change the main window title when the service changes + Hook to change the main window title when the service chmainwindow.pyanges ``reset`` Shows if the service has been cleared or saved @@ -684,6 +691,9 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): title = u'%s - %s*' % (self.mainTitle, service_name) self.setWindowTitle(title) + def showStatusMessage(self, message): + self.StatusBar.showMessage(message) + def defaultThemeChanged(self, theme): self.DefaultThemeLabel.setText( u'%s %s' % (self.defaultThemeText, theme)) diff --git a/openlp/core/ui/mediadockmanager.py b/openlp/core/ui/mediadockmanager.py index 0873133b2..574b181da 100644 --- a/openlp/core/ui/mediadockmanager.py +++ b/openlp/core/ui/mediadockmanager.py @@ -6,15 +6,15 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 MERCHANdockILITY or # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # # more details. # # # diff --git a/openlp/core/ui/plugindialog.py b/openlp/core/ui/plugindialog.py index a20e669cc..f4a1773c9 100644 --- a/openlp/core/ui/plugindialog.py +++ b/openlp/core/ui/plugindialog.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -105,4 +105,4 @@ class Ui_PluginViewDialog(object): self.AboutLabel.setText(self.trUtf8('About:')) self.StatusLabel.setText(self.trUtf8('Status:')) self.StatusComboBox.setItemText(0, self.trUtf8('Active')) - self.StatusComboBox.setItemText(1, self.trUtf8('Inactive')) \ No newline at end of file + self.StatusComboBox.setItemText(1, self.trUtf8('Inactive')) diff --git a/openlp/core/ui/pluginform.py b/openlp/core/ui/pluginform.py index 9af8b7ca3..9969ed165 100644 --- a/openlp/core/ui/pluginform.py +++ b/openlp/core/ui/pluginform.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/core/ui/screen.py b/openlp/core/ui/screen.py index b85b3b003..32cc5ba50 100644 --- a/openlp/core/ui/screen.py +++ b/openlp/core/ui/screen.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -22,6 +22,7 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### + import logging log = logging.getLogger(__name__) @@ -36,14 +37,17 @@ class ScreenList(object): self.preview = None self.current = None self.screen_list = [] - self.count = 0 + self.display_count = 0 + #actual display number self.current_display = 0 + #save config display number + self.monitor_number = 0 def add_screen(self, screen): if screen[u'primary']: self.current = screen self.screen_list.append(screen) - self.count += 1 + self.display_count += 1 def screen_exists(self, number): for screen in self.screen_list: @@ -52,21 +56,15 @@ class ScreenList(object): return False def set_current_display(self, number): - if number + 1 > self.count: + """ + Set up the current screen dimensions + """ + if number + 1 > self.display_count: self.current = self.screen_list[0] self.current_display = 0 else: self.current = self.screen_list[number] self.preview = self.current self.current_display = number - if self.count == 1: + if self.display_count == 1: self.preview = self.screen_list[0] - -# if self.screen[u'number'] != screenNumber: -# # We will most probably never actually hit this bit, but just in -# # case the index in the list doesn't match the screen number, we -# # search for it. -# for scrn in self.screens: -# if scrn[u'number'] == screenNumber: -# self.screen = scrn -# break diff --git a/openlp/core/ui/serviceitemeditdialog.py b/openlp/core/ui/serviceitemeditdialog.py new file mode 100644 index 000000000..fbaa52ca1 --- /dev/null +++ b/openlp/core/ui/serviceitemeditdialog.py @@ -0,0 +1,73 @@ +# -*- 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 PyQt4 import QtCore, QtGui + +class Ui_ServiceItemEditDialog(object): + def setupUi(self, ServiceItemEditDialog): + ServiceItemEditDialog.setObjectName(u'ServiceItemEditDialog') + ServiceItemEditDialog.resize(386, 272) + self.layoutWidget = QtGui.QWidget(ServiceItemEditDialog) + self.layoutWidget.setGeometry(QtCore.QRect(20, 20, 351, 241)) + self.layoutWidget.setObjectName(u'layoutWidget') + self.outerLayout = QtGui.QVBoxLayout(self.layoutWidget) + self.outerLayout.setObjectName(u'outerLayout') + self.topLayout = QtGui.QHBoxLayout() + self.topLayout.setObjectName(u'topLayout') + self.listWidget = QtGui.QListWidget(self.layoutWidget) + self.listWidget.setAlternatingRowColors(True) + self.listWidget.setObjectName(u'listWidget') + self.topLayout.addWidget(self.listWidget) + self.buttonLayout = QtGui.QVBoxLayout() + self.buttonLayout.setObjectName(u'buttonLayout') + self.upButton = QtGui.QPushButton(self.layoutWidget) + self.upButton.setObjectName(u'upButton') + self.buttonLayout.addWidget(self.upButton) + spacerItem = QtGui.QSpacerItem(20, 40, + QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.buttonLayout.addItem(spacerItem) + self.deleteButton = QtGui.QPushButton(self.layoutWidget) + self.deleteButton.setObjectName(u'deleteButton') + self.buttonLayout.addWidget(self.deleteButton) + self.downButton = QtGui.QPushButton(self.layoutWidget) + self.downButton.setObjectName(u'downButton') + self.buttonLayout.addWidget(self.downButton) + self.topLayout.addLayout(self.buttonLayout) + self.outerLayout.addLayout(self.topLayout) + self.buttonBox = QtGui.QDialogButtonBox(self.layoutWidget) + self.buttonBox.setStandardButtons( + QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Save) + self.buttonBox.setObjectName(u'buttonBox') + self.outerLayout.addWidget(self.buttonBox) + + self.retranslateUi(ServiceItemEditDialog) + QtCore.QMetaObject.connectSlotsByName(ServiceItemEditDialog) + + def retranslateUi(self, ServiceItemEditDialog): + ServiceItemEditDialog.setWindowTitle(self.trUtf8('Service Item Maintenance')) + self.upButton.setText(self.trUtf8('Up')) + self.deleteButton.setText(self.trUtf8('Delete')) + self.downButton.setText(self.trUtf8('Down')) + diff --git a/openlp/core/ui/serviceitemeditform.py b/openlp/core/ui/serviceitemeditform.py new file mode 100644 index 000000000..9df8088c8 --- /dev/null +++ b/openlp/core/ui/serviceitemeditform.py @@ -0,0 +1,116 @@ +# -*- 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 PyQt4 import QtCore, QtGui +from serviceitemeditdialog import Ui_ServiceItemEditDialog + +class ServiceItemEditForm(QtGui.QDialog, Ui_ServiceItemEditDialog): + """ + This is the form that is used to edit the verses of the song. + """ + def __init__(self, parent=None): + """ + Constructor + """ + QtGui.QDialog.__init__(self, parent) + self.setupUi(self) + self.itemList = [] + # enable drop + QtCore.QObject.connect(self.upButton, + QtCore.SIGNAL(u'clicked()'), + self.onItemUp) + QtCore.QObject.connect(self.downButton, + QtCore.SIGNAL(u'clicked()'), + self.onItemDown) + QtCore.QObject.connect(self.deleteButton, + QtCore.SIGNAL(u'clicked()'), + self.onItemDelete) + QtCore.QObject.connect(self.buttonBox, + QtCore.SIGNAL(u'accepted()'), + self.accept) + QtCore.QObject.connect(self.buttonBox, + QtCore.SIGNAL(u'rejected()'), + self.reject) + + def setServiceItem(self, item): + self.item = item + self.itemList = [] + if self.item.is_image(): + self.data = True + for frame in self.item._raw_frames: + self.itemList.append(frame) + self.loadData() + + def getServiceItem(self): + if self.data: + self.item._raw_frames = [] + if self.item.is_image(): + for item in self.itemList: + self.item.add_from_image(item[u'path'], + item[u'title'], item[u'image']) + self.item.render() + return self.item + + def loadData(self): + self.listWidget.clear() + for frame in self.itemList: + item_name = QtGui.QListWidgetItem(frame[u'title']) + self.listWidget.addItem(item_name) + + def onItemDelete(self): + """ + Delete the selected row + """ + items = self.listWidget.selectedItems() + for item in items: + row = self.listWidget.row(item) + self.itemList.remove(self.itemList[row]) + self.loadData() + + def onItemUp(self): + """ + Move the selected row up in the list + """ + items = self.listWidget.selectedItems() + for item in items: + row = self.listWidget.row(item) + if row > 0: + temp = self.itemList[row] + self.itemList.remove(self.itemList[row]) + self.itemList.insert(row - 1, temp) + self.loadData() + + def onItemDown(self): + """ + Move the selected row down in the list + """ + items = self.listWidget.selectedItems() + for item in items: + row = self.listWidget.row(item) + if row < len(self.itemList) and row is not -1: + temp = self.itemList[row] + self.itemList.remove(self.itemList[row]) + self.itemList.insert(row + 1, temp) + self.loadData() diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index a0a198f2d..27ca95d0e 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -33,8 +33,8 @@ log = logging.getLogger(__name__) from PyQt4 import QtCore, QtGui from openlp.core.lib import PluginConfig, OpenLPToolbar, ServiceItem, \ - contextMenuAction, Receiver, str_to_bool, build_icon -from openlp.core.ui import ServiceItemNoteForm + contextMenuAction, Receiver, str_to_bool, build_icon, ItemCapabilities +from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm class ServiceManagerList(QtGui.QTreeWidget): @@ -100,12 +100,14 @@ class ServiceManager(QtGui.QWidget): self.parent = parent self.serviceItems = [] self.serviceName = u'' + self.droppos = 0 #is a new service and has not been saved self.isNew = True #Indicates if remoteTriggering is active. If it is the next addServiceItem call #will replace the currently selected one. self.remoteEditTriggered = False - self.serviceItemNoteForm = ServiceItemNoteForm() + self.serviceNoteForm = ServiceNoteForm() + self.serviceItemEditForm = ServiceItemEditForm() #start with the layout self.Layout = QtGui.QVBoxLayout(self) self.Layout.setSpacing(0) @@ -113,13 +115,13 @@ class ServiceManager(QtGui.QWidget): # Create the top toolbar self.Toolbar = OpenLPToolbar(self) self.Toolbar.addToolbarButton( - self.trUtf8('New Service'), u':/services/service_new.png', + self.trUtf8('New Service'), u':/general/general_new.png', self.trUtf8('Create a new service'), self.onNewService) self.Toolbar.addToolbarButton( - self.trUtf8('Open Service'), u':/services/service_open.png', + self.trUtf8('Open Service'), u':/general/general_open.png', self.trUtf8('Load an existing service'), self.onLoadService) self.Toolbar.addToolbarButton( - self.trUtf8('Save Service'), u':/services/service_save.png', + self.trUtf8('Save Service'), u':/general/general_save.png', self.trUtf8('Save this service'), self.onSaveService) self.Toolbar.addSeparator() self.ThemeLabel = QtGui.QLabel(self.trUtf8('Theme:'), @@ -147,7 +149,8 @@ class ServiceManager(QtGui.QWidget): self.ServiceManagerList.setHeaderHidden(True) self.ServiceManagerList.setExpandsOnDoubleClick(False) self.ServiceManagerList.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) - self.ServiceManagerList.customContextMenuRequested.connect(self.contextMenu) + QtCore.QObject.connect(self.ServiceManagerList, + QtCore.SIGNAL('customContextMenuRequested(QPoint)'), self.contextMenu) self.ServiceManagerList.setObjectName(u'ServiceManagerList') # enable drop self.ServiceManagerList.__class__.dragEnterEvent = self.dragEnterEvent @@ -170,7 +173,7 @@ class ServiceManager(QtGui.QWidget): self.trUtf8('Move to end'), self.onServiceEnd) self.OrderToolbar.addSeparator() self.OrderToolbar.addToolbarButton( - self.trUtf8('&Delete From Service'), u':/services/service_delete.png', + self.trUtf8('&Delete From Service'), u':/general/general_delete.png', self.trUtf8('Delete From Service'), self.onDeleteFromService) self.Layout.addWidget(self.OrderToolbar) # Connect up our signals and slots @@ -190,6 +193,8 @@ class ServiceManager(QtGui.QWidget): QtCore.SIGNAL(u'presentation types'), self.onPresentationTypes) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'servicemanager_next_item'), self.nextItem) + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'config_updated'), self.regenerateServiceItems) # Last little bits of setting up self.config = PluginConfig(u'ServiceManager') self.servicePath = self.config.get_data_path() @@ -198,17 +203,19 @@ class ServiceManager(QtGui.QWidget): #build the context menu self.menu = QtGui.QMenu() self.editAction = self.menu.addAction(self.trUtf8('&Edit Item')) - self.editAction.setIcon(build_icon(u':/services/service_edit.png')) + self.editAction.setIcon(build_icon(u':/general/general_edit.png')) + self.maintainAction = self.menu.addAction(self.trUtf8('&Maintain Item')) + self.editAction.setIcon(build_icon(u':/general/general_edit.png')) self.notesAction = self.menu.addAction(self.trUtf8('&Notes')) self.notesAction.setIcon(build_icon(u':/services/service_notes.png')) self.deleteAction = self.menu.addAction(self.trUtf8('&Delete From Service')) - self.deleteAction.setIcon(build_icon(u':/services/service_delete.png')) + self.deleteAction.setIcon(build_icon(u':/general/general_delete.png')) self.sep1 = self.menu.addAction(u'') self.sep1.setSeparator(True) self.previewAction = self.menu.addAction(self.trUtf8('&Preview Verse')) - self.previewAction.setIcon(build_icon(u':/system/system_preview.png')) + self.previewAction.setIcon(build_icon(u':/general/general_preview.png')) self.liveAction = self.menu.addAction(self.trUtf8('&Live Verse')) - self.liveAction.setIcon(build_icon(u':/system/system_live.png')) + self.liveAction.setIcon(build_icon(u':/general/general_live.png')) self.sep2 = self.menu.addAction(u'') self.sep2.setSeparator(True) self.themeMenu = QtGui.QMenu(self.trUtf8(u'&Change Item Theme')) @@ -216,15 +223,21 @@ class ServiceManager(QtGui.QWidget): def contextMenu(self, point): item = self.ServiceManagerList.itemAt(point) + if item is None: + return if item.parent() is None: pos = item.data(0, QtCore.Qt.UserRole).toInt()[0] else: pos = item.parent().data(0, QtCore.Qt.UserRole).toInt()[0] serviceItem = self.serviceItems[pos - 1] self.editAction.setVisible(False) + self.maintainAction.setVisible(False) self.notesAction.setVisible(False) - if serviceItem[u'service_item'].edit_enabled: + if serviceItem[u'service_item'].is_capable(ItemCapabilities.AllowsEdit): self.editAction.setVisible(True) + if serviceItem[u'service_item']\ + .is_capable(ItemCapabilities.AllowsMaintain): + self.maintainAction.setVisible(True) if item.parent() is None: self.notesAction.setVisible(True) self.themeMenu.menuAction().setVisible(False) @@ -233,6 +246,8 @@ class ServiceManager(QtGui.QWidget): action = self.menu.exec_(self.ServiceManagerList.mapToGlobal(point)) if action == self.editAction: self.remoteEdit() + if action == self.maintainAction: + self.onServiceItemEditForm() if action == self.deleteAction: self.onDeleteFromService() if action == self.notesAction: @@ -247,11 +262,20 @@ class ServiceManager(QtGui.QWidget): def onServiceItemNoteForm(self): item, count = self.findServiceItem() - self.serviceItemNoteForm.textEdit.setPlainText( + self.serviceNoteForm.textEdit.setPlainText( self.serviceItems[item][u'service_item'].notes) - if self.serviceItemNoteForm.exec_(): + if self.serviceNoteForm.exec_(): self.serviceItems[item][u'service_item'].notes = \ - self.serviceItemNoteForm.textEdit.toPlainText() + self.serviceNoteForm.textEdit.toPlainText() + self.repaintServiceList(item, 0) + + def onServiceItemEditForm(self): + item, count = self.findServiceItem() + self.serviceItemEditForm.setServiceItem( + self.serviceItems[item][u'service_item']) + if self.serviceItemEditForm.exec_(): + self.serviceItems[item][u'service_item'] = \ + self.serviceItemEditForm.getServiceItem() self.repaintServiceList(item, 0) def nextItem(self): @@ -348,7 +372,7 @@ class ServiceManager(QtGui.QWidget): def onServiceUp(self): """ Move the current ServiceItem up in the list - Note move up means move to top of area ie 0. + Note move up means move to top of area ie 0. """ item, count = self.findServiceItem() if item > 0: @@ -472,7 +496,8 @@ class ServiceManager(QtGui.QWidget): log.debug(u'onSaveService') if not quick or self.isNew: filename = QtGui.QFileDialog.getSaveFileName(self, - u'Save Service', self.config.get_last_dir()) + self.trUtf8(u'Save Service'), self.config.get_last_dir(), + self.trUtf8(u'OpenLP Service Files (*.osz)')) else: filename = self.config.get_last_dir() if filename: @@ -493,7 +518,7 @@ class ServiceManager(QtGui.QWidget): if item[u'service_item'].uses_file(): for frame in item[u'service_item'].get_frames(): path_from = unicode(os.path.join( - item[u'service_item'].service_item_path, + frame[u'path'], frame[u'title'])) zip.write(path_from) file = open(servicefile, u'wb') @@ -511,9 +536,9 @@ class ServiceManager(QtGui.QWidget): os.remove(servicefile) except: pass #if not present do not worry - name = filename.split(os.path.sep) - self.serviceName = name[-1] - self.parent.serviceChanged(True, self.serviceName) + name = filename.split(os.path.sep) + self.serviceName = name[-1] + self.parent.serviceChanged(True, self.serviceName) def onQuickSaveService(self): self.onSaveService(True) @@ -615,7 +640,7 @@ class ServiceManager(QtGui.QWidget): for item in tempServiceItems: self.addServiceItem(item[u'service_item'], False, item[u'expanded']) #Set to False as items may have changed rendering - #does not impact the saved song so True may aslo be valid + #does not impact the saved song so True may also be valid self.parent.serviceChanged(False, self.serviceName) def addServiceItem(self, item, rebuild=False, expand=True): @@ -635,19 +660,27 @@ class ServiceManager(QtGui.QWidget): self.repaintServiceList(sitem + 1, 0) self.parent.LiveController.replaceServiceManagerItem(item) else: - if sitem == -1: - self.serviceItems.append({u'service_item': item, - u'order': len(self.serviceItems) + 1, - u'expanded':expand}) + #nothing selected for dnd + if self.droppos == 0: + if isinstance(item, list): + for inditem in item: + self.serviceItems.append({u'service_item': inditem, + u'order': len(self.serviceItems) + 1, + u'expanded':expand}) + else: + self.serviceItems.append({u'service_item': item, + u'order': len(self.serviceItems) + 1, + u'expanded':expand}) self.repaintServiceList(len(self.serviceItems) + 1, 0) else: - self.serviceItems.insert(sitem + 1, {u'service_item': item, - u'order': len(self.serviceItems)+1, + self.serviceItems.insert(self.droppos, {u'service_item': item, + u'order': self.droppos, u'expanded':expand}) - self.repaintServiceList(sitem + 1, 0) + self.repaintServiceList(self.droppos, 0) #if rebuilding list make sure live is fixed. if rebuild: self.parent.LiveController.replaceServiceManagerItem(item) + self.droppos = 0 self.parent.serviceChanged(False, self.serviceName) def makePreview(self): @@ -658,6 +691,17 @@ class ServiceManager(QtGui.QWidget): self.parent.PreviewController.addServiceManagerItem( self.serviceItems[item][u'service_item'], count) + def getServiceItem(self): + """ + Send the current item to the Preview slide controller + """ + item, count = self.findServiceItem() + if item == -1: + return False + else: + #Switch on remote edit update functionality. + self.remoteEditTriggered = True + return self.serviceItems[item][u'service_item'] def makeLive(self): """ @@ -670,7 +714,7 @@ class ServiceManager(QtGui.QWidget): get_config(u'auto preview', u'False')): item += 1 if self.serviceItems and item < len(self.serviceItems) and \ - self.serviceItems[item][u'service_item'].autoPreviewAllowed: + self.serviceItems[item][u'service_item'].is_capable(ItemCapabilities.AllowsPreview): self.parent.PreviewController.addServiceManagerItem( self.serviceItems[item][u'service_item'], 0) @@ -679,7 +723,8 @@ class ServiceManager(QtGui.QWidget): Posts a remote edit message to a plugin to allow item to be edited. """ item, count = self.findServiceItem() - if self.serviceItems[item][u'service_item'].edit_enabled: + if self.serviceItems[item][u'service_item']\ + .is_capable(ItemCapabilities.AllowsEdit): self.remoteEditTriggered = True Receiver.send_message(u'%s_edit' % self.serviceItems[item][u'service_item'].name, u'L:%s' % @@ -728,18 +773,13 @@ class ServiceManager(QtGui.QWidget): link = event.mimeData() if link.hasText(): plugin = event.mimeData().text() + item = self.ServiceManagerList.itemAt(event.pos()) if plugin == u'ServiceManager': startpos, startCount = self.findServiceItem() - item = self.ServiceManagerList.itemAt(event.pos()) if item is None: endpos = len(self.serviceItems) else: - parentitem = item.parent() - if parentitem is None: - endpos = item.data(0, QtCore.Qt.UserRole).toInt()[0] - else: - endpos = parentitem.data(0, QtCore.Qt.UserRole).toInt()[0] - endpos -= 1 + endpos = self._getParentItemData(item) - 1 if endpos < startpos: newpos = endpos else: @@ -749,6 +789,10 @@ class ServiceManager(QtGui.QWidget): self.serviceItems.insert(newpos, serviceItem) self.repaintServiceList(endpos, startCount) else: + if item == None: + self.droppos = len(self.serviceItems) + else: + self.droppos = self._getParentItemData(item) Receiver.send_message(u'%s_add_service_item' % plugin) def updateThemeList(self, theme_list): @@ -783,3 +827,10 @@ class ServiceManager(QtGui.QWidget): item, count = self.findServiceItem() self.serviceItems[item][u'service_item'].theme = theme self.regenerateServiceItems() + + def _getParentItemData(self, item): + parentitem = item.parent() + if parentitem is None: + return item.data(0, QtCore.Qt.UserRole).toInt()[0] + else: + return parentitem.data(0, QtCore.Qt.UserRole).toInt()[0] diff --git a/openlp/core/ui/serviceitemdialog.py b/openlp/core/ui/servicenotedialog.py similarity index 95% rename from openlp/core/ui/serviceitemdialog.py rename to openlp/core/ui/servicenotedialog.py index 1fe86a913..e1d830c5e 100644 --- a/openlp/core/ui/serviceitemdialog.py +++ b/openlp/core/ui/servicenotedialog.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/core/ui/serviceitemform.py b/openlp/core/ui/servicenoteform.py similarity index 89% rename from openlp/core/ui/serviceitemform.py rename to openlp/core/ui/servicenoteform.py index 43011ead8..6dfdf0b03 100644 --- a/openlp/core/ui/serviceitemform.py +++ b/openlp/core/ui/servicenoteform.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -24,9 +24,9 @@ ############################################################################### from PyQt4 import QtCore, QtGui -from serviceitemdialog import Ui_ServiceNoteEdit +from servicenotedialog import Ui_ServiceNoteEdit -class ServiceItemNoteForm(QtGui.QDialog, Ui_ServiceNoteEdit): +class ServiceNoteForm(QtGui.QDialog, Ui_ServiceNoteEdit): """ This is the form that is used to edit the verses of the song. """ diff --git a/openlp/core/ui/settingsdialog.py b/openlp/core/ui/settingsdialog.py index 9ed843e60..7148b0478 100644 --- a/openlp/core/ui/settingsdialog.py +++ b/openlp/core/ui/settingsdialog.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -59,4 +59,4 @@ class Ui_SettingsDialog(object): QtCore.QMetaObject.connectSlotsByName(SettingsDialog) def retranslateUi(self, SettingsDialog): - SettingsDialog.setWindowTitle(self.trUtf8('Settings')) \ No newline at end of file + SettingsDialog.setWindowTitle(self.trUtf8('Settings')) diff --git a/openlp/core/ui/settingsform.py b/openlp/core/ui/settingsform.py index 4a3902347..c86525a54 100644 --- a/openlp/core/ui/settingsform.py +++ b/openlp/core/ui/settingsform.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -28,24 +28,23 @@ import logging from PyQt4 import QtGui from openlp.core.ui import GeneralTab, ThemesTab -from openlp.core.lib import Receiver from settingsdialog import Ui_SettingsDialog log = logging.getLogger(__name__) class SettingsForm(QtGui.QDialog, Ui_SettingsDialog): - def __init__(self, screen_list, mainWindow, parent=None): + def __init__(self, screens, mainWindow, parent=None): QtGui.QDialog.__init__(self, parent) self.setupUi(self) # General tab - self.GeneralTab = GeneralTab(screen_list) + self.GeneralTab = GeneralTab(screens) self.addTab(u'General', self.GeneralTab) # Themes tab self.ThemesTab = ThemesTab(mainWindow) self.addTab(u'Themes', self.ThemesTab) - def addTab(self, name, tab): + def addTab(self, name, tab): log.info(u'Adding %s tab' % tab.tabTitle) self.SettingsTabWidget.addTab(tab, tab.tabTitleVisible) @@ -65,7 +64,6 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog): def accept(self): for tab_index in range(0, self.SettingsTabWidget.count()): self.SettingsTabWidget.widget(tab_index).save() - Receiver.send_message(u'config_updated') return QtGui.QDialog.accept(self) def postSetUp(self): diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index e26df7a18..aae646f52 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -30,6 +30,17 @@ import os from PyQt4 import QtCore, QtGui from PyQt4.phonon import Phonon +from openlp.core.lib import ItemCapabilities + +class HideMode(object): + """ + This is basically an enumeration class which specifies the mode of a Bible. + Mode refers to whether or not a Bible in OpenLP is a full Bible or needs to + be downloaded from the Internet on an as-needed basis. + """ + Blank = 1 + Theme = 2 + from openlp.core.lib import OpenLPToolbar, Receiver, str_to_bool, \ PluginConfig, resize_image @@ -85,7 +96,7 @@ class SlideController(QtGui.QWidget): self.isLive = isLive self.parent = parent self.songsconfig = PluginConfig(u'Songs') - self.image_list = [ + self.loop_list = [ u'Start Loop', u'Stop Loop', u'Loop Separator', @@ -94,6 +105,10 @@ class SlideController(QtGui.QWidget): self.song_edit_list = [ u'Edit Song', ] + if isLive: + self.labelWidth = 20 + else: + self.labelWidth = 0 self.timer_id = 0 self.songEdit = False self.selectedRow = 0 @@ -133,12 +148,14 @@ class SlideController(QtGui.QWidget): self.ControllerLayout.setMargin(0) # Controller list view self.PreviewListWidget = SlideList(self) - self.PreviewListWidget.setColumnCount(1) + self.PreviewListWidget.setColumnCount(2) self.PreviewListWidget.horizontalHeader().setVisible(False) self.PreviewListWidget.verticalHeader().setVisible(False) - self.PreviewListWidget.setColumnWidth(1, self.Controller.width()) + self.PreviewListWidget.setColumnWidth(1, self.labelWidth) + self.PreviewListWidget.setColumnWidth(1, self.Controller.width() - self.labelWidth) self.PreviewListWidget.isLive = self.isLive self.PreviewListWidget.setObjectName(u'PreviewListWidget') + self.PreviewListWidget.setSelectionBehavior(1) self.PreviewListWidget.setEditTriggers( QtGui.QAbstractItemView.NoEditTriggers) self.PreviewListWidget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) @@ -170,18 +187,24 @@ class SlideController(QtGui.QWidget): if self.isLive: self.Toolbar.addToolbarSeparator(u'Close Separator') self.blankButton = self.Toolbar.addToolbarButton( - u'Blank Screen', u':/slides/slide_close.png', + u'Blank Screen', u':/slides/slide_blank.png', self.trUtf8('Blank Screen'), self.onBlankDisplay, True) + self.themeButton = self.Toolbar.addToolbarButton( + u'Display Theme', u':/slides/slide_theme.png', + self.trUtf8('Theme Screen'), self.onThemeDisplay, True) + self.hideButton = self.Toolbar.addToolbarButton( + u'Hide screen', u':/slides/slide_desktop.png', + self.trUtf8('Hide Screen'), self.onHideDisplay, True) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'live_slide_blank'), self.blankScreen) if not self.isLive: self.Toolbar.addToolbarSeparator(u'Close Separator') self.Toolbar.addToolbarButton( - u'Go Live', u':/system/system_live.png', + u'Go Live', u':/general/general_live.png', self.trUtf8('Move to live'), self.onGoLive) self.Toolbar.addToolbarSeparator(u'Close Separator') self.Toolbar.addToolbarButton( - u'Edit Song', u':/services/service_edit.png', + u'Edit Song', u':/general/general_edit.png', self.trUtf8('Edit and re-preview Song'), self.onEditSong) if isLive: self.Toolbar.addToolbarSeparator(u'Loop Separator') @@ -210,6 +233,12 @@ class SlideController(QtGui.QWidget): self.Mediabar.addToolbarButton( u'Media Stop', u':/slides/media_playback_stop.png', self.trUtf8('Start playing media'), self.onMediaStop) + if not self.isLive: + self.seekSlider = Phonon.SeekSlider() + self.seekSlider.setGeometry(QtCore.QRect(90, 260, 221, 24)) + self.seekSlider.setObjectName(u'seekSlider') + self.Mediabar.addToolbarWidget( + u'Seek Slider', self.seekSlider) self.volumeSlider = Phonon.VolumeSlider() self.volumeSlider.setGeometry(QtCore.QRect(90, 260, 221, 24)) self.volumeSlider.setObjectName(u'volumeSlider') @@ -276,7 +305,7 @@ class SlideController(QtGui.QWidget): QtCore.SIGNAL(u'update_spin_delay'), self.receiveSpinDelay) Receiver.send_message(u'request_spin_delay') if isLive: - self.Toolbar.makeWidgetsInvisible(self.image_list) + self.Toolbar.makeWidgetsInvisible(self.loop_list) else: self.Toolbar.makeWidgetsInvisible(self.song_edit_list) self.Mediabar.setVisible(False) @@ -299,6 +328,8 @@ class SlideController(QtGui.QWidget): QtCore.SIGNAL(u'%s_change' % prefix), self.onSlideChange) QtCore.QObject.connect(self.Splitter, QtCore.SIGNAL(u'splitterMoved(int, int)'), self.trackSplitter) + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'config_updated'), self.refreshServiceItem) def widthChanged(self): """ @@ -307,7 +338,8 @@ class SlideController(QtGui.QWidget): """ width = self.parent.ControlSplitter.sizes()[self.split] height = width * self.parent.RenderManager.screen_ratio - self.PreviewListWidget.setColumnWidth(0, width) + self.PreviewListWidget.setColumnWidth(0, self.labelWidth) + self.PreviewListWidget.setColumnWidth(1, width - self.labelWidth) #Sort out image hights (Songs , bibles excluded) if self.serviceItem and not self.serviceItem.is_text(): for framenumber, frame in enumerate(self.serviceItem.get_frames()): @@ -348,20 +380,19 @@ class SlideController(QtGui.QWidget): self.Toolbar.setVisible(True) self.Mediabar.setVisible(False) self.Toolbar.makeWidgetsInvisible([u'Song Menu']) - self.Toolbar.makeWidgetsInvisible(self.image_list) + self.Toolbar.makeWidgetsInvisible(self.loop_list) if item.is_text(): - self.Toolbar.makeWidgetsInvisible(self.image_list) - if item.is_song() and \ - str_to_bool(self.songsconfig.get_config(u'show songbar', True)): + self.Toolbar.makeWidgetsInvisible(self.loop_list) + if str_to_bool(self.songsconfig.get_config(u'show songbar', True)) \ + and len(self.slideList) > 0: self.Toolbar.makeWidgetsVisible([u'Song Menu']) - elif item.is_image(): - #Not sensible to allow loops with 1 frame - if len(item.get_frames()) > 1: - self.Toolbar.makeWidgetsVisible(self.image_list) - elif item.is_media(): + if item.is_capable(ItemCapabilities.AllowsLoop) and \ + len(item.get_frames()) > 1: + self.Toolbar.makeWidgetsVisible(self.loop_list) + if item.is_media(): self.Toolbar.setVisible(False) self.Mediabar.setVisible(True) - self.volumeSlider.setAudioOutput(self.parent.mainDisplay.audio) + #self.volumeSlider.setAudioOutput(self.parent.mainDisplay.videoDisplay.audio) def enablePreviewToolBar(self, item): """ @@ -370,13 +401,24 @@ class SlideController(QtGui.QWidget): self.Toolbar.setVisible(True) self.Mediabar.setVisible(False) self.Toolbar.makeWidgetsInvisible(self.song_edit_list) - if item.edit_enabled and item.fromPlugin: + if item.is_capable(ItemCapabilities.AllowsEdit) and item.from_plugin: self.Toolbar.makeWidgetsVisible(self.song_edit_list) elif item.is_media(): self.Toolbar.setVisible(False) self.Mediabar.setVisible(True) self.volumeSlider.setAudioOutput(self.audio) + def refreshServiceItem(self): + """ + Method to update the service item if the screen has changed + """ + log.debug(u'refreshServiceItem') + if self.serviceItem: + if self.serviceItem.is_text() or self.serviceItem.is_image(): + item = self.serviceItem + item.render() + self.addServiceManagerItem(item, self.selectedRow) + def addServiceItem(self, item): """ Method to install the service item into the controller @@ -390,14 +432,14 @@ class SlideController(QtGui.QWidget): if self.songEdit: slideno = self.selectedRow self.songEdit = False - self.addServiceManagerItem(item, slideno) + self._processItem(item, slideno) def replaceServiceManagerItem(self, item): """ Replacement item following a remote edit """ if item.__eq__(self.serviceItem): - self.addServiceManagerItem(item, self.PreviewListWidget.currentRow()) + self._processItem(item, self.PreviewListWidget.currentRow()) def addServiceManagerItem(self, item, slideno): """ @@ -406,27 +448,32 @@ class SlideController(QtGui.QWidget): Called by ServiceManager """ log.debug(u'addServiceManagerItem') - #If old item was a command tell it to stop - if self.serviceItem and self.serviceItem.is_command(): - self.onMediaStop() - if item.is_media(): - self.onMediaStart(item) - elif item.is_command(): - if self.isLive: - blanked = self.blankButton.isChecked() - else: - blanked = False - Receiver.send_message(u'%s_start' % item.name.lower(), \ - [item.title, item.service_item_path, - item.get_frame_title(), slideno, self.isLive, blanked]) - self.displayServiceManagerItems(item, slideno) + #If service item is the same as the current on only change slide + if item.__eq__(self.serviceItem): + self.PreviewListWidget.selectRow(slideno) + self.onSlideSelected() + return + self._processItem(item, slideno) - def displayServiceManagerItems(self, serviceItem, slideno): + def _processItem(self, serviceItem, slideno): """ Loads a ServiceItem into the system from ServiceManager Display the slide number passed """ - log.debug(u'displayServiceManagerItems Start') + log.debug(u'processsManagerItem') + #If old item was a command tell it to stop + if self.serviceItem and self.serviceItem.is_command(): + self.onMediaStop() + if serviceItem.is_media(): + self.onMediaStart(serviceItem) + elif serviceItem.is_command(): + if self.isLive: + blanked = self.blankButton.isChecked() + else: + blanked = False + Receiver.send_message(u'%s_start' % serviceItem.name.lower(), \ + [serviceItem.title, serviceItem.get_frame_path(), + serviceItem.get_frame_title(), slideno, self.isLive, blanked]) self.slideList = {} width = self.parent.ControlSplitter.sizes()[self.split] #Set pointing cursor when we have somthing to point at @@ -435,12 +482,15 @@ class SlideController(QtGui.QWidget): self.serviceItem = serviceItem self.PreviewListWidget.clear() self.PreviewListWidget.setRowCount(0) - self.PreviewListWidget.setColumnWidth(0, width) + self.PreviewListWidget.setColumnWidth(0, self.labelWidth) + self.PreviewListWidget.setColumnWidth(1, width - self.labelWidth) if self.isLive: self.SongMenu.menu().clear() + row = 0 for framenumber, frame in enumerate(self.serviceItem.get_frames()): self.PreviewListWidget.setRowCount( self.PreviewListWidget.rowCount() + 1) + rowitem = QtGui.QTableWidgetItem() item = QtGui.QTableWidgetItem() slide_height = 0 #It is a based Text Render @@ -450,18 +500,21 @@ class SlideController(QtGui.QWidget): bits = frame[u'verseTag'].split(u':') tag = None #If verse handle verse number else tag only - if bits[0] == self.trUtf8('Verse'): - tag = u'%s%s' % (bits[0][0], bits[1][0:] ) - row = bits[1][0:] + if bits[0] == self.trUtf8('Verse') or \ + bits[0] == self.trUtf8('Chorus'): + tag = u'%s\n%s' % (bits[0][0], bits[1][0:] ) + tag1 = u'%s%s' % (bits[0][0], bits[1][0:] ) + row = tag else: tag = bits[0] + tag1 = tag row = bits[0][0:1] - try: - test = self.slideList[tag] - except: - self.slideList[tag] = framenumber - self.SongMenu.menu().addAction(self.trUtf8(u'%s'%tag), + if tag1 not in self.slideList: + self.slideList[tag1] = framenumber + self.SongMenu.menu().addAction(self.trUtf8(u'%s'%tag1), self.onSongBarHandler) + else: + row += 1 item.setText(frame[u'text']) else: label = QtGui.QLabel() @@ -471,15 +524,20 @@ class SlideController(QtGui.QWidget): self.parent.RenderManager.height) label.setScaledContents(True) label.setPixmap(QtGui.QPixmap.fromImage(pixmap)) - self.PreviewListWidget.setCellWidget(framenumber, 0, label) + self.PreviewListWidget.setCellWidget(framenumber, 1, label) slide_height = width * self.parent.RenderManager.screen_ratio - self.PreviewListWidget.setItem(framenumber, 0, item) + row += 1 + rowitem.setText(unicode(row)) + rowitem.setTextAlignment(QtCore.Qt.AlignVCenter) + self.PreviewListWidget.setItem(framenumber, 0, rowitem) + self.PreviewListWidget.setItem(framenumber, 1, item) if slide_height != 0: self.PreviewListWidget.setRowHeight(framenumber, slide_height) if self.serviceItem.is_text(): self.PreviewListWidget.resizeRowsToContents() - self.PreviewListWidget.setColumnWidth( - 0, self.PreviewListWidget.viewport().size().width()) + self.PreviewListWidget.setColumnWidth(0, self.labelWidth) + self.PreviewListWidget.setColumnWidth(1, + self.PreviewListWidget.viewport().size().width() - self.labelWidth ) if slideno > self.PreviewListWidget.rowCount(): self.PreviewListWidget.selectRow(self.PreviewListWidget.rowCount()) else: @@ -490,7 +548,6 @@ class SlideController(QtGui.QWidget): log.log(15, u'Display Rendering took %4s' % (time.time() - before)) if self.isLive: self.serviceItem.request_audit() - log.debug(u'displayServiceManagerItems End') #Screen event methods def onSlideSelectedFirst(self): @@ -511,13 +568,35 @@ class SlideController(QtGui.QWidget): """ Handle the blank screen button """ + log.debug(u'onBlankDisplay %d' % force) if force: self.blankButton.setChecked(True) - self.blankScreen(self.blankButton.isChecked()) + self.blankScreen(HideMode.Blank, self.blankButton.isChecked()) self.parent.generalConfig.set_config(u'screen blank', self.blankButton.isChecked()) - def blankScreen(self, blanked=False): + def onThemeDisplay(self, force=False): + """ + Handle the Theme screen button + """ + log.debug(u'onThemeDisplay %d' % force) + if force: + self.themeButton.setChecked(True) + self.blankScreen(HideMode.Theme, self.themeButton.isChecked()) + + def onHideDisplay(self, force=False): + """ + Handle the Hide screen button + """ + log.debug(u'onHideDisplay %d' % force) + if force: + self.hideButton.setChecked(True) + if self.hideButton.isChecked(): + self.parent.mainDisplay.hideDisplay() + else: + self.parent.mainDisplay.showDisplay() + + def blankScreen(self, blankType, blanked=False): """ Blank the display screen. """ @@ -527,8 +606,10 @@ class SlideController(QtGui.QWidget): Receiver.send_message(u'%s_blank'% self.serviceItem.name.lower()) else: Receiver.send_message(u'%s_unblank'% self.serviceItem.name.lower()) + else: + self.parent.mainDisplay.blankDisplay(blankType, blanked) else: - self.parent.mainDisplay.blankDisplay(blanked) + self.parent.mainDisplay.blankDisplay(blankType, blanked) def onSlideSelected(self): """ @@ -554,7 +635,7 @@ class SlideController(QtGui.QWidget): self.SlidePreview.setPixmap(QtGui.QPixmap.fromImage(frame[u'main'])) log.log(15, u'Slide Rendering took %4s' % (time.time() - before)) if self.isLive: - self.parent.mainDisplay.frameView(frame, True) + self.parent.displayManager.mainDisplay.frameView(frame, True) self.selectedRow = row def onSlideChange(self, row): @@ -572,7 +653,7 @@ class SlideController(QtGui.QWidget): QtCore.QTimer.singleShot(2.5, self.grabMainDisplay) else: label = self.PreviewListWidget.cellWidget( - self.PreviewListWidget.currentRow(), 0) + self.PreviewListWidget.currentRow(), 1) self.SlidePreview.setPixmap(label.pixmap()) def grabMainDisplay(self): @@ -641,7 +722,8 @@ class SlideController(QtGui.QWidget): self.serviceItem.name.lower(), self.isLive) self.updatePreview() else: - self.PreviewListWidget.selectRow(self.PreviewListWidget.rowCount() - 1) + self.PreviewListWidget.selectRow( + self.PreviewListWidget.rowCount() - 1) self.onSlideSelected() def onStartLoop(self): @@ -682,13 +764,15 @@ class SlideController(QtGui.QWidget): def onMediaStart(self, item): if self.isLive: Receiver.send_message(u'%s_start' % item.name.lower(), \ - [item.title, item.service_item_path, + [item.title, item.get_frame_path(), item.get_frame_title(), self.isLive, self.blankButton.isChecked()]) else: self.mediaObject.stop() self.mediaObject.clearQueue() - file = os.path.join(item.service_item_path, item.get_frame_title()) + file = os.path.join(item.get_frame_path(), item.get_frame_title()) self.mediaObject.setCurrentSource(Phonon.MediaSource(file)) + self.seekSlider.setMediaObject(self.mediaObject) + self.seekSlider.show() self.onMediaPlay() def onMediaPause(self): diff --git a/openlp/core/ui/splashscreen.py b/openlp/core/ui/splashscreen.py index 69ef7910d..10cea5a11 100644 --- a/openlp/core/ui/splashscreen.py +++ b/openlp/core/ui/splashscreen.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -67,4 +67,4 @@ class SplashScreen(object): self.splash_screen.repaint() def finish(self, widget): - self.splash_screen.finish(widget) \ No newline at end of file + self.splash_screen.finish(widget) diff --git a/openlp/core/ui/test/test_service_manager.py b/openlp/core/ui/test/test_service_manager.py deleted file mode 100644 index a23819383..000000000 --- a/openlp/core/ui/test/test_service_manager.py +++ /dev/null @@ -1,153 +0,0 @@ -""" -OpenLP - Open Source Lyrics Projection -Copyright (c) 2008 Raoul Snyman -Portions copyright (c) 2008 Martin Thompson, Tim Bentley - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free Software -Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place, Suite 330, Boston, MA 02111-1307 USA -""" - -import sys -import os -import os.path -import logging - -from PyQt4 import QtGui - -from openlp.core.ui import ServiceManager -from openlp.plugins.images.lib import ImageServiceItem - -mypath = os.path.split(os.path.abspath(__file__))[0] -sys.path.insert(0, (os.path.join(mypath, '..', '..', '..', '..'))) - -logging.basicConfig(filename='test_service_manager.log', level=logging.INFO, - filemode='w') - -# # from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66062 -# def whoami(depth=1): -# return sys._getframe(depth).f_code.co_name -global app -global log -log = logging.getLogger(u'TestServiceManager') - -class TestServiceManager_base: - def __init__(self): - pass - - def setup_class(self): - log.info( "class setup" + unicode(self)) - try: - if app is None: - app = QtGui.QApplication([]) - except UnboundLocalError: - app = QtGui.QApplication([]) - - def teardown_class(self): - pass - - def setup_method(self, method): - log.info(u'Setup method:' + unicode(method)) - self.expected_answer = "Don't know yet" - self.answer = None - self.s = ServiceManager(None) - log.info(u'--------------- Setup Done -------------') - - def teardown_method(self, method): - self.s = None - - def select_row(self, row): - # now select the line we just added - # first get the index - i = QModelIndex(self.s.service_data.index(0,0)) - # make a selection of it - self.sm = QItemSelectionModel(self.s.service_data) - self.sm.select(i, QItemSelectionModel.ClearAndSelect) - log.info(unicode(self.sm.selectedIndexes())) - self.s.TreeView.setSelectionModel(self.sm) - log.info(u'Selected indexes = ' + unicode( - self.s.TreeView.selectedIndexes())) - - def test_easy(self): - log.info(u'test_easy') - item = ImageServiceItem(None) - item.add(u'test.gif') - self.s.addServiceItem(item) - answer = self.s.service_as_text() - log.info(u'Answer = ' + unicode(answer)) - lines = answer.split(u'\n') - log.info(u'lines = ' + unicode(lines)) - assert lines[0].startswith(u'# Alerts Plugin
This plugin ' diff --git a/openlp/plugins/alerts/forms/__init__.py b/openlp/plugins/alerts/forms/__init__.py index 14c30d73b..2ef91059f 100644 --- a/openlp/plugins/alerts/forms/__init__.py +++ b/openlp/plugins/alerts/forms/__init__.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -25,4 +25,3 @@ from alertstab import AlertsTab from alertform import AlertForm -from alerteditform import AlertEditForm diff --git a/openlp/plugins/alerts/forms/alertdialog.py b/openlp/plugins/alerts/forms/alertdialog.py index 53fc1fff5..804975ff1 100644 --- a/openlp/plugins/alerts/forms/alertdialog.py +++ b/openlp/plugins/alerts/forms/alertdialog.py @@ -1,71 +1,134 @@ # -*- coding: utf-8 -*- -# Form implementation generated from reading ui file 'alertform.ui' +# Form implementation generated from reading ui file 'alertdialog.ui' # -# Created: Sat Feb 13 08:19:51 2010 -# by: PyQt4 UI code generator 4.6.2 +# Created: Sat Apr 17 08:07:40 2010 +# by: PyQt4 UI code generator 4.7 # # WARNING! All changes made in this file will be lost! from PyQt4 import QtCore, QtGui class Ui_AlertDialog(object): - def setupUi(self, AlertForm): - AlertForm.setObjectName(u'AlertDialog') - AlertForm.resize(430, 320) + def setupUi(self, AlertDialog): + AlertDialog.setObjectName("AlertDialog") + AlertDialog.resize(567, 440) icon = QtGui.QIcon() - icon.addPixmap(QtGui.QPixmap(u':/icon/openlp.org-icon-32.bmp'), QtGui.QIcon.Normal, QtGui.QIcon.Off) - AlertForm.setWindowIcon(icon) - self.AlertFormLayout = QtGui.QVBoxLayout(AlertForm) + icon.addPixmap(QtGui.QPixmap(":/icon/openlp.org-icon-32.bmp"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + AlertDialog.setWindowIcon(icon) + self.AlertFormLayout = QtGui.QVBoxLayout(AlertDialog) self.AlertFormLayout.setSpacing(8) self.AlertFormLayout.setMargin(8) - self.AlertFormLayout.setObjectName(u'AlertFormLayout') - self.AlertEntryWidget = QtGui.QWidget(AlertForm) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.AlertEntryWidget.sizePolicy().hasHeightForWidth()) - self.AlertEntryWidget.setSizePolicy(sizePolicy) - self.AlertEntryWidget.setObjectName(u'AlertEntryWidget') - self.verticalLayout_2 = QtGui.QVBoxLayout(self.AlertEntryWidget) - self.verticalLayout_2.setObjectName(u'verticalLayout_2') - self.verticalLayout = QtGui.QVBoxLayout() - self.verticalLayout.setObjectName(u'verticalLayout') - self.AlertEntryLabel = QtGui.QLabel(self.AlertEntryWidget) + self.AlertFormLayout.setObjectName("AlertFormLayout") + self.AlertTextLayout = QtGui.QFormLayout() + self.AlertTextLayout.setContentsMargins(0, 0, -1, -1) + self.AlertTextLayout.setSpacing(8) + self.AlertTextLayout.setObjectName("AlertTextLayout") + self.AlertEntryLabel = QtGui.QLabel(AlertDialog) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.AlertEntryLabel.sizePolicy().hasHeightForWidth()) self.AlertEntryLabel.setSizePolicy(sizePolicy) - self.AlertEntryLabel.setObjectName(u'AlertEntryLabel') - self.verticalLayout.addWidget(self.AlertEntryLabel) - self.AlertEntryEditItem = QtGui.QLineEdit(self.AlertEntryWidget) - self.AlertEntryEditItem.setObjectName(u'AlertEntryEditItem') - self.verticalLayout.addWidget(self.AlertEntryEditItem) - self.AlertListWidget = QtGui.QListWidget(self.AlertEntryWidget) + self.AlertEntryLabel.setObjectName("AlertEntryLabel") + self.AlertTextLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.AlertEntryLabel) + self.AlertParameter = QtGui.QLabel(AlertDialog) + self.AlertParameter.setObjectName("AlertParameter") + self.AlertTextLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.AlertParameter) + self.ParameterEdit = QtGui.QLineEdit(AlertDialog) + self.ParameterEdit.setObjectName("ParameterEdit") + self.AlertTextLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.ParameterEdit) + self.AlertTextEdit = QtGui.QLineEdit(AlertDialog) + self.AlertTextEdit.setObjectName("AlertTextEdit") + self.AlertTextLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.AlertTextEdit) + self.AlertFormLayout.addLayout(self.AlertTextLayout) + self.ManagementLayout = QtGui.QHBoxLayout() + self.ManagementLayout.setSpacing(8) + self.ManagementLayout.setContentsMargins(-1, -1, -1, 0) + self.ManagementLayout.setObjectName("ManagementLayout") + self.AlertListWidget = QtGui.QListWidget(AlertDialog) self.AlertListWidget.setAlternatingRowColors(True) - self.AlertListWidget.setObjectName(u'AlertListWidget') - self.verticalLayout.addWidget(self.AlertListWidget) - self.verticalLayout_2.addLayout(self.verticalLayout) - self.horizontalLayout = QtGui.QHBoxLayout() - self.horizontalLayout.setObjectName(u'horizontalLayout') - spacerItem = QtGui.QSpacerItem(181, 38, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout.addItem(spacerItem) - self.DisplayButton = QtGui.QPushButton(self.AlertEntryWidget) - self.DisplayButton.setObjectName(u'DisplayButton') - self.horizontalLayout.addWidget(self.DisplayButton) - self.CancelButton = QtGui.QPushButton(self.AlertEntryWidget) - self.CancelButton.setObjectName(u'CancelButton') - self.horizontalLayout.addWidget(self.CancelButton) - self.verticalLayout_2.addLayout(self.horizontalLayout) - self.AlertFormLayout.addWidget(self.AlertEntryWidget) + self.AlertListWidget.setObjectName("AlertListWidget") + self.ManagementLayout.addWidget(self.AlertListWidget) + self.ManageButtonLayout = QtGui.QVBoxLayout() + self.ManageButtonLayout.setSpacing(8) + self.ManageButtonLayout.setObjectName("ManageButtonLayout") + self.NewButton = QtGui.QPushButton(AlertDialog) + icon1 = QtGui.QIcon() + icon1.addPixmap(QtGui.QPixmap(":/general/general_new.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.NewButton.setIcon(icon1) + self.NewButton.setObjectName("NewButton") + self.ManageButtonLayout.addWidget(self.NewButton) + self.SaveButton = QtGui.QPushButton(AlertDialog) + self.SaveButton.setEnabled(False) + icon2 = QtGui.QIcon() + icon2.addPixmap(QtGui.QPixmap(":/general/general_save.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.SaveButton.setIcon(icon2) + self.SaveButton.setObjectName("SaveButton") + self.ManageButtonLayout.addWidget(self.SaveButton) + self.EditButton = QtGui.QPushButton(AlertDialog) + icon3 = QtGui.QIcon() + icon3.addPixmap(QtGui.QPixmap(":/general/general_edit.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.EditButton.setIcon(icon3) + self.EditButton.setObjectName("EditButton") + self.ManageButtonLayout.addWidget(self.EditButton) + self.DeleteButton = QtGui.QPushButton(AlertDialog) + icon4 = QtGui.QIcon() + icon4.addPixmap(QtGui.QPixmap(":/general/general_delete.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.DeleteButton.setIcon(icon4) + self.DeleteButton.setObjectName("DeleteButton") + self.ManageButtonLayout.addWidget(self.DeleteButton) + spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.ManageButtonLayout.addItem(spacerItem) + self.ManagementLayout.addLayout(self.ManageButtonLayout) + self.AlertFormLayout.addLayout(self.ManagementLayout) + self.AlertButtonLayout = QtGui.QHBoxLayout() + self.AlertButtonLayout.setSpacing(8) + self.AlertButtonLayout.setObjectName("AlertButtonLayout") + spacerItem1 = QtGui.QSpacerItem(181, 0, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.AlertButtonLayout.addItem(spacerItem1) + self.DisplayButton = QtGui.QPushButton(AlertDialog) + icon5 = QtGui.QIcon() + icon5.addPixmap(QtGui.QPixmap(":/general/general_live.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.DisplayButton.setIcon(icon5) + self.DisplayButton.setObjectName("DisplayButton") + self.AlertButtonLayout.addWidget(self.DisplayButton) + self.DisplayCloseButton = QtGui.QPushButton(AlertDialog) + self.DisplayCloseButton.setIcon(icon5) + self.DisplayCloseButton.setObjectName("DisplayCloseButton") + self.AlertButtonLayout.addWidget(self.DisplayCloseButton) + self.CloseButton = QtGui.QPushButton(AlertDialog) + icon6 = QtGui.QIcon() + icon6.addPixmap(QtGui.QPixmap(":/system/system_close.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.CloseButton.setIcon(icon6) + self.CloseButton.setObjectName("CloseButton") + self.AlertButtonLayout.addWidget(self.CloseButton) + self.AlertFormLayout.addLayout(self.AlertButtonLayout) + self.AlertEntryLabel.setBuddy(self.AlertTextEdit) + self.AlertParameter.setBuddy(self.ParameterEdit) - self.retranslateUi(AlertForm) - QtCore.QObject.connect(self.CancelButton, QtCore.SIGNAL(u'clicked()'), self.close) - QtCore.QMetaObject.connectSlotsByName(AlertForm) + self.retranslateUi(AlertDialog) + QtCore.QObject.connect(self.CloseButton, QtCore.SIGNAL("clicked()"), AlertDialog.close) + QtCore.QMetaObject.connectSlotsByName(AlertDialog) + AlertDialog.setTabOrder(self.AlertTextEdit, self.ParameterEdit) + AlertDialog.setTabOrder(self.ParameterEdit, self.AlertListWidget) + AlertDialog.setTabOrder(self.AlertListWidget, self.NewButton) + AlertDialog.setTabOrder(self.NewButton, self.SaveButton) + AlertDialog.setTabOrder(self.SaveButton, self.EditButton) + AlertDialog.setTabOrder(self.EditButton, self.DeleteButton) + AlertDialog.setTabOrder(self.DeleteButton, self.DisplayButton) + AlertDialog.setTabOrder(self.DisplayButton, self.DisplayCloseButton) + AlertDialog.setTabOrder(self.DisplayCloseButton, self.CloseButton) + + def retranslateUi(self, AlertDialog): + AlertDialog.setWindowTitle(QtGui.QApplication.translate("AlertDialog", "Alert Message", None, QtGui.QApplication.UnicodeUTF8)) + self.AlertEntryLabel.setText(QtGui.QApplication.translate("AlertDialog", "Alert &text:", None, QtGui.QApplication.UnicodeUTF8)) + self.AlertParameter.setText(QtGui.QApplication.translate("AlertDialog", "&Parameter(s):", None, QtGui.QApplication.UnicodeUTF8)) + self.NewButton.setText(QtGui.QApplication.translate("AlertDialog", "&New", None, QtGui.QApplication.UnicodeUTF8)) + self.SaveButton.setText(QtGui.QApplication.translate("AlertDialog", "&Save", None, QtGui.QApplication.UnicodeUTF8)) + self.EditButton.setText(QtGui.QApplication.translate("AlertDialog", "&Edit", None, QtGui.QApplication.UnicodeUTF8)) + self.DeleteButton.setText(QtGui.QApplication.translate("AlertDialog", "&Delete", None, QtGui.QApplication.UnicodeUTF8)) + self.DisplayButton.setText(QtGui.QApplication.translate("AlertDialog", "Displ&ay", None, QtGui.QApplication.UnicodeUTF8)) + self.DisplayCloseButton.setText(QtGui.QApplication.translate("AlertDialog", "Display && Cl&ose", None, QtGui.QApplication.UnicodeUTF8)) + self.CloseButton.setText(QtGui.QApplication.translate("AlertDialog", "&Close", None, QtGui.QApplication.UnicodeUTF8)) - def retranslateUi(self, AlertForm): - AlertForm.setWindowTitle(self.trUtf8('Alert Message')) - self.AlertEntryLabel.setText(self.trUtf8('Alert Text:')) - self.DisplayButton.setText(self.trUtf8('Display')) - self.CancelButton.setText(self.trUtf8('Cancel')) diff --git a/openlp/plugins/alerts/forms/alerteditdialog.py b/openlp/plugins/alerts/forms/alerteditdialog.py deleted file mode 100644 index 6cf4769ef..000000000 --- a/openlp/plugins/alerts/forms/alerteditdialog.py +++ /dev/null @@ -1,67 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'alerteditdialog.ui' -# -# Created: Sun Feb 14 16:45:10 2010 -# by: PyQt4 UI code generator 4.6.2 -# -# WARNING! All changes made in this file will be lost! - -from PyQt4 import QtCore, QtGui - -class Ui_AlertEditDialog(object): - def setupUi(self, AlertEditDialog): - AlertEditDialog.setObjectName(u'AlertEditDialog') - AlertEditDialog.resize(400, 300) - self.buttonBox = QtGui.QDialogButtonBox(AlertEditDialog) - self.buttonBox.setGeometry(QtCore.QRect(220, 270, 173, 27)) - self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel) - self.buttonBox.setObjectName(u'buttonBox') - self.layoutWidget = QtGui.QWidget(AlertEditDialog) - self.layoutWidget.setGeometry(QtCore.QRect(20, 10, 361, 251)) - self.layoutWidget.setObjectName(u'layoutWidget') - self.verticalLayout_2 = QtGui.QVBoxLayout(self.layoutWidget) - self.verticalLayout_2.setObjectName(u'verticalLayout_2') - self.horizontalLayout_2 = QtGui.QHBoxLayout() - self.horizontalLayout_2.setObjectName(u'horizontalLayout_2') - self.AlertLineEdit = QtGui.QLineEdit(self.layoutWidget) - self.AlertLineEdit.setObjectName(u'AlertLineEdit') - self.horizontalLayout_2.addWidget(self.AlertLineEdit) - self.verticalLayout_2.addLayout(self.horizontalLayout_2) - self.horizontalLayout = QtGui.QHBoxLayout() - self.horizontalLayout.setObjectName(u'horizontalLayout') - self.AlertListWidget = QtGui.QListWidget(self.layoutWidget) - self.AlertListWidget.setAlternatingRowColors(True) - self.AlertListWidget.setObjectName(u'AlertListWidget') - self.horizontalLayout.addWidget(self.AlertListWidget) - self.verticalLayout = QtGui.QVBoxLayout() - self.verticalLayout.setObjectName(u'verticalLayout') - self.SaveButton = QtGui.QPushButton(self.layoutWidget) - self.SaveButton.setObjectName(u'SaveButton') - self.verticalLayout.addWidget(self.SaveButton) - self.ClearButton = QtGui.QPushButton(self.layoutWidget) - self.ClearButton.setObjectName(u'ClearButton') - self.verticalLayout.addWidget(self.ClearButton) - self.AddButton = QtGui.QPushButton(self.layoutWidget) - self.AddButton.setObjectName(u'AddButton') - self.verticalLayout.addWidget(self.AddButton) - self.EditButton = QtGui.QPushButton(self.layoutWidget) - self.EditButton.setObjectName(u'EditButton') - self.verticalLayout.addWidget(self.EditButton) - self.DeleteButton = QtGui.QPushButton(self.layoutWidget) - self.DeleteButton.setObjectName(u'DeleteButton') - self.verticalLayout.addWidget(self.DeleteButton) - self.horizontalLayout.addLayout(self.verticalLayout) - self.verticalLayout_2.addLayout(self.horizontalLayout) - - self.retranslateUi(AlertEditDialog) - QtCore.QMetaObject.connectSlotsByName(AlertEditDialog) - - def retranslateUi(self, AlertEditDialog): - AlertEditDialog.setWindowTitle(self.trUtf8('Maintain Alerts')) - self.SaveButton.setText(self.trUtf8('Save')) - self.ClearButton.setText(self.trUtf8('Clear')) - self.AddButton.setText(self.trUtf8('Add')) - self.EditButton.setText(self.trUtf8('Edit')) - self.DeleteButton.setText(self.trUtf8('Delete')) - diff --git a/openlp/plugins/alerts/forms/alerteditform.py b/openlp/plugins/alerts/forms/alerteditform.py deleted file mode 100644 index 62c129508..000000000 --- a/openlp/plugins/alerts/forms/alerteditform.py +++ /dev/null @@ -1,166 +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, 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 PyQt4 import QtGui, QtCore -from openlp.plugins.alerts.lib.models import AlertItem - -from alerteditdialog import Ui_AlertEditDialog - -class AlertEditForm(QtGui.QDialog, Ui_AlertEditDialog): - """ - Class documentation goes here. - """ - def __init__(self, manager, parent): - """ - Constructor - """ - self.manager = manager - self.parent = parent - QtGui.QDialog.__init__(self, None) - self.setupUi(self) - QtCore.QObject.connect(self.DeleteButton, - QtCore.SIGNAL(u'clicked()'), - self.onDeleteClick) - QtCore.QObject.connect(self.ClearButton, - QtCore.SIGNAL(u'clicked()'), - self.onClearClick) - QtCore.QObject.connect(self.EditButton, - QtCore.SIGNAL(u'clicked()'), - self.onEditClick) - QtCore.QObject.connect(self.AddButton, - QtCore.SIGNAL(u'clicked()'), - self.onAddClick) - QtCore.QObject.connect(self.SaveButton, - QtCore.SIGNAL(u'clicked()'), - self.onSaveClick) - QtCore.QObject.connect(self.buttonBox, - QtCore.SIGNAL(u'rejected()'), self.close) - QtCore.QObject.connect(self.AlertLineEdit, - QtCore.SIGNAL(u'textChanged(const QString&)'), - self.onTextChanged) - QtCore.QObject.connect(self.AlertListWidget, - QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), - self.onItemSelected) - QtCore.QObject.connect(self.AlertListWidget, - QtCore.SIGNAL(u'clicked(QModelIndex)'), - self.onItemSelected) - - def loadList(self): - self.AlertListWidget.clear() - alerts = self.manager.get_all_alerts() - for alert in alerts: - item_name = QtGui.QListWidgetItem(alert.text) - item_name.setData( - QtCore.Qt.UserRole, QtCore.QVariant(alert.id)) - self.AlertListWidget.addItem(item_name) - self.AddButton.setEnabled(True) - self.ClearButton.setEnabled(False) - self.SaveButton.setEnabled(False) - self.EditButton.setEnabled(False) - self.DeleteButton.setEnabled(False) - - def onItemSelected(self): - if self.AlertLineEdit.text(): - QtGui.QMessageBox.information(self, - self.trUtf8('Item selected to Edit'), - self.trUtf8('Please Save or Clear seletced item')) - else: - self.EditButton.setEnabled(True) - self.DeleteButton.setEnabled(True) - - def onDeleteClick(self): - item = self.AlertListWidget.currentItem() - if item: - item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] - self.parent.manager.delete_alert(item_id) - row = self.AlertListWidget.row(item) - self.AlertListWidget.takeItem(row) - self.AddButton.setEnabled(True) - self.SaveButton.setEnabled(False) - self.DeleteButton.setEnabled(False) - self.EditButton.setEnabled(False) - - def onEditClick(self): - item = self.AlertListWidget.currentItem() - if item: - self.item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] - self.AlertLineEdit.setText(unicode(item.text())) - self.AddButton.setEnabled(True) - self.ClearButton.setEnabled(True) - self.SaveButton.setEnabled(True) - self.DeleteButton.setEnabled(True) - self.EditButton.setEnabled(False) - - def onClearClick(self): - self.AlertLineEdit.setText(u'') - self.AddButton.setEnabled(False) - self.ClearButton.setEnabled(True) - self.SaveButton.setEnabled(False) - self.DeleteButton.setEnabled(False) - self.EditButton.setEnabled(False) - - def onAddClick(self): - if len(self.AlertLineEdit.text()) == 0: - QtGui.QMessageBox.information(self, - self.trUtf8('Item selected to Add'), - self.trUtf8('Missing data')) - else: - alert = AlertItem() - alert.text = unicode(self.AlertLineEdit.text()) - self.manager.save_alert(alert) - self.onClearClick() - self.loadList() - - def onSaveClick(self): - alert = self.manager.get_alert(self.item_id) - alert.text = unicode(self.AlertLineEdit.text()) - self.manager.save_alert(alert) - self.onClearClick() - self.loadList() - - def onTextChanged(self): - self.AddButton.setEnabled(True) - - def onDoubleClick(self): - """ - List item has been double clicked to display it - """ - items = self.AlertListWidget.selectedIndexes() - for item in items: - bitem = self.AlertListWidget.item(item.row()) - self.triggerAlert(bitem.text()) - - def onSingleClick(self): - """ - List item has been single clicked to add it to - the edit field so it can be changed. - """ - items = self.AlertListWidget.selectedIndexes() - for item in items: - bitem = self.AlertListWidget.item(item.row()) - self.AlertEntryEditItem.setText(bitem.text()) - - def triggerAlert(self, text): - self.parent.alertsmanager.displayAlert(text) diff --git a/openlp/plugins/alerts/forms/alertform.py b/openlp/plugins/alerts/forms/alertform.py index 2d7dd1c21..08e5f5e02 100644 --- a/openlp/plugins/alerts/forms/alertform.py +++ b/openlp/plugins/alerts/forms/alertform.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -45,9 +45,24 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): QtCore.QObject.connect(self.DisplayButton, QtCore.SIGNAL(u'clicked()'), self.onDisplayClicked) - QtCore.QObject.connect(self.AlertEntryEditItem, + QtCore.QObject.connect(self.DisplayCloseButton, + QtCore.SIGNAL(u'clicked()'), + self.onDisplayCloseClicked) + QtCore.QObject.connect(self.AlertTextEdit, QtCore.SIGNAL(u'textChanged(const QString&)'), self.onTextChanged) + QtCore.QObject.connect(self.NewButton, + QtCore.SIGNAL(u'clicked()'), + self.onNewClick) + QtCore.QObject.connect(self.DeleteButton, + QtCore.SIGNAL(u'clicked()'), + self.onDeleteClick) + QtCore.QObject.connect(self.EditButton, + QtCore.SIGNAL(u'clicked()'), + self.onEditClick) + QtCore.QObject.connect(self.SaveButton, + QtCore.SIGNAL(u'clicked()'), + self.onSaveClick) QtCore.QObject.connect(self.AlertListWidget, QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), self.onDoubleClick) @@ -60,19 +75,64 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): alerts = self.manager.get_all_alerts() for alert in alerts: item_name = QtGui.QListWidgetItem(alert.text) + item_name.setData( + QtCore.Qt.UserRole, QtCore.QVariant(alert.id)) self.AlertListWidget.addItem(item_name) + self.SaveButton.setEnabled(False) + self.EditButton.setEnabled(False) + self.DeleteButton.setEnabled(False) def onDisplayClicked(self): - self.triggerAlert(unicode(self.AlertEntryEditItem.text())) - if self.parent.alertsTab.save_history and self.history_required: + if self.triggerAlert(unicode(self.AlertTextEdit.text())): + self.history_required = False + self.loadList() + + def onDisplayCloseClicked(self): + if self.triggerAlert(unicode(self.AlertTextEdit.text())): + self.close() + + def onDeleteClick(self): + item = self.AlertListWidget.currentItem() + if item: + item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] + self.parent.manager.delete_alert(item_id) + row = self.AlertListWidget.row(item) + self.AlertListWidget.takeItem(row) + self.AlertTextEdit.setText(u'') + self.SaveButton.setEnabled(False) + self.DeleteButton.setEnabled(False) + self.EditButton.setEnabled(False) + + def onEditClick(self): + item = self.AlertListWidget.currentItem() + if item: + self.item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] + self.AlertTextEdit.setText(unicode(item.text())) + self.SaveButton.setEnabled(True) + self.DeleteButton.setEnabled(True) + self.EditButton.setEnabled(False) + + def onNewClick(self): + if len(self.AlertTextEdit.text()) == 0: + QtGui.QMessageBox.information(self, + self.trUtf8('Item selected to Add'), + self.trUtf8('Missing data')) + else: alert = AlertItem() - alert.text = unicode(self.AlertEntryEditItem.text()) + alert.text = unicode(self.AlertTextEdit.text()) self.manager.save_alert(alert) - self.history_required = False + self.onClearClick() + self.loadList() + + def onSaveClick(self): + alert = self.manager.get_alert(self.item_id) + alert.text = unicode(self.AlertTextEdit.text()) + self.manager.save_alert(alert) + self.onClearClick() self.loadList() def onTextChanged(self): - #Data has changed by editing it so potential storage + #Data has changed by editing it so potential storage required self.history_required = True def onDoubleClick(self): @@ -93,8 +153,17 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): items = self.AlertListWidget.selectedIndexes() for item in items: bitem = self.AlertListWidget.item(item.row()) - self.AlertEntryEditItem.setText(bitem.text()) + self.AlertTextEdit.setText(bitem.text()) self.history_required = False + self.EditButton.setEnabled(True) + self.DeleteButton.setEnabled(True) def triggerAlert(self, text): - self.parent.alertsmanager.displayAlert(text) + if text: + self.parent.alertsmanager.displayAlert(text) + if self.parent.alertsTab.save_history and self.history_required: + alert = AlertItem() + alert.text = unicode(self.AlertTextEdit.text()) + self.manager.save_alert(alert) + return True + return False diff --git a/openlp/plugins/alerts/forms/alertstab.py b/openlp/plugins/alerts/forms/alertstab.py index c842c2e20..d15865a6d 100644 --- a/openlp/plugins/alerts/forms/alertstab.py +++ b/openlp/plugins/alerts/forms/alertstab.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -26,6 +26,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import SettingsTab, str_to_bool +from openlp.plugins.alerts.lib.models import AlertItem class AlertsTab(SettingsTab): """ @@ -33,6 +34,8 @@ class AlertsTab(SettingsTab): """ def __init__(self, parent, section=None): self.parent = parent + self.manager = parent.manager + self.alertsmanager = parent.alertsmanager SettingsTab.__init__(self, parent.name, section) def setupUi(self): @@ -149,22 +152,6 @@ class AlertsTab(SettingsTab): QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) self.HistoryLayout.addItem(self.HistorySpacer) self.FontLayout.addWidget(self.HistoryWidget) - self.HistoryEditWidget = QtGui.QWidget(self.FontGroupBox) - self.HistoryEditWidget.setObjectName(u'HistoryEditWidget') - self.HistoryEditLayout = QtGui.QHBoxLayout(self.HistoryEditWidget) - self.HistoryEditLayout.setSpacing(8) - self.HistoryEditLayout.setMargin(0) - self.HistoryEditLayout.setObjectName(u'HistoryEditLayout') - self.HistoryEditLabel = QtGui.QLabel(self.HistoryEditWidget) - self.HistoryEditLabel.setObjectName(u'HistoryEditLabel') - self.HistoryEditLayout.addWidget(self.HistoryEditLabel) - self.HistoryEditPushButton = QtGui.QPushButton(self.HistoryEditWidget) - self.HistoryEditPushButton.setObjectName(u'HistoryEditPushButton') - self.HistoryEditLayout.addWidget(self.HistoryEditPushButton) - self.HistoryEditSpacer = QtGui.QSpacerItem(147, 20, - QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.HistoryEditLayout.addItem(self.HistoryEditSpacer) - self.FontLayout.addWidget(self.HistoryEditWidget) self.SlideLeftLayout.addWidget(self.FontGroupBox) self.SlideLeftSpacer = QtGui.QSpacerItem(20, 94, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) @@ -210,8 +197,6 @@ class AlertsTab(SettingsTab): QtCore.SIGNAL(u'pressed()'), self.onBackgroundColorButtonClicked) QtCore.QObject.connect(self.FontColorButton, QtCore.SIGNAL(u'pressed()'), self.onFontColorButtonClicked) - QtCore.QObject.connect(self.HistoryEditPushButton, - QtCore.SIGNAL(u'pressed()'), self.onHistoryEditButtonClicked) QtCore.QObject.connect(self.FontComboBox, QtCore.SIGNAL(u'activated(int)'), self.onFontComboBoxClicked) QtCore.QObject.connect(self.LocationComboBox, @@ -232,7 +217,6 @@ class AlertsTab(SettingsTab): self.TimeoutSpinBox.setSuffix(self.trUtf8('s')) self.LocationLabel.setText(self.trUtf8('Location:')) self.HistoryLabel.setText(self.trUtf8('Keep History:')) - self.HistoryEditLabel.setText(self.trUtf8('Edit History:')) self.PreviewGroupBox.setTitle(self.trUtf8('Preview')) self.FontPreview.setText(self.trUtf8('openlp.org')) self.LocationComboBox.setItemText(0, self.trUtf8('Top')) @@ -271,9 +255,6 @@ class AlertsTab(SettingsTab): self.font_size = self.FontSizeSpinBox.value() self.updateDisplay() - def onHistoryEditButtonClicked(self): - self.parent.onAlertsEdit() - def load(self): self.timeout = int(self.config.get_config(u'timeout', 5)) self.font_color = unicode( @@ -299,6 +280,10 @@ class AlertsTab(SettingsTab): self.FontComboBox.setCurrentFont(font) self.updateDisplay() + def onItemSelected(self): + self.EditButton.setEnabled(True) + self.DeleteButton.setEnabled(True) + def save(self): self.font_face = self.FontComboBox.currentFont().family() self.config.set_config(u'background color', unicode(self.bg_color)) diff --git a/openlp/plugins/alerts/lib/__init__.py b/openlp/plugins/alerts/lib/__init__.py index c39574719..59a27b28e 100644 --- a/openlp/plugins/alerts/lib/__init__.py +++ b/openlp/plugins/alerts/lib/__init__.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -22,5 +22,6 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### + from alertsmanager import AlertsManager from manager import DBManager diff --git a/openlp/plugins/alerts/lib/alertsmanager.py b/openlp/plugins/alerts/lib/alertsmanager.py index 41fc25562..2243b5bef 100644 --- a/openlp/plugins/alerts/lib/alertsmanager.py +++ b/openlp/plugins/alerts/lib/alertsmanager.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -40,6 +40,7 @@ class AlertsManager(QtCore.QObject): def __init__(self, parent): QtCore.QObject.__init__(self) self.parent = parent + self.screen = None self.timer_id = 0 self.alertList = [] QtCore.QObject.connect(Receiver.get_receiver(), @@ -53,8 +54,8 @@ class AlertsManager(QtCore.QObject): def screenChanged(self): log.debug(u'screen changed') - self.screen = self.parent.maindisplay.screen 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) @@ -64,9 +65,12 @@ class AlertsManager(QtCore.QObject): 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) + 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 displayAlert(self, text=u''): """ @@ -76,12 +80,14 @@ class AlertsManager(QtCore.QObject): display text """ log.debug(u'display alert called %s' % text) - self.parent.maindisplay.parent.StatusBar.showMessage(u'') + if not self.screen: + self.screenChanged() self.alertList.append(text) - if self.timer_id != 0 or self.parent.maindisplay.mediaLoaded: - self.parent.maindisplay.parent.StatusBar.showMessage(\ - self.trUtf8(u'Alert message created and delayed')) + if self.timer_id != 0: + Receiver.send_message(u'status_message', + self.trUtf8(u'Alert message created and delayed')) return + Receiver.send_message(u'status_message', u'') self.generateAlert() def generateAlert(self): @@ -113,6 +119,7 @@ class AlertsManager(QtCore.QObject): self.timer_id = self.startTimer(int(alertTab.timeout) * 1000) def timerEvent(self, event): + log.debug(u'timer event') if event.timerId() == self.timer_id: self.parent.maindisplay.addAlertImage(None, True) self.killTimer(self.timer_id) diff --git a/openlp/plugins/alerts/lib/classes.py b/openlp/plugins/alerts/lib/classes.py index eec21300c..fd1883b71 100644 --- a/openlp/plugins/alerts/lib/classes.py +++ b/openlp/plugins/alerts/lib/classes.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/plugins/alerts/lib/manager.py b/openlp/plugins/alerts/lib/manager.py index a3ed1ee7e..ec4654807 100644 --- a/openlp/plugins/alerts/lib/manager.py +++ b/openlp/plugins/alerts/lib/manager.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/plugins/alerts/lib/meta.py b/openlp/plugins/alerts/lib/meta.py index 38b0f7206..affa31969 100644 --- a/openlp/plugins/alerts/lib/meta.py +++ b/openlp/plugins/alerts/lib/meta.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -35,4 +35,4 @@ session = None # Global metadata. If you have multiple databases with overlapping table # names, you'll need a metadata for each database -metadata = MetaData() \ No newline at end of file +metadata = MetaData() diff --git a/openlp/plugins/alerts/lib/models.py b/openlp/plugins/alerts/lib/models.py index 4f556cd23..d95ebce5d 100644 --- a/openlp/plugins/alerts/lib/models.py +++ b/openlp/plugins/alerts/lib/models.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/plugins/alerts/lib/tables.py b/openlp/plugins/alerts/lib/tables.py index 0a731fb13..0e707570d 100644 --- a/openlp/plugins/alerts/lib/tables.py +++ b/openlp/plugins/alerts/lib/tables.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/plugins/bibles/__init__.py b/openlp/plugins/bibles/__init__.py index bc50edda3..1a348a0df 100644 --- a/openlp/plugins/bibles/__init__.py +++ b/openlp/plugins/bibles/__init__.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -21,4 +21,4 @@ # 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 # -############################################################################### \ No newline at end of file +############################################################################### diff --git a/openlp/plugins/bibles/bibleplugin.py b/openlp/plugins/bibles/bibleplugin.py index bd65b6622..61724ffb6 100644 --- a/openlp/plugins/bibles/bibleplugin.py +++ b/openlp/plugins/bibles/bibleplugin.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -73,7 +73,7 @@ class BiblePlugin(Plugin): self.ImportBibleItem.setText(import_menu.trUtf8('&Bible')) # Signals and slots QtCore.QObject.connect(self.ImportBibleItem, - QtCore.SIGNAL(u'triggered()'), self.onBibleNewClick) + QtCore.SIGNAL(u'triggered()'), self.onBibleImportClick) self.ImportBibleItem.setVisible(False) def add_export_menu_item(self, export_menu): @@ -83,9 +83,9 @@ class BiblePlugin(Plugin): self.ExportBibleItem.setText(export_menu.trUtf8('&Bible')) self.ExportBibleItem.setVisible(False) - def onBibleNewClick(self): + def onBibleImportClick(self): if self.media_item: - self.media_item.onNewClick() + self.media_item.onImportClick() def about(self): about_text = self.trUtf8('Bible Plugin
This ' @@ -93,7 +93,6 @@ class BiblePlugin(Plugin): 'displayed on the screen during the service.') return about_text - def can_delete_theme(self, theme): if self.settings_tab.bible_theme == theme: return False diff --git a/openlp/plugins/bibles/forms/__init__.py b/openlp/plugins/bibles/forms/__init__.py index dd504d347..312aa7506 100644 --- a/openlp/plugins/bibles/forms/__init__.py +++ b/openlp/plugins/bibles/forms/__init__.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -25,4 +25,4 @@ from importwizardform import ImportWizardForm -__all__ = ['ImportWizardForm'] \ No newline at end of file +__all__ = ['ImportWizardForm'] diff --git a/openlp/plugins/bibles/forms/bibleimportwizard.py b/openlp/plugins/bibles/forms/bibleimportwizard.py index 59e38e39a..7b42ed26d 100644 --- a/openlp/plugins/bibles/forms/bibleimportwizard.py +++ b/openlp/plugins/bibles/forms/bibleimportwizard.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -104,7 +104,7 @@ class Ui_BibleImportWizard(object): self.OsisFileButton = QtGui.QToolButton(self.OsisPage) self.OsisFileButton.setMaximumSize(QtCore.QSize(32, 16777215)) icon = QtGui.QIcon() - icon.addPixmap(QtGui.QPixmap(u':/imports/import_load.png'), + icon.addPixmap(QtGui.QPixmap(u':/general/general_open.png'), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.OsisFileButton.setIcon(icon) self.OsisFileButton.setObjectName(u'OsisFileButton') diff --git a/openlp/plugins/bibles/forms/importwizardform.py b/openlp/plugins/bibles/forms/importwizardform.py index 742598fdb..a717a4f44 100644 --- a/openlp/plugins/bibles/forms/importwizardform.py +++ b/openlp/plugins/bibles/forms/importwizardform.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -32,11 +32,12 @@ from PyQt4 import QtCore, QtGui from bibleimportwizard import Ui_BibleImportWizard from openlp.core.lib import Receiver +from openlp.core.utils import AppLocation, variant_to_unicode from openlp.plugins.bibles.lib.manager import BibleFormat log = logging.getLogger(__name__) -class DownloadLocation(object): +class WebDownload(object): Unknown = -1 Crosswalk = 0 BibleGateway = 1 @@ -59,9 +60,21 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): log.info(u'BibleImportForm loaded') def __init__(self, parent, config, manager, bibleplugin): - ''' - Constructor - ''' + """ + Instantiate the wizard, and run any extra setup we need to. + + ``parent`` + The QWidget-derived parent of the wizard. + + ``config`` + The configuration object for storing and retrieving settings. + + ``manager`` + The Bible manager. + + ``bibleplugin`` + The Bible plugin. + """ QtGui.QWizard.__init__(self, parent) self.setupUi(self) self.registerFields() @@ -96,10 +109,16 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): self.onCurrentIdChanged) def exec_(self): + """ + Run the wizard. + """ self.setDefaults() return QtGui.QWizard.exec_(self) def validateCurrentPage(self): + """ + Validate the current page before moving on to the next page. + """ if self.currentId() == 0: # Welcome page return True @@ -110,7 +129,7 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): QtGui.QMessageBox.critical(self, self.trUtf8('Invalid Bible Location'), self.trUtf8('You need to specify a file to import your ' - 'Bible from!'), + 'Bible from.'), QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok)) self.OSISLocationEdit.setFocus() return False @@ -119,7 +138,7 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): QtGui.QMessageBox.critical(self, self.trUtf8('Invalid Books File'), self.trUtf8('You need to specify a file with books of ' - 'the Bible to use in the import!'), + 'the Bible to use in the import.'), QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok)) self.BooksLocationEdit.setFocus() return False @@ -127,7 +146,7 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): QtGui.QMessageBox.critical(self, self.trUtf8('Invalid Verse File'), self.trUtf8('You need to specify a file of Bible ' - 'verses to import!'), + 'verses to import.'), QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok)) self.CsvVerseLocationEdit.setFocus() return False @@ -136,22 +155,24 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): QtGui.QMessageBox.critical(self, self.trUtf8('Invalid OpenSong Bible'), self.trUtf8('You need to specify an OpenSong Bible ' - 'file to import!'), + 'file to import.'), QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok)) self.OpenSongFileEdit.setFocus() return False return True elif self.currentId() == 2: # License details - if self.field(u'license_version').toString() == u'': + license_version = variant_to_unicode(self.field(u'license_version')) + license_copyright = variant_to_unicode(self.field(u'license_copyright')) + if license_version == u'': QtGui.QMessageBox.critical(self, self.trUtf8('Empty Version Name'), self.trUtf8('You need to specify a version name for your ' - 'Bible!'), + 'Bible.'), QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok)) self.VersionNameEdit.setFocus() return False - elif self.field(u'license_copyright').toString() == u'': + elif license_copyright == u'': QtGui.QMessageBox.critical(self, self.trUtf8('Empty Copyright'), self.trUtf8('You need to set a copyright for your Bible! ' @@ -160,8 +181,7 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok)) self.CopyrightEdit.setFocus() return False - elif self.manager.exists( - self.field(u'license_version').toString()): + elif self.manager.exists(license_version): QtGui.QMessageBox.critical(self, self.trUtf8('Bible Exists'), self.trUtf8('This Bible already exists! Please import ' @@ -175,27 +195,49 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): return True def onLocationComboBoxChanged(self, index): + """ + Setup the list of Bibles when you select a different source on the web + download page. + + ``index`` + The index of the combo box. + """ self.BibleComboBox.clear() - for bible, abbreviation in self.web_bible_list[index].iteritems(): + for bible in self.web_bible_list[index].keys(): self.BibleComboBox.addItem(unicode(self.trUtf8(bible))) def onOsisFileButtonClicked(self): - self.getFileName(self.trUtf8('Open OSIS file'), + """ + Show the file open dialog for the OSIS file. + """ + self.getFileName(self.trUtf8('Open OSIS File'), self.OSISLocationEdit) def onBooksFileButtonClicked(self): - self.getFileName(self.trUtf8('Open Books CSV file'), + """ + Show the file open dialog for the books CSV file. + """ + self.getFileName(self.trUtf8('Open Books CSV File'), self.BooksLocationEdit) def onCsvVersesFileButtonClicked(self): - self.getFileName(self.trUtf8('Open Verses CSV file'), + """ + Show the file open dialog for the verses CSV file. + """ + self.getFileName(self.trUtf8('Open Verses CSV File'), self.CsvVerseLocationEdit) def onOpenSongBrowseButtonClicked(self): + """ + Show the file open dialog for the OpenSong file. + """ self.getFileName(self.trUtf8('Open OpenSong Bible'), self.OpenSongFileEdit) def onCancelButtonClicked(self, checked): + """ + Stop the import on pressing the cancel button. + """ log.debug('Cancel button pressed!') if self.currentId() == 3: Receiver.send_message(u'openlpstopimport') @@ -240,7 +282,7 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): self.setField(u'csv_booksfile', QtCore.QVariant('')) self.setField(u'csv_versefile', QtCore.QVariant('')) self.setField(u'opensong_file', QtCore.QVariant('')) - self.setField(u'web_location', QtCore.QVariant(DownloadLocation.Crosswalk)) + self.setField(u'web_location', QtCore.QVariant(WebDownload.Crosswalk)) self.setField(u'web_biblename', QtCore.QVariant(self.BibleComboBox)) self.setField(u'proxy_server', QtCore.QVariant(self.config.get_config(u'proxy address', ''))) @@ -251,26 +293,30 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): self.setField(u'license_version', QtCore.QVariant(self.VersionNameEdit)) self.setField(u'license_copyright', QtCore.QVariant(self.CopyrightEdit)) self.setField(u'license_permission', QtCore.QVariant(self.PermissionEdit)) - self.onLocationComboBoxChanged(DownloadLocation.Crosswalk) + self.onLocationComboBoxChanged(WebDownload.Crosswalk) def loadWebBibles(self): """ Load the list of Crosswalk and BibleGateway bibles. """ #Load and store Crosswalk Bibles - filepath = os.path.abspath(os.path.join( - os.path.split(os.path.abspath(__file__))[0], - u'..', u'resources')) + filepath = AppLocation.get_directory(AppLocation.PluginsDir) + filepath = os.path.join(filepath, u'bibles', u'resources') fbibles = None try: - self.web_bible_list[DownloadLocation.Crosswalk] = {} + self.web_bible_list[WebDownload.Crosswalk] = {} books_file = open(os.path.join(filepath, u'crosswalkbooks.csv'), 'r') dialect = csv.Sniffer().sniff(books_file.read(1024)) books_file.seek(0) books_reader = csv.reader(books_file, dialect) for line in books_reader: - self.web_bible_list[DownloadLocation.Crosswalk][line[0]] = \ - unicode(line[1], u'utf-8').strip() + ver = line[0] + name = line[1] + if not isinstance(ver, unicode): + ver = unicode(ver, u'utf8') + if not isinstance(name, unicode): + name = unicode(name, u'utf8') + self.web_bible_list[WebDownload.Crosswalk][ver] = name.strip() except: log.exception(u'Crosswalk resources missing') finally: @@ -278,14 +324,19 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): books_file.close() #Load and store BibleGateway Bibles try: - self.web_bible_list[DownloadLocation.BibleGateway] = {} + self.web_bible_list[WebDownload.BibleGateway] = {} books_file = open(os.path.join(filepath, u'biblegateway.csv'), 'r') dialect = csv.Sniffer().sniff(books_file.read(1024)) books_file.seek(0) books_reader = csv.reader(books_file, dialect) for line in books_reader: - self.web_bible_list[DownloadLocation.BibleGateway][line[0]] = \ - unicode(line[1], u'utf-8').strip() + ver = line[0] + name = line[1] + if not isinstance(ver, unicode): + ver = unicode(ver, u'utf8') + if not isinstance(name, unicode): + name = unicode(name, u'utf8') + self.web_bible_list[WebDownload.BibleGateway][ver] = name.strip() except: log.exception(u'Biblegateway resources missing') finally: @@ -315,56 +366,59 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): def performImport(self): bible_type = self.field(u'source_format').toInt()[0] - success = False + license_version = variant_to_unicode(self.field(u'license_version')) + license_copyright = variant_to_unicode(self.field(u'license_copyright')) + license_permission = variant_to_unicode(self.field(u'license_permission')) + importer = None if bible_type == BibleFormat.OSIS: # Import an OSIS bible - success = self.manager.import_bible(BibleFormat.OSIS, - name=unicode(self.field(u'license_version').toString()), - filename=unicode(self.field(u'osis_location').toString()) + importer = self.manager.import_bible(BibleFormat.OSIS, + name=license_version, + filename=variant_to_unicode(self.field(u'osis_location')) ) elif bible_type == BibleFormat.CSV: # Import a CSV bible - success = self.manager.import_bible(BibleFormat.CSV, - name=unicode(self.field(u'license_version').toString()), - booksfile=self.field(u'csv_booksfile').toString(), - versefile=self.field(u'csv_versefile').toString() + importer = self.manager.import_bible(BibleFormat.CSV, + name=license_version, + booksfile=variant_to_unicode(self.field(u'csv_booksfile')), + versefile=variant_to_unicode(self.field(u'csv_versefile')) ) elif bible_type == BibleFormat.OpenSong: # Import an OpenSong bible - success = self.manager.import_bible(BibleFormat.OpenSong, - name=unicode(self.field(u'license_version').toString()), - filename=self.field(u'opensong_file').toString() + importer = self.manager.import_bible(BibleFormat.OpenSong, + name=license_version, + filename=variant_to_unicode(self.field(u'opensong_file')) ) elif bible_type == BibleFormat.WebDownload: # Import a bible from the web self.ImportProgressBar.setMaximum(1) download_location = self.field(u'web_location').toInt()[0] - if download_location == DownloadLocation.Crosswalk: - bible = self.web_bible_list[DownloadLocation.Crosswalk][ - unicode(self.BibleComboBox.currentText())] - elif download_location == DownloadLocation.BibleGateway: - bible = self.web_bible_list[DownloadLocation.BibleGateway][ - unicode(self.BibleComboBox.currentText())] - success = self.manager.import_bible(BibleFormat.WebDownload, - name=unicode(self.field(u'license_version').toString()), - download_source=unicode(DownloadLocation.get_name(download_location)), - download_name=unicode(bible), - proxy_server=unicode(self.field(u'proxy_server').toString()), - proxy_username=unicode(self.field(u'proxy_username').toString()), - proxy_password=unicode(self.field(u'proxy_password').toString()) + bible_version = self.BibleComboBox.currentText() + if not isinstance(bible_version, unicode): + bible_version = unicode(bible_version, u'utf8') + if download_location == WebDownload.Crosswalk: + bible = self.web_bible_list[WebDownload.Crosswalk][bible_version] + elif download_location == WebDownload.BibleGateway: + bible = self.web_bible_list[WebDownload.BibleGateway][bible_version] + importer = self.manager.import_bible( + BibleFormat.WebDownload, + name=license_version, + download_source=WebDownload.get_name(download_location), + download_name=bible, + proxy_server=variant_to_unicode(self.field(u'proxy_server')), + proxy_username=variant_to_unicode(self.field(u'proxy_username')), + proxy_password=variant_to_unicode(self.field(u'proxy_password')) ) + success = importer.do_import() if success: - self.manager.save_meta_data( - unicode(self.field(u'license_version').toString()), - unicode(self.field(u'license_version').toString()), - unicode(self.field(u'license_copyright').toString()), - unicode(self.field(u'license_permission').toString()) - ) + self.manager.save_meta_data(license_version, license_version, + license_copyright, license_permission) self.manager.reload_bibles() self.ImportProgressLabel.setText(self.trUtf8('Finished import.')) else: self.ImportProgressLabel.setText( self.trUtf8('Your Bible import failed.')) + importer.delete() def postImport(self): self.ImportProgressBar.setValue(self.ImportProgressBar.maximum()) diff --git a/openlp/plugins/bibles/lib/__init__.py b/openlp/plugins/bibles/lib/__init__.py index f60ef5bbc..a69db14b3 100644 --- a/openlp/plugins/bibles/lib/__init__.py +++ b/openlp/plugins/bibles/lib/__init__.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -26,4 +26,4 @@ from common import BibleCommon from manager import BibleManager from biblestab import BiblesTab -from mediaitem import BibleMediaItem \ No newline at end of file +from mediaitem import BibleMediaItem diff --git a/openlp/plugins/bibles/lib/biblestab.py b/openlp/plugins/bibles/lib/biblestab.py index 398040fd8..4c205b920 100644 --- a/openlp/plugins/bibles/lib/biblestab.py +++ b/openlp/plugins/bibles/lib/biblestab.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/plugins/bibles/lib/common.py b/openlp/plugins/bibles/lib/common.py index 9a876266d..48e55cb7e 100644 --- a/openlp/plugins/bibles/lib/common.py +++ b/openlp/plugins/bibles/lib/common.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -27,12 +27,13 @@ import urllib2 import logging import re import chardet +import htmlentitydefs only_verses = re.compile(r'([\w .]+)[ ]+([0-9]+)[ ]*[:|v|V][ ]*([0-9]+)' r'(?:[ ]*-[ ]*([0-9]+|end))?(?:[ ]*,[ ]*([0-9]+)(?:[ ]*-[ ]*([0-9]+|end))?)?', re.UNICODE) chapter_range = re.compile(r'([\w .]+)[ ]+([0-9]+)[ ]*[:|v|V][ ]*' - r'([0-9]+)[ ]*-[ ]*([0-9]+)[ ]*[:|v|V][ ]*([0-9]+)', + r'([0-9]+|end)[ ]*-[ ]*([0-9]+)[ ]*[:|v|V][ ]*([0-9]+|end)', re.UNICODE) log = logging.getLogger(__name__) @@ -115,7 +116,6 @@ def parse_reference(reference): log.debug(reference_list) return reference_list - class SearchResults(object): """ Encapsulate a set of search results. This is Bible-type independant. @@ -247,3 +247,33 @@ class BibleCommon(object): start_tag = text.find(u'<') text = text.replace(u'>', u'') return text.rstrip().lstrip() + + +def unescape(text): + """ + Removes HTML or XML character references and entities from a text string. + Courtesy of Fredrik Lundh, http://effbot.org/zone/re-sub.htm#unescape-html + + @param text The HTML (or XML) source text. + @return The plain text, as a Unicode string, if necessary. + """ + def fixup(m): + text = m.group(0) + if text[:2] == u'&#': + # character reference + try: + if text[:3] == u'&#x': + return unichr(int(text[3:-1], 16)) + else: + return unichr(int(text[2:-1])) + except ValueError: + pass + else: + # named entity + try: + text = unichr(htmlentitydefs.name2codepoint[text[1:-1]]) + except KeyError: + pass + return text # leave as is + return re.sub(u'&#?\w+;', fixup, text) + diff --git a/openlp/plugins/bibles/lib/csvbible.py b/openlp/plugins/bibles/lib/csvbible.py index a1a16339c..2f40e4b96 100644 --- a/openlp/plugins/bibles/lib/csvbible.py +++ b/openlp/plugins/bibles/lib/csvbible.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py index be4112a54..66b956109 100644 --- a/openlp/plugins/bibles/lib/db.py +++ b/openlp/plugins/bibles/lib/db.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -26,6 +26,7 @@ import os import logging import chardet +import re from sqlalchemy import or_ from PyQt4 import QtCore @@ -63,16 +64,21 @@ class BibleDB(QtCore.QObject): QtCore.QObject.__init__(self) if u'path' not in kwargs: raise KeyError(u'Missing keyword argument "path".') - if u'name' not in kwargs: - raise KeyError(u'Missing keyword argument "name".') if u'config' not in kwargs: raise KeyError(u'Missing keyword argument "config".') + if u'name' not in kwargs and u'file' not in kwargs: + raise KeyError(u'Missing keyword argument "name" or "file".') self.stop_import_flag = False - self.name = kwargs[u'name'] self.config = kwargs[u'config'] - self.db_file = os.path.join(kwargs[u'path'], - u'%s.sqlite' % kwargs[u'name']) - log.debug(u'Load bible %s on path %s', kwargs[u'name'], self.db_file) + if u'name' in kwargs: + self.name = kwargs[u'name'] + if not isinstance(self.name, unicode): + self.name = unicode(self.name, u'utf-8') + 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) db_type = self.config.get_config(u'db type', u'sqlite') db_url = u'' if db_type == u'sqlite': @@ -85,6 +91,42 @@ class BibleDB(QtCore.QObject): self.config.get_config(u'db database')) self.metadata, self.session = init_models(db_url) self.metadata.create_all(checkfirst=True) + if u'file' in kwargs: + self.get_name() + + def get_name(self): + """ + Returns the version name of the Bible. + """ + version_name = self.get_meta(u'Version') + if version_name: + self.name = version_name.value + else: + self.name = None + return self.name + + def clean_filename(self, old_filename): + """ + Clean up the version name of the Bible and convert it into a valid + file name. + + ``old_filename`` + The "dirty" file name or version name. + """ + if not isinstance(old_filename, unicode): + old_filename = unicode(old_filename, u'utf-8') + 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: + return False def register(self, wizard): """ @@ -92,16 +134,25 @@ class BibleDB(QtCore.QObject): from the Bible Manager when a Bible is imported. Descendant classes may want to override this method to supply their own custom initialisation as well. + + ``wizard`` + The actual Qt wizard form. """ self.wizard = wizard self.create_tables() return self.name def commit(self): + """ + Perform a database commit. + """ log.debug('Committing...') self.session.commit() def create_tables(self): + """ + Create some initial metadata. + """ log.debug(u'createTables') self.create_meta(u'dbversion', u'2') self.create_testament(u'Old Testament') @@ -109,11 +160,29 @@ class BibleDB(QtCore.QObject): 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() def create_book(self, name, abbrev, testament=1): + """ + Add a book to the database. + + ``name`` + The name of the book. + + ``abbrev`` + The abbreviation of the book. + + ``testament`` + *Defaults to 1.* The id of the testament this book belongs to. + """ log.debug(u'create_book %s,%s', name, abbrev) book = Book.populate(name=name, abbreviation=abbrev, testament_id=testament) @@ -122,6 +191,19 @@ class BibleDB(QtCore.QObject): return book def create_chapter(self, book_id, chapter, textlist): + """ + Add a chapter and it's verses to a book. + + ``book_id`` + The id of the book being appended. + + ``chapter`` + The chapter number. + + ``textlist`` + A dict of the verses to be inserted. The key is the verse number, + and the value is the verse text. + """ log.debug(u'create_chapter %s,%s', book_id, chapter) #text list has book and chapter as first two elements of the array for verse_number, verse_text in textlist.iteritems(): @@ -135,6 +217,21 @@ class BibleDB(QtCore.QObject): self.commit() def create_verse(self, book_id, chapter, verse, text): + """ + Add a single verse to a chapter. + + ``book_id`` + The id of the book being appended. + + ``chapter`` + The chapter number. + + ``verse`` + The verse number. + + ``text`` + The verse text. + """ if not isinstance(text, unicode): details = chardet.detect(text) text = unicode(text, details[u'encoding']) @@ -241,8 +338,6 @@ class BibleDB(QtCore.QObject): count = self.session.query(Verse.chapter).join(Book)\ .filter(Book.name==book)\ .distinct().count() - #verse = self.session.query(Verse).join(Book).filter( - # Book.name == bookname).order_by(Verse.chapter.desc()).first() if not count: return 0 else: @@ -254,9 +349,6 @@ class BibleDB(QtCore.QObject): .filter(Book.name==book)\ .filter(Verse.chapter==chapter)\ .count() - #verse = self.session.query(Verse).join(Book).filter( - # Book.name == bookname).filter( - # Verse.chapter == chapter).order_by(Verse.verse.desc()).first() if not count: return 0 else: diff --git a/openlp/plugins/bibles/lib/http.py b/openlp/plugins/bibles/lib/http.py index bd4ad8e0b..b14f9b3a2 100644 --- a/openlp/plugins/bibles/lib/http.py +++ b/openlp/plugins/bibles/lib/http.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -27,36 +27,60 @@ import logging import urllib2 import os import sqlite3 +import re -from BeautifulSoup import BeautifulSoup +from BeautifulSoup import BeautifulSoup, Tag, NavigableString from openlp.core.lib import Receiver -from common import BibleCommon, SearchResults +from openlp.core.utils import AppLocation +from common import BibleCommon, SearchResults, unescape from db import BibleDB from openlp.plugins.bibles.lib.models import Book log = logging.getLogger(__name__) class HTTPBooks(object): + """ + A wrapper class around a small SQLite database which contains the books, + chapter counts and verse counts for the web download Bibles. This class + contains a singleton "cursor" so that only one connection to the SQLite + database is ever used. + """ cursor = None @staticmethod def get_cursor(): + """ + Return the cursor object. Instantiate one if it doesn't exist yet. + """ if HTTPBooks.cursor is None: - filepath = os.path.join(os.path.dirname(os.path.abspath(__file__)), - u'..', u'resources', u'httpbooks.sqlite') + filepath = os.path.join( + AppLocation.get_directory(AppLocation.PluginsDir), u'bibles', + u'resources', u'httpbooks.sqlite') conn = sqlite3.connect(filepath) HTTPBooks.cursor = conn.cursor() return HTTPBooks.cursor @staticmethod def run_sql(query, parameters=()): + """ + Run an SQL query on the database, returning the results. + + ``query`` + The actual SQL query to run. + + ``parameters`` + Any variable parameters to add to the query. + """ cursor = HTTPBooks.get_cursor() cursor.execute(query, parameters) return cursor.fetchall() @staticmethod def get_books(): + """ + Return a list of all the books of the Bible. + """ books = HTTPBooks.run_sql(u'SELECT id, testament_id, name, ' u'abbreviation, chapters FROM books ORDER BY id') book_list = [] @@ -72,6 +96,12 @@ class HTTPBooks(object): @staticmethod def get_book(name): + """ + Return a book by name or abbreviation. + + ``name`` + The name or abbreviation of the book. + """ if not isinstance(name, unicode): name = unicode(name) books = HTTPBooks.run_sql(u'SELECT id, testament_id, name, ' @@ -90,6 +120,15 @@ class HTTPBooks(object): @staticmethod def get_chapter(name, chapter): + """ + Return the chapter details for a specific chapter of a book. + + ``name`` + The name or abbreviation of a book. + + ``chapter`` + The chapter number. + """ if not isinstance(name, int): chapter = int(chapter) book = HTTPBooks.get_book(name) @@ -107,6 +146,12 @@ class HTTPBooks(object): @staticmethod def get_chapter_count(book): + """ + Return the number of chapters in a book. + + ``book`` + The name or abbreviation of the book. + """ details = HTTPBooks.get_book(book) if details: return details[u'chapters'] @@ -114,6 +159,15 @@ class HTTPBooks(object): @staticmethod def get_verse_count(book, chapter): + """ + Return the number of verses in a chapter. + + ``book`` + The name or abbreviation of the book. + + ``chapter`` + The number of the chapter. + """ details = HTTPBooks.get_chapter(book, chapter) if details: return details[u'verses'] @@ -121,7 +175,9 @@ class HTTPBooks(object): class BGExtract(BibleCommon): - log.info(u'%s BGExtract loaded', __name__) + """ + Extract verses from BibleGateway + """ def __init__(self, proxyurl=None): log.debug(u'init %s', proxyurl) @@ -131,7 +187,7 @@ class BGExtract(BibleCommon): """ Access and decode bibles via the BibleGateway website - ``Version`` + ``version`` The version of the bible like 31 for New International version ``bookname`` @@ -144,54 +200,81 @@ class BGExtract(BibleCommon): urlstring = u'http://www.biblegateway.com/passage/?search=%s+%s' \ u'&version=%s' % (bookname, chapter, version) log.debug(u'BibleGateway url = %s' % urlstring) - xml_string = self._get_web_text(urlstring, self.proxyurl) - verseSearch = u' -1: - # clear out string - verseText = u'' - versePos = xml_string.find(u'', versePos) + 6 - i = xml_string.find(verseSearch, versePos + 1) - # Not sure if this is needed now - if i == -1: - i = xml_string.find(u' 0 and j < i: - i = j - verseText = xml_string[versePos + 7 : i ] - # store the verse - bible[verse] = self._clean_text(verseText) - versePos = -1 - else: - verseText = xml_string[versePos: i] - start_tag = verseText.find(verseFootnote) - while start_tag > -1: - end_tag = verseText.find(u'') - verseText = verseText[:start_tag] + verseText[end_tag + 6:len(verseText)] - start_tag = verseText.find(verseFootnote) - # Chop off verse and start again - xml_string = xml_string[i:] - #look for the next verse - versePos = xml_string.find(verseSearch) - # store the verse - bible[verse] = self._clean_text(verseText) - verse += 1 - return SearchResults(bookname, chapter, bible) + # Let's get the page, and then open it in BeautifulSoup, so as to + # attempt to make "easy" work of bad HTML. + page = urllib2.urlopen(urlstring) + Receiver.send_message(u'process_events') + soup = BeautifulSoup(page) + Receiver.send_message(u'process_events') + verses = soup.find(u'div', u'result-text-style-normal') + verse_number = 0 + verse_list = {0: u''} + # http://www.codinghorror.com/blog/2009/11/parsing-html-the-cthulhu-way.html + # This is a PERFECT example of opening the Cthulu tag! + # O Bible Gateway, why doth ye such horrific HTML produce? + for verse in verses: + Receiver.send_message(u'process_events') + if isinstance(verse, Tag) and verse.name == u'div' and filter(lambda a: a[0] == u'class', verse.attrs)[0][1] == u'footnotes': + break + if isinstance(verse, Tag) and verse.name == u'sup' and filter(lambda a: a[0] == u'class', verse.attrs)[0][1] != u'versenum': + continue + if isinstance(verse, Tag) and verse.name == u'p' and not verse.contents: + continue + if isinstance(verse, Tag) and (verse.name == u'p' or verse.name == u'font') and verse.contents: + for item in verse.contents: + Receiver.send_message(u'process_events') + if isinstance(item, Tag) and (item.name == u'h4' or item.name == u'h5'): + continue + if isinstance(item, Tag) and item.name == u'sup' and filter(lambda a: a[0] == u'class', item.attrs)[0][1] != u'versenum': + continue + if isinstance(item, Tag) and item.name == u'p' and not item.contents: + continue + if isinstance(item, Tag) and item.name == u'sup': + verse_number = int(str(item.contents[0])) + verse_list[verse_number] = u'' + continue + if isinstance(item, Tag) and item.name == u'font': + for subitem in item.contents: + Receiver.send_message(u'process_events') + if isinstance(subitem, Tag) and subitem.name == u'sup' and filter(lambda a: a[0] == u'class', subitem.attrs)[0][1] != u'versenum': + continue + if isinstance(subitem, Tag) and subitem.name == u'p' and not subitem.contents: + continue + if isinstance(subitem, Tag) and subitem.name == u'sup': + verse_number = int(str(subitem.contents[0])) + verse_list[verse_number] = u'' + continue + if isinstance(subitem, NavigableString): + verse_list[verse_number] = verse_list[verse_number] + subitem.replace(u' ', u' ') + continue + if isinstance(item, NavigableString): + verse_list[verse_number] = verse_list[verse_number] + item.replace(u' ', u' ') + continue + if isinstance(verse, Tag) and verse.name == u'sup': + verse_number = int(str(verse.contents[0])) + verse_list[verse_number] = u'' + continue + if isinstance(verse, NavigableString): + if not isinstance(verse, unicode): + verse = unicode(verse, u'utf8') + verse_list[verse_number] = verse_list[verse_number] + \ + unescape(verse.replace(u' ', u' ')) + # Delete the "0" element, since we don't need it, it's just there for + # some stupid initial whitespace, courtesy of Bible Gateway. + del verse_list[0] + # Finally, return the list of verses in a "SearchResults" object. + return SearchResults(bookname, chapter, verse_list) class CWExtract(BibleCommon): - log.info(u'%s CWExtract loaded', __name__) + """ + Extract verses from CrossWalk/BibleStudyTools + """ def __init__(self, proxyurl=None): log.debug(u'init %s', proxyurl) self.proxyurl = proxyurl def get_bible_chapter(self, version, bookname, chapter): - log.debug(u'%s %s, %s, %s', __name__, version, bookname, chapter) """ Access and decode bibles via the Crosswalk website @@ -206,28 +289,47 @@ class CWExtract(BibleCommon): """ log.debug(u'get_bible_chapter %s,%s,%s', version, bookname, chapter) - bookname = bookname.replace(u' ', u'') + urlbookname = bookname.replace(u' ', u'-') chapter_url = u'http://www.biblestudytools.com/%s/%s/%s.html' % \ - (version, bookname.lower(), chapter) + (version, urlbookname.lower(), chapter) log.debug(u'URL: %s', chapter_url) page = urllib2.urlopen(chapter_url) + Receiver.send_message(u'process_events') if not page: return None soup = BeautifulSoup(page) + Receiver.send_message(u'process_events') htmlverses = soup.findAll(u'span', u'versetext') verses = {} + reduce_spaces = re.compile(r'[ ]{2,}') + fix_punctuation = re.compile(r'[ ]+([.,;])') for verse in htmlverses: Receiver.send_message(u'process_events') versenumber = int(verse.contents[0].contents[0]) versetext = u'' for part in verse.contents: - if str(part)[0] != u'<': + Receiver.send_message(u'process_events') + if isinstance(part, NavigableString): versetext = versetext + part - elif part and part.attrMap and part.attrMap[u'class'] == u'WordsOfChrist': + elif part and part.attrMap and \ + (part.attrMap[u'class'] == u'WordsOfChrist' or \ + part.attrMap[u'class'] == u'strongs'): for subpart in part.contents: - if str(subpart)[0] != '<': + Receiver.send_message(u'process_events') + if isinstance(subpart, NavigableString): versetext = versetext + subpart + elif subpart and subpart.attrMap and \ + subpart.attrMap[u'class'] == u'strongs': + for subsub in subpart.contents: + Receiver.send_message(u'process_events') + if isinstance(subsub, NavigableString): + versetext = versetext + subsub + Receiver.send_message(u'process_events') + # Fix up leading and trailing spaces, multiple spaces, and spaces + # between text and , and . versetext = versetext.strip(u'\n\r\t ') + versetext = reduce_spaces.sub(u' ', versetext) + versetext = fix_punctuation.sub(r'\1', versetext) verses[versenumber] = versetext return SearchResults(bookname, chapter, verses) @@ -266,6 +368,10 @@ class HTTPBible(BibleDB): self.proxy_password = None def do_import(self): + """ + Run the import. This method overrides the parent class method. Returns + ``True`` on success, ``False`` on failure. + """ self.wizard.ImportProgressBar.setMaximum(2) self.wizard.incrementProgressBar('Registering bible...') self.create_meta(u'download source', self.download_source) @@ -324,10 +430,12 @@ class HTTPBible(BibleDB): ## we get a correct book. For example it is possible ## to request ac and get Acts back. bookname = search_results.get_book() + Receiver.send_message(u'process_events') # check to see if book/chapter exists db_book = self.get_book(bookname) self.create_chapter(db_book.id, search_results.get_chapter(), search_results.get_verselist()) + Receiver.send_message(u'process_events') Receiver.send_message(u'bible_hideprogress') Receiver.send_message(u'process_events') return BibleDB.get_verses(self, reference_list) @@ -349,17 +457,43 @@ class HTTPBible(BibleDB): return None def get_books(self): + """ + Return the list of books. + """ return [Book.populate(name=book['name']) for book in HTTPBooks.get_books()] def lookup_book(self, book): + """ + Look up the name of a book. + """ return HTTPBooks.get_book(book) def get_chapter_count(self, book): + """ + Return the number of chapters in a particular book. + """ return HTTPBooks.get_chapter_count(book) def get_verse_count(self, book, chapter): + """ + Return the number of verses for the specified chapter and book. + + ``book`` + The name of the book. + + ``chapter`` + The chapter whose verses are being counted. + """ return HTTPBooks.get_verse_count(book, chapter) def set_proxy_server(self, server): + """ + Sets the proxy server. + + **Note: This is not actually used.** + + ``server`` + The hostname or IP address of the proxy server. + """ self.proxy_server = server diff --git a/openlp/plugins/bibles/lib/manager.py b/openlp/plugins/bibles/lib/manager.py index d24982532..8e622963d 100644 --- a/openlp/plugins/bibles/lib/manager.py +++ b/openlp/plugins/bibles/lib/manager.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -24,7 +24,6 @@ ############################################################################### import logging -import os from common import parse_reference from opensong import OpenSongBible @@ -61,6 +60,9 @@ class BibleFormat(object): def get_class(id): """ Return the appropriate imeplementation class. + + ``id`` + The Bible format. """ if id == BibleFormat.OSIS: return OSISBible @@ -75,6 +77,9 @@ class BibleFormat(object): @staticmethod def list(): + """ + Return a list of the supported Bible formats. + """ return [ BibleFormat.OSIS, BibleFormat.CSV, @@ -123,19 +128,21 @@ class BibleManager(object): log.debug(u'Bible Files %s', files) self.db_cache = {} for filename in files: - name, extension = os.path.splitext(filename) - self.db_cache[name] = BibleDB(self.parent, path=self.path, name=name, config=self.config) + bible = BibleDB(self.parent, path=self.path, file=filename, + config=self.config) + name = bible.get_name() + 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') 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') - web_bible = HTTPBible(self.parent, path=self.path, name=name, - config=self.config, download_source=source.value, - download_name=download_name) + web_bible = HTTPBible(self.parent, path=self.path, + file=filename, config=self.config, + download_source=source.value, download_name=download_name) if meta_proxy: web_bible.set_proxy_server(meta_proxy.value) - #del self.db_cache[name] self.db_cache[name] = web_bible log.debug(u'Bibles reloaded') @@ -164,7 +171,7 @@ class BibleManager(object): importer = class_(self.parent, **kwargs) name = importer.register(self.import_wizard) self.db_cache[name] = importer - return importer.do_import() + return importer def get_bibles(self): """ @@ -246,7 +253,7 @@ class BibleManager(object): """ if not isinstance(name, unicode): name = unicode(name) - for bible, db_object in self.db_cache.iteritems(): + for bible in self.db_cache.keys(): log.debug(u'Bible from cache in is_new_bible %s', bible) if not isinstance(bible, unicode): bible = unicode(bible) diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index 278988594..ab067575b 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -29,7 +29,7 @@ import time from PyQt4 import QtCore, QtGui from openlp.core.lib import MediaManagerItem, Receiver, str_to_bool, \ - BaseListWithDnD + BaseListWithDnD, ItemCapabilities from openlp.plugins.bibles.forms import ImportWizardForm log = logging.getLogger(__name__) @@ -45,6 +45,7 @@ class BibleListView(BaseListWithDnD): def resizeEvent(self, event): self.parent.onListViewResize(event.size().width(), event.size().width()) + class BibleMediaItem(MediaManagerItem): """ This is the custom media manager item for Bibles. @@ -56,21 +57,30 @@ class BibleMediaItem(MediaManagerItem): self.ConfigSection = title self.IconPath = u'songs/song' self.ListViewWithDnD_class = BibleListView - self.servicePath = None self.lastReference = [] + self.addToServiceItem = True MediaManagerItem.__init__(self, parent, icon, title) # place to store the search results self.search_results = {} QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'openlpreloadbibles'), self.reloadBibles) + def _decodeQtObject(self, listobj, key): + obj = listobj[QtCore.QString(key)] + if isinstance(obj, QtCore.QVariant): + obj = obj.toPyObject() + return unicode(obj) + def initPluginNameVisible(self): self.PluginNameVisible = self.trUtf8('Bible') def requiredIcons(self): MediaManagerItem.requiredIcons(self) + self.hasImportIcon = True + self.hasNewIcon = False self.hasEditIcon = False self.hasDeleteIcon = False + self.addToServiceItem = True def addEndHeaderBar(self): self.SearchTabWidget = QtGui.QTabWidget(self) @@ -244,6 +254,8 @@ class BibleMediaItem(MediaManagerItem): QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'config_updated'), self.configUpdated) # Other stuff + QtCore.QObject.connect(self.QuickSearchEdit, + QtCore.SIGNAL(u'returnPressed()'), self.onQuickSearchButton) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'bible_showprogress'), self.onSearchProgressShow) QtCore.QObject.connect(Receiver.get_receiver(), @@ -255,8 +267,9 @@ class BibleMediaItem(MediaManagerItem): MediaManagerItem.addListViewToToolBar(self) # Progress Bar self.SearchProgress = QtGui.QProgressBar(self) - self.SearchProgress.setFormat('%p%') - self.SearchProgress.setMaximum(3) + self.SearchProgress.setFormat('') + self.SearchProgress.setMinimum(0) + self.SearchProgress.setMaximum(0) self.SearchProgress.setGeometry(self.ListView.geometry().left(), self.ListView.geometry().top(), 81, 23) self.SearchProgress.setVisible(False) @@ -340,9 +353,10 @@ class BibleMediaItem(MediaManagerItem): def onSearchProgressShow(self): self.SearchProgress.setVisible(True) - self.SearchProgress.setMinimum(0) - self.SearchProgress.setMaximum(2) - self.SearchProgress.setValue(1) + Receiver.send_message(u'process_events') + #self.SearchProgress.setMinimum(0) + #self.SearchProgress.setMaximum(2) + #self.SearchProgress.setValue(1) def onSearchProgressHide(self): self.SearchProgress.setVisible(False) @@ -366,7 +380,7 @@ class BibleMediaItem(MediaManagerItem): unicode(self.AdvancedBookComboBox.currentText()), self.AdvancedBookComboBox.itemData(item).toInt()[0]) - def onNewClick(self): + def onImportClick(self): self.bibleimportform = ImportWizardForm(self, self.parent.config, self.parent.manager, self.parent) self.bibleimportform.exec_() @@ -425,7 +439,7 @@ class BibleMediaItem(MediaManagerItem): if self.search_results: self.displayResults(bible) - def generateSlideData(self, service_item): + def generateSlideData(self, service_item, item=None): log.debug(u'generating slide data') items = self.ListView.selectedIndexes() if len(items) == 0: @@ -434,7 +448,8 @@ class BibleMediaItem(MediaManagerItem): raw_slides = [] raw_footer = [] bible_text = u'' - service_item.autoPreviewAllowed = True + service_item.add_capability(ItemCapabilities.AllowsPreview) + service_item.add_capability(ItemCapabilities.AllowsLoop) #If we want to use a 2nd translation / version bible2 = u'' if self.SearchTabWidget.currentIndex() == 0: @@ -451,15 +466,17 @@ class BibleMediaItem(MediaManagerItem): # Let's loop through the main lot, and assemble our verses for item in items: bitem = self.ListView.item(item.row()) - reference = bitem.data(QtCore.Qt.UserRole).toPyObject() - bible = unicode(reference[QtCore.QString('bible')]) - book = unicode(reference[QtCore.QString('book')]) - chapter = unicode(reference[QtCore.QString('chapter')]) - verse = unicode(reference[QtCore.QString('verse')]) - text = unicode(reference[QtCore.QString('text')]) - version = unicode(reference[QtCore.QString('version')]) - copyright = unicode(reference[QtCore.QString('copyright')]) - permission = unicode(reference[QtCore.QString('permission')]) + reference = bitem.data(QtCore.Qt.UserRole) + if isinstance(reference, QtCore.QVariant): + reference = reference.toPyObject() + bible = self._decodeQtObject(reference, 'bible') + book = self._decodeQtObject(reference, 'book') + chapter = self._decodeQtObject(reference, 'chapter') + verse = self._decodeQtObject(reference, 'verse') + text = self._decodeQtObject(reference, 'text') + version = self._decodeQtObject(reference, 'version') + copyright = self._decodeQtObject(reference, 'copyright') + permission = self._decodeQtObject(reference, 'permission') if self.parent.settings_tab.display_style == 1: verse_text = self.formatVerse(old_chapter, chapter, verse, u'(u', u')') elif self.parent.settings_tab.display_style == 2: @@ -491,7 +508,11 @@ class BibleMediaItem(MediaManagerItem): if self.parent.settings_tab.layout_style == 0: raw_slides.append(bible_text) bible_text = u'' - service_item.title = u'%s %s' % (book, verse_text) + if not service_item.title: + service_item.title = u'%s %s' % (book, verse_text) + elif service_item.title.find(self.trUtf8(u'etc')) == -1: + service_item.title = u'%s, %s' \ + % (service_item.title, self.trUtf8(u'etc')) if len(self.parent.settings_tab.bible_theme) == 0: service_item.theme = None else: @@ -563,7 +584,7 @@ class BibleMediaItem(MediaManagerItem): permission = u'' else: permission = permission.value - for count, verse in enumerate(self.search_results): + for count, verse in enumerate(self.search_results): bible_text = u' %s %d:%d (%s)' % \ (verse.book.name, verse.chapter, verse.verse, bible) bible_verse = QtGui.QListWidgetItem(bible_text) diff --git a/openlp/plugins/bibles/lib/models.py b/openlp/plugins/bibles/lib/models.py index 2802cb27f..4631b1e32 100644 --- a/openlp/plugins/bibles/lib/models.py +++ b/openlp/plugins/bibles/lib/models.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/plugins/bibles/lib/opensong.py b/openlp/plugins/bibles/lib/opensong.py index 6fa18cf6d..2f7e3e451 100644 --- a/openlp/plugins/bibles/lib/opensong.py +++ b/openlp/plugins/bibles/lib/opensong.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -63,7 +63,8 @@ class OpenSongBible(BibleDB): Loads a Bible from file. """ log.debug(u'Starting OpenSong import from "%s"' % self.filename) - self.filename = unicode(self.filename, u'utf-8') + if not isinstance(self.filename, unicode): + self.filename = unicode(self.filename, u'utf8') self.wizard.incrementProgressBar(u'Preparing for import...') file = None success = True @@ -102,7 +103,7 @@ class OpenSongBible(BibleDB): finally: if file: file.close() - if self.stop_import: + if self.stop_import_flag: self.wizard.incrementProgressBar(u'Import canceled!') return False else: diff --git a/openlp/plugins/bibles/lib/osis.py b/openlp/plugins/bibles/lib/osis.py index 658ac8a0b..4416bb2c6 100644 --- a/openlp/plugins/bibles/lib/osis.py +++ b/openlp/plugins/bibles/lib/osis.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -33,6 +33,7 @@ import re from PyQt4 import QtCore from openlp.core.lib import Receiver +from openlp.core.utils import AppLocation from db import BibleDB log = logging.getLogger(__name__) @@ -64,11 +65,12 @@ class OSISBible(BibleDB): self.l_regex = re.compile(r'') self.w_regex = re.compile(r'') self.q_regex = re.compile(r'') + self.trans_regex = re.compile(r'(.*?)') self.spaces_regex = re.compile(r'([ ]{2,})') self.books = {} - filepath = os.path.split(os.path.abspath(__file__))[0] - filepath = os.path.abspath(os.path.join( - filepath, u'..', u'resources', u'osisbooks.csv')) + filepath = os.path.join( + AppLocation.get_directory(AppLocation.PluginsDir), u'bibles', + u'resources', u'osisbooks.csv') fbibles = None try: fbibles = open(filepath, u'r') @@ -113,12 +115,14 @@ class OSISBible(BibleDB): osis = codecs.open(self.filename, u'r', details['encoding']) last_chapter = 0 testament = 1 + match_count = 0 db_book = None for file_record in osis: if self.stop_import_flag: break match = self.verse_regex.search(file_record) if match: + match_count += 1 book = match.group(1) chapter = int(match.group(2)) verse = int(match.group(3)) @@ -156,15 +160,18 @@ class OSISBible(BibleDB): verse_text = self.l_regex.sub(u'', verse_text) verse_text = self.w_regex.sub(u'', verse_text) verse_text = self.q_regex.sub(u'', verse_text) + verse_text = self.trans_regex.sub(u'', verse_text) verse_text = verse_text.replace(u'', u'')\ .replace(u'', u'').replace(u'', u'')\ .replace(u'', u'').replace(u'', u'')\ - .replace(u'', u'') + .replace(u'', u'').replace(u'', u'') verse_text = self.spaces_regex.sub(u' ', verse_text) self.create_verse(db_book.id, chapter, verse, verse_text) Receiver.send_message(u'process_events') self.commit() self.wizard.incrementProgressBar(u'Finishing import...') + if match_count == 0: + success = False except: log.exception(u'Loading bible from OSIS file failed') success = False diff --git a/openlp/plugins/bibles/test/__init__.py b/openlp/plugins/bibles/test/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/openlp/plugins/bibles/test/biblebooks_msg_short.csv b/openlp/plugins/bibles/test/biblebooks_msg_short.csv deleted file mode 100644 index d6af7009d..000000000 --- a/openlp/plugins/bibles/test/biblebooks_msg_short.csv +++ /dev/null @@ -1,8 +0,0 @@ -1,1,"Genesis","GEN" -2,1,"Exodus","EXOD" -3,1,"Leviticus","LEV" -4,1,"Numbers","NUM" -47,2,"Matthew","MATT" -48,2,"Mark","MARK" -49,2,"Luke","LUKE" -50,2,"John","JOHN" diff --git a/openlp/plugins/bibles/test/biblebooks_niv_short.csv b/openlp/plugins/bibles/test/biblebooks_niv_short.csv deleted file mode 100644 index 9f16417e7..000000000 --- a/openlp/plugins/bibles/test/biblebooks_niv_short.csv +++ /dev/null @@ -1,9 +0,0 @@ -1,1,"Genesis","GEN" -2,1,"Exodus","EXOD" -3,1,"Leviticus","LEV" -4,1,"Numbers","NUM" -46,1,"Malachi","MAL" -47,2,"Matthew","MATT" -48,2,"Mark","MARK" -49,2,"Luke","LUKE" -50,2,"John","JOHN" diff --git a/openlp/plugins/bibles/test/bibleverses_msg_short.csv b/openlp/plugins/bibles/test/bibleverses_msg_short.csv deleted file mode 100644 index 8eb4f3851..000000000 --- a/openlp/plugins/bibles/test/bibleverses_msg_short.csv +++ /dev/null @@ -1,35 +0,0 @@ -"Genesis",1,1,"First this: God created the Heavens and Earth - all you see, all you don't see." -"Genesis",1,2,"Earth was a soup of nothingness, a bottomless emptiness, an inky blackness. God's Spirit brooded like a bird above the watery abyss." -"Exodus",1,1,"These are the names of the Israelites who went to Egypt with Jacob, each bringing his family members:" -"Exodus",1,2,"Reuben, Simeon, Levi, and Judah," -"Exodus",2,1,"A man from the family of Levi married a Levite woman." -"Exodus",2,2,"The woman became pregnant and had a son. She saw there was something special about him and hid him. She hid him for three months." -"Leviticus",1,1,"God called Moses and spoke to him from the Tent of Meeting:" -"Leviticus",1,2,"""Speak to the People of Israel. Tell them, When anyone presents an offering to God, present an animal from either the herd or the flock." -"Leviticus",1,3,"""If the offering is a Whole-Burnt-Offering from the herd, present a male without a defect at the entrance to the Tent of Meeting that it may be accepted by God." -"Numbers",1,1,"God spoke to Moses in the Wilderness of Sinai at the Tent of Meeting on the first day of the second month in the second year after they had left Egypt. He said," -"Numbers",1,2,"""Number the congregation of the People of Israel by clans and families, writing down the names of every male." -"Matthew",1,1,"The family tree of Jesus Christ, David's son, Abraham's son:" -"Matthew",1,2,"Abraham had Isaac, Isaac had Jacob, Jacob had Judah and his brothers," -"Matthew",1,3,"Judah had Perez and Zerah (the mother was Tamar), Perez had Hezron, Hezron had Aram," -"Matthew",1,4,"Aram had Amminadab, Amminadab had Nahshon, Nahshon had Salmon," -"Matthew",1,5,"Salmon had Boaz (his mother was Rahab), Boaz had Obed (Ruth was the mother), Obed had Jesse," -"Matthew",1,6,"Jesse had David, and David became king. David had Solomon (Uriah's wife was the mother)," -"Matthew",1,7,"Solomon had Rehoboam, Rehoboam had Abijah, Abijah had Asa," -"Matthew",1,8,"Asa had Jehoshaphat, Jehoshaphat had Joram, Joram had Uzziah," -"Matthew",2,1,"After Jesus was born in Bethlehem village, Judah territory - this was during Herod's kingship - a band of scholars arrived in Jerusalem from the East." -"Matthew",2,2,"They asked around, ""Where can we find and pay homage to the newborn King of the Jews? We observed a star in the eastern sky that "Matthew",3,1,"While Jesus was living in the Galilean hills, John, called ""the Baptizer,"" was preaching in the desert country of Judea." -"Matthew",3,2,"His message was simple and austere, like his desert surroundings: ""Change your life. God's kingdom is here.""" -"Matthew",3,3,"John and his message were authorized by Isaiah's prophecy: Thunder in the desert! Prepare for God's arrival! Make the road smooth and straight!" -"Mark",1,1,"The good news of Jesus Christ - the Message! - begins here," -"Mark",1,2,"following to the letter the scroll of the prophet Isaiah. Watch closely: I'm sending my preacher ahead of you; He'll make the road smooth for you." -"Mark",1,3,"Thunder in the desert! Prepare for God's arrival! Make the road smooth and straight!" -"Luke",1,1,"So many others have tried their hand at putting together a story of the wonderful harvest of Scripture and history that took place among us," -"Luke",1,2,"using reports handed down by the original eyewitnesses who served this Word with their very lives." -"Luke",1,3,"Since I have investigated all the reports in close detail, starting from the story's beginning, I decided to write it all out for you, most honorable Theophilus," -"John",1,1,"The Word was first, the Word present to God, God present to the Word. The Word was God," -"John",1,2,"in readiness for God from day one." -"John",1,3,"Everything was created through him; nothing - not one thing! - came into being without him." -"John",2,1,"Three days later there was a wedding in the village of Cana in Galilee. Jesus' mother was there." -"John",2,2,"Jesus and his disciples were guests also." -"John",2,3,"When they started running low on wine at the wedding banquet, Jesus' mother told him, ""They're just about out of wine.""" diff --git a/openlp/plugins/bibles/test/bibleverses_niv_short.csv b/openlp/plugins/bibles/test/bibleverses_niv_short.csv deleted file mode 100644 index df1f5c436..000000000 --- a/openlp/plugins/bibles/test/bibleverses_niv_short.csv +++ /dev/null @@ -1,35 +0,0 @@ -"Genesis",1,1,"In the beginning God created the heavens and the earth." -"Genesis",1,2,"Now the earth was formless and empty, darkness was over the surface of the deep, and the Spirit of God was hovering over the waters." -"Exodus",1,1,"These are the names of the sons of Israel who went to Egypt with Jacob, each with his family:" -"Exodus",1,2,"Reuben, Simeon, Levi and Judah;" -"Exodus",2,1,"Now a man of the house of Levi married a Levite woman," -"Exodus",2,2,"and she became pregnant and gave birth to a son. When she saw that he was a fine child, she hid him for three months." -"Leviticus",1,1,"The Lord called to Moses and spoke to him from the Tent of Meeting. He said," -"Leviticus",1,2,"""Speak to the Israelites and say to them: 'When any of you brings an offering to the Lord, bring as your offering an animal from either the herd or the flock." -"Leviticus",1,3,"""'If the offering is a burnt offering from the herd, he is to offer a male without defect. He must present it at the entrance to the Tent of Meeting so that it will be acceptable to the Lord." -"Numbers",1,1,"The Lord spoke to Moses in the Tent of Meeting in the Desert of Sinai on the first day of the second month of the second year after the Israelites came out of Egypt. He said:" -"Numbers",1,2,"""Take a census of the whole Israelite community by their clans and families, listing every man by name, one by one." -"Matthew",1,1,"A record of the genealogy of Jesus Christ the son of David, the son of Abraham:" -"Matthew",1,2,"Abraham was the father of Isaac," -"Matthew",1,3,"Judah the father of Perez and Zerah, whose mother was Tamar," -"Matthew",1,4,"Ram the father of Amminadab," -"Matthew",1,5,"Salmon the father of Boaz, whose mother was Rahab," -"Matthew",1,6,"and Jesse the father of King David." -"Matthew",1,7,"Solomon the father of Rehoboam," -"Matthew",1,8,"Asa the father of Jehoshaphat," -"Matthew",2,1,"After Jesus was born in Bethlehem in Judea, during the time of King Herod, Magi from the east came to Jerusalem" -"Matthew",2,2,"and asked, ""Where is the one who has been born king of the Jews? We saw his star in the east and have come to worship "Matthew",3,1,"In those days John the Baptist came, preaching in the Desert of Judea" -"Matthew",3,2,"and saying, ""Repent, for the kingdom of heaven is near.""" -"Matthew",3,3,"This is he who was spoken of through the prophet Isaiah: ""A voice of one calling in the desert, 'Prepare the way for the Lord, make straight paths for him.'""" -"Mark",1,1,"The beginning of the gospel about Jesus Christ, the Son of God." -"Mark",1,2,"It is written in Isaiah the prophet: ""I will send my messenger ahead of you, who will prepare your way""--" -"Mark",1,3,"""a voice of one calling in the desert, 'Prepare the way for the Lord, make straight paths for him.'""" -"Luke",1,1,"Many have undertaken to draw up an account of the things that have been fulfilled among us," -"Luke",1,2,"just as they were handed down to us by those who from the first were eyewitnesses and servants of the word." -"Luke",1,3,"Therefore, since I myself have carefully investigated everything from the beginning, it seemed good also to me to write an orderly account for you, most excellent Theophilus," -"John",1,1,"In the beginning was the Word, and the Word was with God, and the Word was God." -"John",1,2,"He was with God in the beginning." -"John",1,3,"Through him all things were made; without him nothing was made that has been made." -"John",2,1,"On the third day a wedding took place at Cana in Galilee. Jesus' mother was there," -"John",2,2,"and Jesus and his disciples had also been invited to the wedding." -"John",2,3,"When the wine was gone, Jesus' mother said to him, ""They have no more wine.""" diff --git a/openlp/plugins/bibles/test/rt b/openlp/plugins/bibles/test/rt deleted file mode 100755 index 84998ec9b..000000000 --- a/openlp/plugins/bibles/test/rt +++ /dev/null @@ -1 +0,0 @@ -py.test --nocapture test_bibleManager.py diff --git a/openlp/plugins/bibles/test/test_bibleManager.py b/openlp/plugins/bibles/test/test_bibleManager.py deleted file mode 100644 index 00af3a2c9..000000000 --- a/openlp/plugins/bibles/test/test_bibleManager.py +++ /dev/null @@ -1,117 +0,0 @@ -""" -OpenLP - Open Source Lyrics Projection -Copyright (c) 2008 Raoul Snyman -Portions copyright (c) 2008 Martin Thompson, Tim Bentley - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free Software -Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place, Suite 330, Boston, MA 02111-1307 USA -""" - -import logging -import os -import os.path -import sys - -from openlp.plugins.bibles.lib.biblemanager import BibleManager - -mypath = os.path.split(os.path.abspath(__file__))[0] -sys.path.insert(0,(os.path.join(mypath, '..', '..','..','..'))) - -logging.basicConfig(level=logging.DEBUG, - format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s', - datefmt='%m-%d %H:%M', - filename='plugins.log', - filemode='w') - -console = logging.StreamHandler() -# set a format which is simpler for console use -formatter = logging.Formatter(u'%(name)-12s: %(levelname)-8s %(message)s') -# tell the handler to use this format -console.setFormatter(formatter) -logging.getLogger(u'').addHandler(console) -log = logging.getLogger(u'') - -logging.info(u'\nLogging started') - -class TestBibleManager: - log = logging.getLogger(u'testBibleMgr') - def setup_class(self): - log.debug(u'\n.......Register BM') - self.bm = BibleManager() - - def testRegisterCSVBibleFiles(self): - # Register a bible from files - log.debug(u'\n.......testRegisterBibleFiles') - self.bm.registerFileBible(u'TheMessage','biblebooks_msg_short.csv','bibleverses_msg_short.csv') - self.bm.registerFileBible(u'NIV','biblebooks_niv_short.csv','bibleverses_niv_short.csv') - b = self.bm.get_bibles() - for b1 in b: - log.debug( b1) - assert(b1 in b) - - def testRegisterHTTPBible(self): - # Register a bible from files - log.debug( '\n.......testRegisterBibleHTTP') - self.bm.registerHTTPBible(u'asv', u'Crosswalk', u'', u'', u'') - self.bm.registerHTTPBible(u'nasb', u'Biblegateway', u'', u'', u'') - self.bm.registerHTTPBible(u'nkj', u'Biblegateway', - u'http://tigger2:3128/', u'', u'') - b = self.bm.get_bibles() - for b1 in b: - log.debug( b1) - assert(b1 in b) - - - def testGetBibles(self): - log.debug(u'\n.......testGetBibles') - # make sure the shuffled sequence does not lose any elements - b = self.bm.get_bibles() - for b1 in b: - log.debug( b1) - assert(b1 in b) - - def testGetBibleBooks(self): - log.debug(u'\n.......testGetBibleBooks') - c = self.bm.get_bible_books(u'NIV') - for c1 in c: - log.debug( c1) - assert(c1 in c) - - def testGetBookChapterCount(self): - log.debug(u'\n.......testGetBookChapterCount') - assert(self.bm.get_book_chapter_count(u'Matthew') == '28') - - def testGetBookVerseCount(self): - log.debug(u'\n.......testGetBookVerseCount') - assert(self.bm.get_book_verse_count(u'Genesis', 1) == '31') - assert(self.bm.get_book_verse_count(u'Genesis', 2) == '25') - assert(self.bm.get_book_verse_count(u'Matthew', 1) == '25') - assert(self.bm.get_book_verse_count(u'Revelation', 1) == '20') - - def testGetVerseText(self): - log.debug(u'\n.......testGetVerseText') - #c = self.bm.get_verse_text(u'TheMessage",'Genesis',1,2,1) - #log.debug( c ) - #c = self.bm.get_verse_text(u'NIV','Genesis',1,1,2) - #log.debug( c ) - c = self.bm.get_verse_text(u'asv','Genesis',10,1,20) - log.debug( c ) - c = self.bm.get_verse_text(u'nasb','Genesis',10,1,20) - log.debug( c ) - c = self.bm.get_verse_text(u'nkj','Revelation',10,1,20) - log.debug( c ) - - def testLoadBible(self): - log.debug(u'\n.......testLoadBible') - #self.bm.loadBible(u'asv') - #self.bm.loadBible(u'nasb') - #self.bm.loadBible(u'nkj') diff --git a/openlp/plugins/bibles/test/test_bibleManagerAPI.py b/openlp/plugins/bibles/test/test_bibleManagerAPI.py deleted file mode 100644 index 1cae4237b..000000000 --- a/openlp/plugins/bibles/test/test_bibleManagerAPI.py +++ /dev/null @@ -1,93 +0,0 @@ -""" -OpenLP - Open Source Lyrics Projection -Copyright (c) 2008 Raoul Snyman -Portions copyright (c) 2008 Martin Thompson, Tim Bentley - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free Software -Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place, Suite 330, Boston, MA 02111-1307 USA -""" - -import logging -import os -import os.path -import sys - -from openlp.plugins.biblemanager.bibleManager import BibleManager - -mypath = os.path.split(os.path.abspath(__file__))[0] -sys.path.insert(0,(os.path.join(mypath, '..', '..','..','..'))) - -logging.basicConfig(level=logging.DEBUG, - format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s', - datefmt='%m-%d %H:%M', - filename='plugins.log', - filemode='w') - -console = logging.StreamHandler() -# set a format which is simpler for console use -formatter = logging.Formatter(u'%(name)-12s: %(levelname)-8s %(message)s') -# tell the handler to use this format -console.setFormatter(formatter) -logging.getLogger(u'').addHandler(console) -log = logging.getLogger(u'') - -logging.info(u'\nLogging started') - -class TestBibleManager: - log = logging.getLogger(u'testBibleMgr') - def setup_class(self): - log.debug(u'\n.......Register BM') - self.bm = BibleManager() - - def testGetBibles(self): - log.debug(u'\n.......testGetBibles') - # make sure the shuffled sequence does not lose any elements - b = self.bm.getBibles() - for b1 in b: - log.debug( b1) - assert(b1 in b) - - def testGetBibleBooks(self): - log.debug(u'\n.......testGetBibleBooks') - c = self.bm.getBibleBooks(u'asv') - for c1 in c: - log.debug( c1) - assert(c1 in c) - - def testGetBookChapterCount(self): - log.debug(u'\n.......testGetBookChapterCount') - assert(self.bm.getBookChapterCount(u'asv', u'Matthew')[0] == 28) - - def testGetBookVerseCount(self): - log.debug(u'\n.......testGetBookVerseCount') - assert(self.bm.getBookVerseCount(u'asv', u'Genesis', 1)[0] == 31) - assert(self.bm.getBookVerseCount(u'TheMessage', u'Genesis', 2)[0] == 25) - assert(self.bm.getBookVerseCount(u'asv', u'Matthew', 1)[0] == 25) - assert(self.bm.getBookVerseCount(u'TheMessage', u'Revelation', - 1)[0] == 20) - - def testGetVerseText(self): - log.debug(u'\n.......testGetVerseText') - #c = self.bm.getVerseText(u'TheMessage",'Genesis',1,2,1) - #log.debug( c ) - #c = self.bm.getVerseText(u'NIV','Genesis',1,1,2) - #log.debug( c ) - c = self.bm.getVerseText(u'asv', u'Genesis', 10, 1, 20) - log.debug( c ) - c = self.bm.getVerseText(u'TheMessage', u'Genesis', 10, 1, 20) - log.debug( c ) - c = self.bm.getVerseText(u'asv', u'Revelation', 10, 1, 20) - log.debug( c ) - c = self.bm.getVersesFromText(u'asv', u'Jesus wept') - log.debug( c ) - c = self.bm.getVersesFromText(u'TheMessage', u'Jesus wept') - log.debug( c ) diff --git a/openlp/plugins/bibles/test/test_bibleManagerCSV.py b/openlp/plugins/bibles/test/test_bibleManagerCSV.py deleted file mode 100644 index 239338ebf..000000000 --- a/openlp/plugins/bibles/test/test_bibleManagerCSV.py +++ /dev/null @@ -1,61 +0,0 @@ -""" -OpenLP - Open Source Lyrics Projection -Copyright (c) 2008 Raoul Snyman -Portions copyright (c) 2008 Martin Thompson, Tim Bentley - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free Software -Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place, Suite 330, Boston, MA 02111-1307 USA -""" - -import logging -import os -import os.path -import sys - -from openlp.plugins.bibles.lib.biblemanager import BibleManager - -mypath = os.path.split(os.path.abspath(__file__))[0] -sys.path.insert(0,(os.path.join(mypath, '..', '..','..','..'))) - -logging.basicConfig(level=logging.DEBUG, - format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s', - datefmt='%m-%d %H:%M', - filename='plugins.log', - filemode='w') - -console = logging.StreamHandler() -# set a format which is simpler for console use -formatter = logging.Formatter(u'%(name)-12s: %(levelname)-8s %(message)s') -# tell the handler to use this format -console.setFormatter(formatter) -logging.getLogger(u'').addHandler(console) -log = logging.getLogger(u'') - -logging.info(u'\nLogging started') - -class TestBibleManager: - log = logging.getLogger(u'testBibleMgr') - def setup_class(self): - log.debug(u'\n.......Register BM') - self.bm = BibleManager() - - def testRegisterCSVBibleFiles(self): - # Register a bible from files - log.debug(u'\n.......testRegisterBibleFiles') - self.bm.registerCSVFileBible(u'TheMessage', - u'biblebooks_msg_short.csv', u'bibleverses_msg_short.csv') - self.bm.registerCSVFileBible(u'NIV', u'biblebooks_niv_short.csv', - u'bibleverses_niv_short.csv') - b = self.bm.get_bibles() - for b1 in b: - log.debug( b1) - assert(b1 in b) diff --git a/openlp/plugins/bibles/test/test_bibleManagerOSIS.py b/openlp/plugins/bibles/test/test_bibleManagerOSIS.py deleted file mode 100644 index bf1264050..000000000 --- a/openlp/plugins/bibles/test/test_bibleManagerOSIS.py +++ /dev/null @@ -1,58 +0,0 @@ -""" -OpenLP - Open Source Lyrics Projection -Copyright (c) 2008 Raoul Snyman -Portions copyright (c) 2008 Martin Thompson, Tim Bentley - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free Software -Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place, Suite 330, Boston, MA 02111-1307 USA -""" - -import logging -import os -import os.path -import sys - -from openlp.plugins.bibles.lib.biblemanager import BibleManager - -mypath = os.path.split(os.path.abspath(__file__))[0] -sys.path.insert(0,(os.path.join(mypath, '..', '..','..','..'))) - -logging.basicConfig(level=logging.DEBUG, - format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s', - datefmt='%m-%d %H:%M', - filename='plugins.log', - filemode='w') - -console = logging.StreamHandler() -# set a format which is simpler for console use -formatter = logging.Formatter(u'%(name)-12s: %(levelname)-8s %(message)s') -# tell the handler to use this format -console.setFormatter(formatter) -logging.getLogger(u'').addHandler(console) -log = logging.getLogger(u'') - -logging.info(u'\nLogging started') - -class TestBibleManager: - log = logging.getLogger(u'testBibleMgr') - def setup_class(self): - log.debug(u'\n.......Register BM') - self.bm = BibleManager() - - def testRegisterOSISBibleFiles(self): - # Register a bible from files - log.debug(u'\n.......testRegisterOSISBibleFiles') - self.bm.register_osis_file_bible(u'asv', u'asv.osis') - b = self.bm.get_bibles() - for b1 in b: - log.debug( b1) - assert(b1 in b) diff --git a/openlp/plugins/custom/__init__.py b/openlp/plugins/custom/__init__.py index bc50edda3..1a348a0df 100644 --- a/openlp/plugins/custom/__init__.py +++ b/openlp/plugins/custom/__init__.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -21,4 +21,4 @@ # 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 # -############################################################################### \ No newline at end of file +############################################################################### diff --git a/openlp/plugins/custom/customplugin.py b/openlp/plugins/custom/customplugin.py index ac5384390..979df411c 100644 --- a/openlp/plugins/custom/customplugin.py +++ b/openlp/plugins/custom/customplugin.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -69,7 +69,7 @@ class CustomPlugin(Plugin): def about(self): about_text = self.trUtf8('Custom Plugin
This plugin ' 'allows slides to be displayed on the screen in the same way ' - 'songs are. This plugin provides greater freedom over the ' + 'songs are. This plugin provides greater freedom over the ' 'songs plugin.
') return about_text diff --git a/openlp/plugins/custom/forms/__init__.py b/openlp/plugins/custom/forms/__init__.py index 994868dab..4a4a88237 100644 --- a/openlp/plugins/custom/forms/__init__.py +++ b/openlp/plugins/custom/forms/__init__.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -23,4 +23,4 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from editcustomform import EditCustomForm \ No newline at end of file +from editcustomform import EditCustomForm diff --git a/openlp/plugins/custom/forms/editcustomdialog.py b/openlp/plugins/custom/forms/editcustomdialog.py index f2fa195cb..5f3fe7614 100644 --- a/openlp/plugins/custom/forms/editcustomdialog.py +++ b/openlp/plugins/custom/forms/editcustomdialog.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -24,13 +24,14 @@ ############################################################################### from PyQt4 import QtCore, QtGui -from openlp.core.lib import build_icon class Ui_customEditDialog(object): def setupUi(self, customEditDialog): customEditDialog.setObjectName(u'customEditDialog') customEditDialog.resize(590, 541) - icon = build_icon(u':/icon/openlp.org-icon-32.bmp') + icon = QtGui.QIcon() + icon.addPixmap(QtGui.QPixmap(u':/icon/openlp.org-icon-32.bmp'), + QtGui.QIcon.Normal, QtGui.QIcon.Off) customEditDialog.setWindowIcon(icon) self.gridLayout = QtGui.QGridLayout(customEditDialog) self.gridLayout.setObjectName(u'gridLayout') @@ -52,15 +53,19 @@ class Ui_customEditDialog(object): self.verticalLayout = QtGui.QVBoxLayout() self.verticalLayout.setObjectName(u'verticalLayout') self.UpButton = QtGui.QPushButton(customEditDialog) - icon1 = build_icon(u':/services/service_up.png') + icon1 = QtGui.QIcon() + icon1.addPixmap(QtGui.QPixmap(u':/services/service_up.png'), + QtGui.QIcon.Normal, QtGui.QIcon.Off) self.UpButton.setIcon(icon1) self.UpButton.setObjectName(u'UpButton') self.verticalLayout.addWidget(self.UpButton) - spacerItem = QtGui.QSpacerItem(20, 128, - QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + spacerItem = QtGui.QSpacerItem(20, 128, QtGui.QSizePolicy.Minimum, + QtGui.QSizePolicy.Expanding) self.verticalLayout.addItem(spacerItem) self.DownButton = QtGui.QPushButton(customEditDialog) - icon2 = build_icon(u':/services/service_down.png') + icon2 = QtGui.QIcon() + icon2.addPixmap(QtGui.QPixmap(u':/services/service_down.png'), + QtGui.QIcon.Normal, QtGui.QIcon.Off) self.DownButton.setIcon(icon2) self.DownButton.setObjectName(u'DownButton') self.verticalLayout.addWidget(self.DownButton) @@ -97,6 +102,9 @@ class Ui_customEditDialog(object): self.ClearButton = QtGui.QPushButton(self.ButtonWidge) self.ClearButton.setObjectName(u'ClearButton') self.verticalLayout_2.addWidget(self.ClearButton) + self.SplitButton = QtGui.QPushButton(self.ButtonWidge) + self.SplitButton.setObjectName(u'SplitButton') + self.verticalLayout_2.addWidget(self.SplitButton) spacerItem1 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) self.verticalLayout_2.addItem(spacerItem1) @@ -121,16 +129,15 @@ class Ui_customEditDialog(object): self.horizontalLayout_2.addWidget(self.CreditEdit) self.gridLayout.addLayout(self.horizontalLayout_2, 4, 0, 1, 1) self.buttonBox = QtGui.QDialogButtonBox(customEditDialog) - self.buttonBox.setStandardButtons( - QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Save) + self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Save) self.buttonBox.setObjectName(u'buttonBox') self.gridLayout.addWidget(self.buttonBox, 5, 0, 1, 1) self.retranslateUi(customEditDialog) - QtCore.QObject.connect(self.buttonBox, - QtCore.SIGNAL(u'rejected()'), customEditDialog.closePressed) - QtCore.QObject.connect(self.buttonBox, - QtCore.SIGNAL(u'accepted()'), customEditDialog.accept) + QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(u'accepted()'), + customEditDialog.accept) + QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(u'rejected()'), + customEditDialog.closePressed) QtCore.QMetaObject.connectSlotsByName(customEditDialog) customEditDialog.setTabOrder(self.TitleEdit, self.VerseTextEdit) customEditDialog.setTabOrder(self.VerseTextEdit, self.AddButton) @@ -143,12 +150,11 @@ class Ui_customEditDialog(object): customEditDialog.setTabOrder(self.CreditEdit, self.UpButton) customEditDialog.setTabOrder(self.UpButton, self.DownButton) customEditDialog.setTabOrder(self.DownButton, self.ThemeComboBox) - customEditDialog.setTabOrder(self.ThemeComboBox, self.buttonBox) def retranslateUi(self, customEditDialog): + customEditDialog.setWindowTitle(self.trUtf8('Edit Custom Slides')) self.UpButton.setToolTip(self.trUtf8('Move slide Up 1')) self.DownButton.setToolTip(self.trUtf8('Move slide down 1')) - customEditDialog.setWindowTitle(self.trUtf8('Edit Custom Slides')) self.TitleLabel.setText(self.trUtf8('Title:')) self.AddButton.setText(self.trUtf8('Add New')) self.AddButton.setToolTip(self.trUtf8('Add new slide at bottom')) @@ -162,6 +168,7 @@ class Ui_customEditDialog(object): self.DeleteButton.setToolTip(self.trUtf8('Delete selected slide')) self.ClearButton.setText(self.trUtf8('Clear')) self.ClearButton.setToolTip(self.trUtf8('Clear edit area')) + self.SplitButton.setText(self.trUtf8('Split Slide')) + self.SplitButton.setToolTip(self.trUtf8('Add slide split')) self.ThemeLabel.setText(self.trUtf8('Theme:')) - self.ThemeComboBox.setToolTip(self.trUtf8('Set Theme for Slides')) - self.CreditLabel.setText(self.trUtf8('Credits:')) \ No newline at end of file + self.CreditLabel.setText(self.trUtf8('Credits:')) diff --git a/openlp/plugins/custom/forms/editcustomform.py b/openlp/plugins/custom/forms/editcustomform.py index b4402ceb3..cbbb023aa 100644 --- a/openlp/plugins/custom/forms/editcustomform.py +++ b/openlp/plugins/custom/forms/editcustomform.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -22,6 +22,7 @@ # 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, QtGui @@ -67,6 +68,8 @@ class EditCustomForm(QtGui.QDialog, Ui_customEditDialog): QtCore.SIGNAL(u'pressed()'), self.onUpButtonPressed) QtCore.QObject.connect(self.DownButton, QtCore.SIGNAL(u'pressed()'), self.onDownButtonPressed) + QtCore.QObject.connect(self.SplitButton, + QtCore.SIGNAL(u'pressed()'), self.onSplitButtonPressed) QtCore.QObject.connect(self.VerseListView, QtCore.SIGNAL(u'itemDoubleClicked(QListWidgetItem*)'), self.onVerseListViewSelected) @@ -87,11 +90,13 @@ class EditCustomForm(QtGui.QDialog, Ui_customEditDialog): def initialise(self): self.editAll = False + self.AddButton.setEnabled(True) self.DeleteButton.setEnabled(False) self.EditButton.setEnabled(False) self.EditAllButton.setEnabled(True) self.SaveButton.setEnabled(False) self.ClearButton.setEnabled(False) + self.SplitButton.setEnabled(False) self.TitleEdit.setText(u'') self.CreditEdit.setText(u'') self.VerseTextEdit.clear() @@ -200,12 +205,14 @@ class EditCustomForm(QtGui.QDialog, Ui_customEditDialog): def onEditAllButtonPressed(self): self.editAll = True self.AddButton.setEnabled(False) + self.SplitButton.setEnabled(True) if self.VerseListView.count() > 0: verse_list = u'' for row in range(0, self.VerseListView.count()): item = self.VerseListView.item(row) verse_list += item.text() - verse_list += u'\n---\n' + if row != self.VerseListView.count() - 1: + verse_list += u'\n[---]\n' self.editText(verse_list) def editText(self, text): @@ -220,7 +227,7 @@ class EditCustomForm(QtGui.QDialog, Ui_customEditDialog): def onSaveButtonPressed(self): if self.editAll: self.VerseListView.clear() - for row in unicode(self.VerseTextEdit.toPlainText()).split(u'\n---\n'): + for row in unicode(self.VerseTextEdit.toPlainText()).split(u'\n[---]\n'): self.VerseListView.addItem(row) else: self.VerseListView.currentItem().setText( @@ -239,8 +246,15 @@ class EditCustomForm(QtGui.QDialog, Ui_customEditDialog): self.SaveButton.setEnabled(False) self.EditButton.setEnabled(False) self.EditAllButton.setEnabled(True) + self.SplitButton.setEnabled(False) self.VerseTextEdit.clear() + def onSplitButtonPressed(self): + if self.VerseTextEdit.textCursor().columnNumber() != 0: + self.VerseTextEdit.insertPlainText(u'\n') + self.VerseTextEdit.insertPlainText(u'[---]\n' ) + self.VerseTextEdit.setFocus() + def onDeleteButtonPressed(self): self.VerseListView.takeItem(self.VerseListView.currentRow()) self.EditButton.setEnabled(False) @@ -256,5 +270,5 @@ class EditCustomForm(QtGui.QDialog, Ui_customEditDialog): return False, self.trUtf8('You need to enter a slide') if self.VerseTextEdit.toPlainText(): self.VerseTextEdit.setFocus() - return False, self.trUtf8('You have unsaved data') + return False, self.trUtf8('You have unsaved data, please save or clear') return True, u'' diff --git a/openlp/plugins/custom/lib/__init__.py b/openlp/plugins/custom/lib/__init__.py index 9fedfa9d6..e62669ad3 100644 --- a/openlp/plugins/custom/lib/__init__.py +++ b/openlp/plugins/custom/lib/__init__.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -25,4 +25,4 @@ from manager import CustomManager from mediaitem import CustomMediaItem -from customtab import CustomTab \ No newline at end of file +from customtab import CustomTab diff --git a/openlp/plugins/custom/lib/classes.py b/openlp/plugins/custom/lib/classes.py index 32707ea08..305852df2 100644 --- a/openlp/plugins/custom/lib/classes.py +++ b/openlp/plugins/custom/lib/classes.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -43,4 +43,4 @@ class CustomSlide(BaseModel): """ Custom Slide model """ - pass \ No newline at end of file + pass diff --git a/openlp/plugins/custom/lib/customtab.py b/openlp/plugins/custom/lib/customtab.py index f42132a79..cceca1148 100644 --- a/openlp/plugins/custom/lib/customtab.py +++ b/openlp/plugins/custom/lib/customtab.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -71,4 +71,4 @@ class CustomTab(SettingsTab): self.DisplayFooterCheckBox.setChecked(self.displayFooter) def save(self): - self.config.set_config(u'display footer', unicode(self.displayFooter)) \ No newline at end of file + self.config.set_config(u'display footer', unicode(self.displayFooter)) diff --git a/openlp/plugins/custom/lib/manager.py b/openlp/plugins/custom/lib/manager.py index 1368b89ee..2deee9ba2 100644 --- a/openlp/plugins/custom/lib/manager.py +++ b/openlp/plugins/custom/lib/manager.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/plugins/custom/lib/mediaitem.py b/openlp/plugins/custom/lib/mediaitem.py index 61d1b05d7..3d55db719 100644 --- a/openlp/plugins/custom/lib/mediaitem.py +++ b/openlp/plugins/custom/lib/mediaitem.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -28,7 +28,7 @@ import logging from PyQt4 import QtCore, QtGui from openlp.core.lib import MediaManagerItem, SongXMLParser, BaseListWithDnD,\ -Receiver, str_to_bool +Receiver, str_to_bool, ItemCapabilities log = logging.getLogger(__name__) @@ -50,8 +50,8 @@ class CustomMediaItem(MediaManagerItem): # this next is a class, not an instance of a class - it will # be instanced by the base MediaManagerItem self.ListViewWithDnD_class = CustomListView - self.servicePath = None MediaManagerItem.__init__(self, parent, icon, title) + self.singleServiceItem = False # Holds information about whether the edit is remotly triggered and # which Custom is required. self.remoteCustom = -1 @@ -132,23 +132,27 @@ class CustomMediaItem(MediaManagerItem): row = self.ListView.row(item) self.ListView.takeItem(row) - def generateSlideData(self, service_item): + def generateSlideData(self, service_item, item=None): raw_slides =[] raw_footer = [] slide = None theme = None - if self.remoteTriggered is None: - item = self.ListView.currentItem() - if item is None: - return False - item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] + if item is None: + if self.remoteTriggered is None: + item = self.ListView.currentItem() + if item is None: + return False + item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] + else: + item_id = self.remoteCustom else: - item_id = self.remoteCustom - service_item.autoPreviewAllowed = True + item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] + 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) title = customSlide.title credit = customSlide.credits - service_item.edit_enabled = True service_item.editId = item_id theme = customSlide.theme_name if theme: diff --git a/openlp/plugins/custom/lib/meta.py b/openlp/plugins/custom/lib/meta.py index 38b0f7206..affa31969 100644 --- a/openlp/plugins/custom/lib/meta.py +++ b/openlp/plugins/custom/lib/meta.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -35,4 +35,4 @@ session = None # Global metadata. If you have multiple databases with overlapping table # names, you'll need a metadata for each database -metadata = MetaData() \ No newline at end of file +metadata = MetaData() diff --git a/openlp/plugins/custom/lib/models.py b/openlp/plugins/custom/lib/models.py index 809397031..d75968882 100644 --- a/openlp/plugins/custom/lib/models.py +++ b/openlp/plugins/custom/lib/models.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -36,4 +36,4 @@ def init_models(url): session = scoped_session(sessionmaker(autoflush=True, autocommit=False, bind=engine)) mapper(CustomSlide, custom_slide_table) - return session \ No newline at end of file + return session diff --git a/openlp/plugins/custom/lib/tables.py b/openlp/plugins/custom/lib/tables.py index 13c9de5b9..bb86d9d6d 100644 --- a/openlp/plugins/custom/lib/tables.py +++ b/openlp/plugins/custom/lib/tables.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/plugins/images/__init__.py b/openlp/plugins/images/__init__.py index bc50edda3..1a348a0df 100644 --- a/openlp/plugins/images/__init__.py +++ b/openlp/plugins/images/__init__.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -21,4 +21,4 @@ # 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 # -############################################################################### \ No newline at end of file +############################################################################### diff --git a/openlp/plugins/images/imageplugin.py b/openlp/plugins/images/imageplugin.py index 37219b5db..ec1a637e1 100644 --- a/openlp/plugins/images/imageplugin.py +++ b/openlp/plugins/images/imageplugin.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/plugins/images/lib/__init__.py b/openlp/plugins/images/lib/__init__.py index 40123fe65..f5312fd6a 100644 --- a/openlp/plugins/images/lib/__init__.py +++ b/openlp/plugins/images/lib/__init__.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -24,4 +24,4 @@ ############################################################################### from mediaitem import ImageMediaItem -from imagetab import ImageTab \ No newline at end of file +from imagetab import ImageTab diff --git a/openlp/plugins/images/lib/imagetab.py b/openlp/plugins/images/lib/imagetab.py index b70006bdb..203b36842 100644 --- a/openlp/plugins/images/lib/imagetab.py +++ b/openlp/plugins/images/lib/imagetab.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py index 75f2fd981..6fbf66022 100644 --- a/openlp/plugins/images/lib/mediaitem.py +++ b/openlp/plugins/images/lib/mediaitem.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -27,7 +27,8 @@ import logging import os from PyQt4 import QtCore, QtGui -from openlp.core.lib import MediaManagerItem, BaseListWithDnD, build_icon +from openlp.core.lib import MediaManagerItem, BaseListWithDnD, build_icon, \ + contextMenuAction, ItemCapabilities log = logging.getLogger(__name__) @@ -51,9 +52,7 @@ class ImageMediaItem(MediaManagerItem): # this next is a class, not an instance of a class - it will # be instanced by the base MediaManagerItem self.ListViewWithDnD_class = ImageListView - self.servicePath = None MediaManagerItem.__init__(self, parent, icon, title) - self.overrideActive = False def initPluginNameVisible(self): self.PluginNameVisible = self.trUtf8('Image') @@ -61,13 +60,14 @@ class ImageMediaItem(MediaManagerItem): def retranslateUi(self): self.OnNewPrompt = self.trUtf8('Select Image(s)') self.OnNewFileMasks = \ - self.trUtf8('Images (*.jpg *jpeg *.gif *.png *.bmp);; All files (*)') + self.trUtf8('Images (*.jpg *.jpeg *.gif *.png *.bmp);; All files (*)') def requiredIcons(self): MediaManagerItem.requiredIcons(self) self.hasFileIcon = True self.hasNewIcon = False self.hasEditIcon = False + self.addToServiceItem = True def initialise(self): log.debug(u'initialise') @@ -81,6 +81,15 @@ class ImageMediaItem(MediaManagerItem): os.mkdir(self.servicePath) self.loadList(self.parent.config.load_list(self.ConfigSection)) + def addListViewToToolBar(self): + MediaManagerItem.addListViewToToolBar(self) + self.ListView.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) + self.ListView.addAction( + contextMenuAction( + self.ListView, u':/slides/slide_blank.png', + self.trUtf8('Replace Live Background'), + self.onReplaceClick)) + def addEndHeaderBar(self): self.ImageWidget = QtGui.QWidget(self) sizePolicy = QtGui.QSizePolicy( @@ -91,60 +100,46 @@ class ImageMediaItem(MediaManagerItem): self.ImageWidget.sizePolicy().hasHeightForWidth()) self.ImageWidget.setSizePolicy(sizePolicy) self.ImageWidget.setObjectName(u'ImageWidget') - self.OverrideLayout = QtGui.QVBoxLayout(self.ImageWidget) - self.OverrideLayout.setMargin(5) - self.OverrideLayout.setSpacing(4) - self.OverrideLayout.setObjectName(u'OverrideLayout') - self.OverrideCheckBox = QtGui.QCheckBox(self.ImageWidget) - self.OverrideCheckBox.setObjectName(u'OverrideCheckBox') - self.OverrideCheckBox.setCheckable(True) - self.OverrideCheckBox.setChecked(False) - self.OverrideCheckBox.setText(self.trUtf8('Override background')) - self.OverrideCheckBox.setStatusTip( - self.trUtf8('Allow background of live slide to be overridden')) - self.OverrideLayout.addWidget(self.OverrideCheckBox) - self.OverrideLabel = QtGui.QLabel(self.ImageWidget) - self.OverrideLabel.setObjectName(u'OverrideLabel') - self.OverrideLayout.addWidget(self.OverrideLabel) + self.blankButton = self.Toolbar.addToolbarButton( + u'Replace Background', u':/slides/slide_blank.png', + self.trUtf8('Replace Live Background'), self.onReplaceClick, False) # Add the song widget to the page layout self.PageLayout.addWidget(self.ImageWidget) - QtCore.QObject.connect(self.OverrideCheckBox, - QtCore.SIGNAL(u'stateChanged(int)'), - self.toggleOverrideState) def onDeleteClick(self): - item = self.ListView.currentItem() - if item: - try: - os.remove(os.path.join(self.servicePath, unicode(item.text()))) - except: - #if not present do not worry - pass - row = self.ListView.row(item) - self.ListView.takeItem(row) - self.parent.config.set_list(self.ConfigSection, self.getFileList()) + items = self.ListView.selectedIndexes() + if items: + for item in items: + text = self.ListView.item(item.row()) + try: + os.remove(os.path.join(self.servicePath, unicode(text.text()))) + except: + #if not present do not worry + pass + self.ListView.takeItem(item.row()) + self.parent.config.set_list(self.ConfigSection, self.getFileList()) def loadList(self, list): for file in list: (path, filename) = os.path.split(unicode(file)) thumb = os.path.join(self.servicePath, filename) if os.path.exists(thumb): + self.validate(file, thumb) icon = build_icon(thumb) else: - icon = build_icon(unicode(file)) - pixmap = icon.pixmap(QtCore.QSize(88,50)) - ext = os.path.splitext(thumb)[1].lower() - pixmap.save(thumb, ext[1:]) + icon = self.IconFromFile(file, thumb) item_name = QtGui.QListWidgetItem(filename) item_name.setIcon(icon) item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(file)) self.ListView.addItem(item_name) - def generateSlideData(self, service_item): + def generateSlideData(self, service_item, item=None): items = self.ListView.selectedIndexes() if items: service_item.title = self.trUtf8('Image(s)') - service_item.autoPreviewAllowed = True + service_item.add_capability(ItemCapabilities.AllowsMaintain) + service_item.add_capability(ItemCapabilities.AllowsPreview) + service_item.add_capability(ItemCapabilities.AllowsLoop) for item in items: bitem = self.ListView.item(item.row()) filename = unicode((bitem.data(QtCore.Qt.UserRole)).toString()) @@ -155,24 +150,17 @@ class ImageMediaItem(MediaManagerItem): else: return False - def toggleOverrideState(self): - self.overrideActive = not self.overrideActive - if not self.overrideActive: - self.OverrideLabel.setText(u'') - self.parent.render_manager.override_background = None + def onReplaceClick(self): + if not self.ListView.selectedIndexes(): + QtGui.QMessageBox.information(self, + self.trUtf8('No item selected'), + self.trUtf8('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) def onPreviewClick(self): - if self.overrideActive: - if not self.ListView.selectedIndexes(): - QtGui.QMessageBox.information(self, - self.trUtf8('No items selected...'), - self.trUtf8('You must select one or more items')) - items = self.ListView.selectedIndexes() - for item in items: - bitem = self.ListView.item(item.row()) - filename = unicode((bitem.data(QtCore.Qt.UserRole)).toString()) - self.OverrideLabel.setText(bitem.text()) - frame = QtGui.QImage(unicode(filename)) - self.parent.maindisplay.addImageWithText(frame) - else: - MediaManagerItem.onPreviewClick(self) + MediaManagerItem.onPreviewClick(self) diff --git a/openlp/plugins/media/__init__.py b/openlp/plugins/media/__init__.py index bc50edda3..1a348a0df 100644 --- a/openlp/plugins/media/__init__.py +++ b/openlp/plugins/media/__init__.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -21,4 +21,4 @@ # 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 # -############################################################################### \ No newline at end of file +############################################################################### diff --git a/openlp/plugins/media/lib/__init__.py b/openlp/plugins/media/lib/__init__.py index 0ba6b6bf6..a5406d6a8 100644 --- a/openlp/plugins/media/lib/__init__.py +++ b/openlp/plugins/media/lib/__init__.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -25,4 +25,4 @@ from mediaitem import MediaMediaItem -__all__ = ['MediaMediaItem'] \ No newline at end of file +__all__ = ['MediaMediaItem'] diff --git a/openlp/plugins/media/lib/mediaitem.py b/openlp/plugins/media/lib/mediaitem.py index c91440c5c..aa1a8f38a 100644 --- a/openlp/plugins/media/lib/mediaitem.py +++ b/openlp/plugins/media/lib/mediaitem.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -28,7 +28,8 @@ import os from PyQt4 import QtCore, QtGui -from openlp.core.lib import MediaManagerItem, BaseListWithDnD, build_icon +from openlp.core.lib import MediaManagerItem, BaseListWithDnD, build_icon, \ +ItemCapabilities log = logging.getLogger(__name__) @@ -51,10 +52,10 @@ class MediaMediaItem(MediaManagerItem): # this next is a class, not an instance of a class - it will # be instanced by the base MediaManagerItem self.ListViewWithDnD_class = MediaListView - self.PreviewFunction = self.video_get_preview + self.PreviewFunction = QtGui.QPixmap(u':/media/media_video.png').toImage() MediaManagerItem.__init__(self, parent, icon, title) + self.singleServiceItem = False self.ServiceItemIconName = u':/media/media_video.png' - self.MainDisplay = self.parent.maindisplay def initPluginNameVisible(self): self.PluginNameVisible = self.trUtf8('Media') @@ -71,23 +72,17 @@ class MediaMediaItem(MediaManagerItem): self.hasNewIcon = False self.hasEditIcon = False - def video_get_preview(self): - # For now cross platform is an icon. Phonon does not support - # individual frame access (yet?) and GStreamer is not available - # on Windows - return QtGui.QPixmap(u':/media/media_video.png').toImage() - - def generateSlideData(self, service_item): - items = self.ListView.selectedIndexes() - if len(items) > 1: - return False + def generateSlideData(self, service_item, item=None): + if item is None: + item = self.ListView.currentItem() + if item is None: + return False + filename = unicode((item.data(QtCore.Qt.UserRole)).toString()) service_item.title = unicode(self.trUtf8('Media')) - for item in items: - bitem = self.ListView.item(item.row()) - filename = unicode((bitem.data(QtCore.Qt.UserRole)).toString()) - frame = u':/media/image_clapperboard.png' - (path, name) = os.path.split(filename) - service_item.add_from_command(path, name, frame) + service_item.add_capability(ItemCapabilities.RequiresMedia) + frame = u':/media/image_clapperboard.png' + (path, name) = os.path.split(filename) + service_item.add_from_command(path, name, frame) return True def initialise(self): @@ -108,7 +103,7 @@ class MediaMediaItem(MediaManagerItem): for file in list: (path, filename) = os.path.split(unicode(file)) item_name = QtGui.QListWidgetItem(filename) - img = self.video_get_preview() + img = QtGui.QPixmap(u':/media/media_video.png').toImage() item_name.setIcon(build_icon(img)) item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(file)) - self.ListView.addItem(item_name) + self.ListView.addItem(item_name) \ No newline at end of file diff --git a/openlp/plugins/media/mediaplugin.py b/openlp/plugins/media/mediaplugin.py index 096d53aea..1fb7d7405 100644 --- a/openlp/plugins/media/mediaplugin.py +++ b/openlp/plugins/media/mediaplugin.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/plugins/presentations/__init__.py b/openlp/plugins/presentations/__init__.py index bc50edda3..1a348a0df 100644 --- a/openlp/plugins/presentations/__init__.py +++ b/openlp/plugins/presentations/__init__.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -21,4 +21,4 @@ # 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 # -############################################################################### \ No newline at end of file +############################################################################### diff --git a/openlp/plugins/presentations/lib/__init__.py b/openlp/plugins/presentations/lib/__init__.py index 39139fe45..a89b62fbe 100644 --- a/openlp/plugins/presentations/lib/__init__.py +++ b/openlp/plugins/presentations/lib/__init__.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -26,4 +26,4 @@ from presentationcontroller import PresentationController from messagelistener import MessageListener from mediaitem import PresentationMediaItem -from presentationtab import PresentationTab \ No newline at end of file +from presentationtab import PresentationTab diff --git a/openlp/plugins/presentations/lib/impresscontroller.py b/openlp/plugins/presentations/lib/impresscontroller.py index 2756f718e..92717b6d7 100644 --- a/openlp/plugins/presentations/lib/impresscontroller.py +++ b/openlp/plugins/presentations/lib/impresscontroller.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -37,6 +37,8 @@ import logging import os import time +from openlp.core.lib import resize_image + if os.name == u'nt': from win32com.client import Dispatch else: @@ -147,12 +149,16 @@ class ImpressController(PresentationController): Called at system exit to clean up any running presentations """ log.debug(u'Kill OpenOffice') - for doc in self.docs: - doc.close_presentation() + while self.docs: + self.docs[0].close_presentation() if os.name != u'nt': desktop = self.get_uno_desktop() else: desktop = self.get_com_desktop() + #Sometimes we get a failure and desktop is None + if not desktop: + log.exception(u'Failed to terminate OpenOffice') + return docs = desktop.getComponents() if docs.hasElements(): log.debug(u'OpenOffice not terminated') @@ -178,7 +184,7 @@ class ImpressDocument(PresentationDocument): self.presentation = None self.control = None self.store_filename(presentation) - + def load_presentation(self): """ Called when a presentation is added to the SlideController. @@ -218,7 +224,7 @@ class ImpressDocument(PresentationDocument): self.presentation.Display = self.controller.plugin.render_manager.screens.current_display + 1 self.control = None self.create_thumbnails() - + def create_thumbnails(self): """ Create thumbnail images for presentation @@ -239,17 +245,22 @@ class ImpressDocument(PresentationDocument): for idx in range(pages.getCount()): page = pages.getByIndex(idx) doc.getCurrentController().setCurrentPage(page) - path = u'%s/%s%s.png'% (thumbdir, self.controller.thumbnailprefix, + path = u'%s/%s%s.png' % (thumbdir, self.controller.thumbnailprefix, unicode(idx + 1)) try: doc.storeToURL(path , props) + preview = resize_image(path, 640, 480) + if os.path.exists(path): + os.remove(path) + preview.save(path, u'png') except: - log.exception(u'%s\nUnable to store preview' % path) + log.exception(u'%s - Unable to store openoffice preview' % path) def create_property(self, name, value): log.debug(u'create property OpenOffice') if os.name == u'nt': - prop = self.controller.manager.Bridge_GetStruct(u'com.sun.star.beans.PropertyValue') + prop = self.controller.manager.\ + Bridge_GetStruct(u'com.sun.star.beans.PropertyValue') else: prop = PropertyValue() prop.Name = name @@ -307,7 +318,7 @@ class ImpressDocument(PresentationDocument): def blank_screen(self): log.debug(u'blank screen OpenOffice') self.control.blankScreen(0) - + def is_blank(self): """ Returns true if screen is blank @@ -356,7 +367,8 @@ class ImpressDocument(PresentationDocument): def get_slide_preview_file(self, slide_no): """ - Returns an image path containing a preview for the requested slide + Returns an image path containing a preview for the + requested slide ``slide_no`` The slide an image is required for, starting at 1 @@ -384,7 +396,7 @@ class ImpressDocument(PresentationDocument): if shape.supportsService("com.sun.star.drawing.Text"): text += shape.getString() + '\n' return text - + def get_slide_notes(self, slide_no): """ Returns the text on the slide diff --git a/openlp/plugins/presentations/lib/mediaitem.py b/openlp/plugins/presentations/lib/mediaitem.py index 37d50d01c..79c8600f0 100644 --- a/openlp/plugins/presentations/lib/mediaitem.py +++ b/openlp/plugins/presentations/lib/mediaitem.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -58,7 +58,7 @@ class PresentationMediaItem(MediaManagerItem): self.ListViewWithDnD_class = PresentationListView MediaManagerItem.__init__(self, parent, icon, title) self.message_listener = MessageListener(self) - + def initPluginNameVisible(self): self.PluginNameVisible = self.trUtf8('Presentation') @@ -140,19 +140,20 @@ class PresentationMediaItem(MediaManagerItem): self.parent.config.set_list( self.ConfigSection, 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() - self.controllers[cidx].remove_doc(doc) + doc.close_presentation() - def generateSlideData(self, service_item): + def generateSlideData(self, service_item, item=None): items = self.ListView.selectedIndexes() if len(items) > 1: return False service_item.title = unicode(self.DisplayTypeComboBox.currentText()) service_item.shortname = unicode(self.DisplayTypeComboBox.currentText()) shortname = service_item.shortname - for item in items: bitem = self.ListView.item(item.row()) filename = unicode((bitem.data(QtCore.Qt.UserRole)).toString()) @@ -171,7 +172,7 @@ class PresentationMediaItem(MediaManagerItem): service_item.add_from_command(path, name, img) i = i + 1 img = doc.get_slide_preview_file(i) - controller.remove_doc(doc) + doc.close_presentation() return True def findControllerByType(self, filename): diff --git a/openlp/plugins/presentations/lib/messagelistener.py b/openlp/plugins/presentations/lib/messagelistener.py index 08aa7e73a..39717d42d 100644 --- a/openlp/plugins/presentations/lib/messagelistener.py +++ b/openlp/plugins/presentations/lib/messagelistener.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -151,7 +151,7 @@ class Controller(object): #self.timer.stop() def blank(self): - log.debug(u'Live = %s, blank' % self.isLive) + log.debug(u'Live = %s, blank' % self.isLive) if not self.isLive: return if not self.doc.is_loaded(): @@ -161,7 +161,7 @@ class Controller(object): self.doc.blank_screen() def unblank(self): - log.debug(u'Live = %s, unblank' % self.isLive) + log.debug(u'Live = %s, unblank' % self.isLive) if not self.isLive: return self.activate() @@ -218,7 +218,7 @@ class MessageListener(object): self.handler = self.mediaitem.findControllerByType(file) if not self.handler: return - + if isLive: controller = self.liveHandler else: diff --git a/openlp/plugins/presentations/lib/powerpointcontroller.py b/openlp/plugins/presentations/lib/powerpointcontroller.py index 2137496a5..67870574d 100644 --- a/openlp/plugins/presentations/lib/powerpointcontroller.py +++ b/openlp/plugins/presentations/lib/powerpointcontroller.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -81,8 +81,9 @@ class PowerpointController(PresentationController): """ Called at system exit to clean up any running presentations """ - for doc in self.docs: - doc.close_presentation() + log.debug(u'Kill powerpoint') + while self.docs: + self.docs[0].close_presentation() if self.process is None: return if self.process.Presentations.Count > 0: @@ -149,12 +150,12 @@ class PowerpointDocument(PresentationDocument): Triggerent by new object being added to SlideController orOpenLP being shut down """ - if self.presentation is None: - return - try: - self.presentation.Close() - except: - pass + log.debug(u'ClosePresentation') + if self.presentation: + try: + self.presentation.Close() + except: + pass self.presentation = None self.controller.remove_doc(self) @@ -294,7 +295,7 @@ class PowerpointDocument(PresentationDocument): shape = shapes(idx + 1) if shape.HasTextFrame: text += shape.TextFrame.TextRange.Text + '\n' - return text + return text def get_slide_notes(self, slide_no): """ diff --git a/openlp/plugins/presentations/lib/pptviewcontroller.py b/openlp/plugins/presentations/lib/pptviewcontroller.py index 6bec8dbf1..455e1c601 100644 --- a/openlp/plugins/presentations/lib/pptviewcontroller.py +++ b/openlp/plugins/presentations/lib/pptviewcontroller.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -88,9 +88,9 @@ class PptviewController(PresentationController): """ Called at system exit to clean up any running presentations """ - log.debug(u'Kill') - for doc in self.docs: - doc.close_presentation() + log.debug(u'Kill pptviewer') + while self.docs: + self.docs[0].close_presentation() def add_doc(self, name): log.debug(u'Add Doc PPTView') @@ -112,7 +112,7 @@ class PptviewDocument(PresentationDocument): """ Called when a presentation is added to the SlideController. It builds the environment, starts communcations with the background - PptView task started earlier. + PptView task started earlier. ``presentation`` The file name of the presentations to run. @@ -137,6 +137,7 @@ class PptviewDocument(PresentationDocument): Triggerent by new object being added to SlideController orOpenLP being shut down """ + log.debug(u'ClosePresentation') self.controller.process.ClosePPT(self.pptid) self.pptid = -1 self.controller.remove_doc(self) diff --git a/openlp/plugins/presentations/lib/pptviewlib/ppttest.py b/openlp/plugins/presentations/lib/pptviewlib/ppttest.py index 7344268b8..b4a82d236 100644 --- a/openlp/plugins/presentations/lib/pptviewlib/ppttest.py +++ b/openlp/plugins/presentations/lib/pptviewlib/ppttest.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -168,4 +168,4 @@ if __name__ == '__main__': app = QtGui.QApplication(sys.argv) qb = PPTViewer() qb.show() - sys.exit(app.exec_()) \ No newline at end of file + sys.exit(app.exec_()) diff --git a/openlp/plugins/presentations/lib/presentationcontroller.py b/openlp/plugins/presentations/lib/presentationcontroller.py index ae41a56b1..389744b0b 100644 --- a/openlp/plugins/presentations/lib/presentationcontroller.py +++ b/openlp/plugins/presentations/lib/presentationcontroller.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -115,7 +115,6 @@ class PresentationController(object): """ return False - def start_process(self): """ Loads a running version of the presentation application in the background. @@ -138,18 +137,23 @@ class PresentationController(object): self.docs.append(doc) return doc - def remove_doc(self, doc): + def remove_doc(self, doc=None): """ Called to remove an open document from the collection """ log.debug(u'remove_doc Presentation') - self.docs.remove(doc) - + if doc is None: + return + if doc in self.docs: + self.docs.remove(doc) + + def close_presentation(self): + pass class PresentationDocument(object): """ Base class for presentation documents to inherit from. - Loads and closes the presentation as well as triggering the correct + Loads and closes the presentation as well as triggering the correct activities based on the users input **Hook Functions** @@ -235,7 +239,7 @@ class PresentationDocument(object): def get_file_name(self, presentation): return os.path.split(presentation)[1] - + def get_thumbnail_path(self, presentation): return os.path.join(self.controller.thumbnailroot, self.get_file_name(presentation)) @@ -256,10 +260,10 @@ class PresentationDocument(object): Close presentation and clean up objects Triggered by new object being added to SlideController """ - self.controller.delete_doc(self) + self.controller.close_presentation() def is_active(self): - """ + """ Returns True if a presentation is currently running """ return False @@ -287,7 +291,7 @@ class PresentationDocument(object): Returns true if screen is blank """ return False - + def stop_presentation(self): """ Stops the presentation, removing it from the output display @@ -368,7 +372,7 @@ class PresentationDocument(object): The slide the text is required for, starting at 1 """ return '' - + def get_slide_notes(self, slide_no): """ Returns the text on the slide diff --git a/openlp/plugins/presentations/lib/presentationtab.py b/openlp/plugins/presentations/lib/presentationtab.py index 0ef7e17d1..cf18359b1 100644 --- a/openlp/plugins/presentations/lib/presentationtab.py +++ b/openlp/plugins/presentations/lib/presentationtab.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/plugins/presentations/presentationplugin.py b/openlp/plugins/presentations/presentationplugin.py index 8353611ab..00a83fe4b 100644 --- a/openlp/plugins/presentations/presentationplugin.py +++ b/openlp/plugins/presentations/presentationplugin.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -27,6 +27,7 @@ import os import logging from openlp.core.lib import Plugin, build_icon, Receiver, PluginStatus +from openlp.core.utils import AppLocation from openlp.plugins.presentations.lib import * log = logging.getLogger(__name__) @@ -56,6 +57,8 @@ class PresentationPlugin(Plugin): for controller in self.controllers: if self.controllers[controller].enabled: presentation_types.append({u'%s' % controller : self.controllers[controller].supports}) + self.controllers[controller].start_process() + Receiver.send_message( u'presentation types', presentation_types) @@ -84,11 +87,13 @@ class PresentationPlugin(Plugin): If Not do not install the plugin. """ log.debug(u'check_pre_conditions') - dir = os.path.join(os.path.dirname(__file__), u'lib') - for filename in os.listdir(dir): + controller_dir = os.path.join( + AppLocation.get_directory(AppLocation.PluginsDir), + u'presentations', u'lib') + for filename in os.listdir(controller_dir): if filename.endswith(u'controller.py') and \ not filename == 'presentationcontroller.py': - path = os.path.join(dir, filename) + path = os.path.join(controller_dir, filename) if os.path.isfile(path): modulename = u'openlp.plugins.presentations.lib.' + \ os.path.splitext(filename)[0] @@ -101,8 +106,6 @@ class PresentationPlugin(Plugin): for controller_class in controller_classes: controller = controller_class(self) self.registerControllers(controller) - if controller.enabled: - controller.start_process() if self.controllers: return True else: @@ -111,6 +114,6 @@ class PresentationPlugin(Plugin): def about(self): about_text = self.trUtf8('Presentation Plugin
Delivers ' 'the ability to show presentations using a number of different ' - 'programs. The choice of available presentation programs is ' + 'programs. The choice of available presentation programs is ' 'available to the user in a drop down box.') return about_text diff --git a/openlp/plugins/red-x.png b/openlp/plugins/red-x.png deleted file mode 100644 index c23f2ac9f..000000000 Binary files a/openlp/plugins/red-x.png and /dev/null differ diff --git a/openlp/plugins/remotes/__init__.py b/openlp/plugins/remotes/__init__.py index bc50edda3..1a348a0df 100644 --- a/openlp/plugins/remotes/__init__.py +++ b/openlp/plugins/remotes/__init__.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -21,4 +21,4 @@ # 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 # -############################################################################### \ No newline at end of file +############################################################################### diff --git a/openlp/plugins/remotes/lib/__init__.py b/openlp/plugins/remotes/lib/__init__.py index ebd77bdae..bb613fb53 100644 --- a/openlp/plugins/remotes/lib/__init__.py +++ b/openlp/plugins/remotes/lib/__init__.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -23,4 +23,4 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from remotetab import RemoteTab \ No newline at end of file +from remotetab import RemoteTab diff --git a/openlp/plugins/remotes/lib/remotetab.py b/openlp/plugins/remotes/lib/remotetab.py index a1f70ccbf..31af42ff2 100644 --- a/openlp/plugins/remotes/lib/remotetab.py +++ b/openlp/plugins/remotes/lib/remotetab.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -61,4 +61,4 @@ class RemoteTab(SettingsTab): def save(self): self.config.set_config( - u'remote port', unicode(self.RemotePortSpinBox.value())) \ No newline at end of file + u'remote port', unicode(self.RemotePortSpinBox.value())) diff --git a/openlp/plugins/remotes/remoteplugin.py b/openlp/plugins/remotes/remoteplugin.py index acfa6f97d..4e01e43ee 100644 --- a/openlp/plugins/remotes/remoteplugin.py +++ b/openlp/plugins/remotes/remoteplugin.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/plugins/songs/__init__.py b/openlp/plugins/songs/__init__.py index bc50edda3..1a348a0df 100644 --- a/openlp/plugins/songs/__init__.py +++ b/openlp/plugins/songs/__init__.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -21,4 +21,4 @@ # 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 # -############################################################################### \ No newline at end of file +############################################################################### diff --git a/openlp/plugins/songs/forms/__init__.py b/openlp/plugins/songs/forms/__init__.py index cc36ff0fa..f850a3adb 100644 --- a/openlp/plugins/songs/forms/__init__.py +++ b/openlp/plugins/songs/forms/__init__.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -33,4 +33,4 @@ from songmaintenanceform import SongMaintenanceForm from openlpexportform import OpenLPExportForm from openlpimportform import OpenLPImportForm from opensongexportform import OpenSongExportForm -from opensongimportform import OpenSongImportForm \ No newline at end of file +from opensongimportform import OpenSongImportForm diff --git a/openlp/plugins/songs/forms/authorsdialog.py b/openlp/plugins/songs/forms/authorsdialog.py index 269874011..ca28f461c 100644 --- a/openlp/plugins/songs/forms/authorsdialog.py +++ b/openlp/plugins/songs/forms/authorsdialog.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -76,4 +76,4 @@ class Ui_AuthorsDialog(object): AuthorsDialog.setWindowTitle(self.trUtf8('Author Maintenance')) self.DisplayLabel.setText(self.trUtf8('Display name:')) self.FirstNameLabel.setText(self.trUtf8('First name:')) - self.LastNameLabel.setText(self.trUtf8('Last name:')) \ No newline at end of file + self.LastNameLabel.setText(self.trUtf8('Last name:')) diff --git a/openlp/plugins/songs/forms/authorsform.py b/openlp/plugins/songs/forms/authorsform.py index bbdb724af..d1cb24761 100644 --- a/openlp/plugins/songs/forms/authorsform.py +++ b/openlp/plugins/songs/forms/authorsform.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/plugins/songs/forms/editsongdialog.py b/openlp/plugins/songs/forms/editsongdialog.py index e0a2ec185..b992aeea4 100644 --- a/openlp/plugins/songs/forms/editsongdialog.py +++ b/openlp/plugins/songs/forms/editsongdialog.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -135,7 +135,7 @@ class Ui_EditSongDialog(object): sizePolicy.setHeightForWidth( self.AuthorsSelectionComboItem.sizePolicy().hasHeightForWidth()) self.AuthorsSelectionComboItem.setSizePolicy(sizePolicy) - self.AuthorsSelectionComboItem.setEditable(False) + self.AuthorsSelectionComboItem.setEditable(True) self.AuthorsSelectionComboItem.setInsertPolicy( QtGui.QComboBox.InsertAlphabetically) self.AuthorsSelectionComboItem.setSizeAdjustPolicy( @@ -212,6 +212,7 @@ class Ui_EditSongDialog(object): sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.SongTopicCombo.sizePolicy().hasHeightForWidth()) + self.SongTopicCombo.setEditable(True) self.SongTopicCombo.setSizePolicy(sizePolicy) self.SongTopicCombo.setObjectName(u'SongTopicCombo') self.TopicAddLayout.addWidget(self.SongTopicCombo) @@ -256,6 +257,7 @@ class Ui_EditSongDialog(object): sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.SongbookCombo.sizePolicy().hasHeightForWidth()) + self.SongbookCombo.setEditable(True) self.SongbookCombo.setSizePolicy(sizePolicy) self.SongbookCombo.setObjectName(u'SongbookCombo') self.SongbookLayout.addWidget(self.SongbookCombo, 0, 0, 1, 1) @@ -293,6 +295,7 @@ class Ui_EditSongDialog(object): self.ThemeLayout.setMargin(8) self.ThemeLayout.setObjectName(u'ThemeLayout') self.ThemeSelectionComboItem = QtGui.QComboBox(self.ThemeGroupBox) + self.ThemeSelectionComboItem.setEditable(True) self.ThemeSelectionComboItem.setObjectName(u'ThemeSelectionComboItem') self.ThemeLayout.addWidget(self.ThemeSelectionComboItem) self.ThemeAddButton = QtGui.QPushButton(self.ThemeGroupBox) @@ -447,4 +450,4 @@ class Ui_EditSongDialog(object): self.CommentsGroupBox.setTitle(self.trUtf8('Comments')) self.SongTabWidget.setTabText( self.SongTabWidget.indexOf(self.ThemeTab), - self.trUtf8('Theme, Copyright Info && Comments')) \ No newline at end of file + self.trUtf8('Theme, Copyright Info && Comments')) diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py index 183af6a44..2c03d13f6 100644 --- a/openlp/plugins/songs/forms/editsongform.py +++ b/openlp/plugins/songs/forms/editsongform.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -122,6 +122,11 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): def loadAuthors(self): authors = self.songmanager.get_authors() + authorsCompleter = QtGui.QCompleter( + [author.display_name for author in authors], + self.AuthorsSelectionComboItem) + authorsCompleter.setCaseSensitivity(QtCore.Qt.CaseInsensitive); + self.AuthorsSelectionComboItem.setCompleter(authorsCompleter); self.AuthorsSelectionComboItem.clear() for author in authors: row = self.AuthorsSelectionComboItem.count() @@ -131,6 +136,11 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): def loadTopics(self): topics = self.songmanager.get_topics() + topicsCompleter = QtGui.QCompleter( + [topic.name for topic in topics], + self.SongTopicCombo) + topicsCompleter.setCaseSensitivity(QtCore.Qt.CaseInsensitive); + self.SongTopicCombo.setCompleter(topicsCompleter); self.SongTopicCombo.clear() for topic in topics: row = self.SongTopicCombo.count() @@ -139,6 +149,11 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): def loadBooks(self): books = self.songmanager.get_books() + booksCompleter = QtGui.QCompleter( + [book.name for book in books], + self.SongbookCombo) + booksCompleter.setCaseSensitivity(QtCore.Qt.CaseInsensitive); + self.SongbookCombo.setCompleter(booksCompleter); self.SongbookCombo.clear() self.SongbookCombo.addItem(u' ') for book in books: @@ -147,6 +162,11 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.SongbookCombo.setItemData(row, QtCore.QVariant(book.id)) def loadThemes(self, theme_list): + themesCompleter = QtGui.QCompleter( + [theme for theme in theme_list], + self.ThemeSelectionComboItem) + themesCompleter.setCaseSensitivity(QtCore.Qt.CaseInsensitive); + self.ThemeSelectionComboItem.setCompleter(themesCompleter); self.ThemeSelectionComboItem.clear() self.ThemeSelectionComboItem.addItem(u' ') for theme in theme_list: @@ -411,24 +431,27 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.SongTabWidget.setCurrentIndex(2) self.AuthorsListView.setFocus() #split the verse list by space and mark lower case for testing + taglist = unicode(self.trUtf8(' bitped')) for verse in unicode(self.VerseOrderEdit.text()).lower().split(u' '): if len(verse) > 1: - if verse[0:1] == u'v' and verse[1:].isdigit(): + if (verse[0:1] == u'%s' % self.trUtf8('v') or + verse[0:1] == u'%s' % self.trUtf8('c')) \ + and verse[1:].isdigit(): pass else: self.SongTabWidget.setCurrentIndex(0) self.VerseOrderEdit.setFocus() return False, \ - self.trUtf8('Invalid verse entry - vX') + self.trUtf8('Invalid verse entry - Vx or Cx') else: - if u' bcitped'.find(verse) > -1: + if taglist.find(verse) > -1: pass else: self.SongTabWidget.setCurrentIndex(0) self.VerseOrderEdit.setFocus() return False, \ self.trUtf8(\ - 'Invalid verse entry - values must be Numeric, I,B,C,T,P,E,O') + 'Invalid verse entry, values must be I,B,T,P,E,O,Vx,Cx') return True, u'' def onTitleEditItemLostFocus(self): @@ -498,7 +521,6 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): sxml = SongXMLBuilder() sxml.new_document() sxml.add_lyrics_to_song() - count = 1 text = u' ' for i in range (0, self.VerseListWidget.count()): item = self.VerseListWidget.item(i) @@ -506,7 +528,6 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): bits = verseId.split(u':') sxml.add_verse_to_lyrics(bits[0], bits[1], unicode(item.text())) text = text + unicode(self.VerseListWidget.item(i).text()) + u' ' - count += 1 text = text.replace(u'\'', u'') text = text.replace(u',', u'') text = text.replace(u';', u'') diff --git a/openlp/plugins/songs/forms/editversedialog.py b/openlp/plugins/songs/forms/editversedialog.py index 89e704c87..7829e2c27 100644 --- a/openlp/plugins/songs/forms/editversedialog.py +++ b/openlp/plugins/songs/forms/editversedialog.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/plugins/songs/forms/editverseform.py b/openlp/plugins/songs/forms/editverseform.py index 99dfd6d69..d412e3627 100644 --- a/openlp/plugins/songs/forms/editverseform.py +++ b/openlp/plugins/songs/forms/editverseform.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -53,32 +53,56 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog): QtCore.QObject.connect(self.VerseListComboBox, QtCore.SIGNAL(u'activated(int)'), self.onVerseComboChanged) + def startNewLine(self): + if self.VerseTextEdit.textCursor().columnNumber() != 0: + self.VerseTextEdit.insertPlainText(u'\n') + def onAddIntro(self): - self.VerseTextEdit.insertPlainText(u'---[Intro:1]---') + self.startNewLine() + self.VerseTextEdit.insertPlainText(u'---[Intro:1]---\n') + self.VerseTextEdit.setFocus() def onAddEnding(self): - self.VerseTextEdit.insertPlainText(u'---[Ending:1]---') + self.startNewLine() + self.VerseTextEdit.insertPlainText(u'---[Ending:1]---\n') + self.VerseTextEdit.setFocus() def onAddOther(self): - self.VerseTextEdit.insertPlainText(u'---[Other:1]---') + self.startNewLine() + self.VerseTextEdit.insertPlainText(u'---[Other:1]---\n') + self.VerseTextEdit.setFocus() def onAddPreChorus(self): - self.VerseTextEdit.insertPlainText(u'---[PreChorus:1]---') + self.startNewLine() + self.VerseTextEdit.insertPlainText(u'---[Pre-Chorus:1]---\n') + self.VerseTextEdit.setFocus() def onAddBridge(self): - self.VerseTextEdit.insertPlainText(u'---[Bridge:1]---') + self.startNewLine() + self.VerseTextEdit.insertPlainText(u'---[Bridge:1]---\n') + self.VerseTextEdit.setFocus() def onAddChorus(self): - self.VerseTextEdit.insertPlainText(u'---[Chorus:1]---') + self.startNewLine() + count = self.VerseTextEdit.toPlainText().\ + count(u'---[Chorus') + self.VerseTextEdit.insertPlainText(u'---[Chorus:%s]---\n' + % unicode(count + 1)) + self.VerseTextEdit.setFocus() def onAddVerse(self): - self.VerseTextEdit.insertPlainText(u'---[Verse:1]---') + self.startNewLine() + count = self.VerseTextEdit.toPlainText().\ + count(u'---[Verse') + self.VerseTextEdit.insertPlainText(u'---[Verse:%s]---\n' + % unicode(count + 1)) + self.VerseTextEdit.setFocus() def setVerse(self, text, verseCount=0, single=False, tag=u'Verse:1'): posVerse = 0 posSub = 0 if len(text) == 0 and not single: - text = u'---[Verse:1]---\n' + text = u'---[%s:1]---\n' % self.trUtf8('Verse') if single: id = tag.split(u':') posVerse = self.VerseListComboBox.findText(id[0], QtCore.Qt.MatchExactly) @@ -128,7 +152,8 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog): return text def onVerseComboChanged(self, id): - if unicode(self.VerseListComboBox.currentText()) == u'Verse': + if unicode(self.VerseListComboBox.currentText()) == self.trUtf8('Verse') or \ + unicode(self.VerseListComboBox.currentText()) == self.trUtf8('Chrous'): self.SubVerseListComboBox.setEnabled(True) else: self.SubVerseListComboBox.setEnabled(False) diff --git a/openlp/plugins/songs/forms/openlpexportdialog.py b/openlp/plugins/songs/forms/openlpexportdialog.py index ca23498f4..2236d9ed3 100644 --- a/openlp/plugins/songs/forms/openlpexportdialog.py +++ b/openlp/plugins/songs/forms/openlpexportdialog.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -54,7 +54,7 @@ class Ui_OpenLPExportDialog(object): self.horizontalLayout.addWidget(self.ExportFileLineEdit) self.ExportFileSelectPushButton = QtGui.QPushButton(self.ExportFileWidget) icon1 = QtGui.QIcon() - icon1.addPixmap(QtGui.QPixmap(u':/exports/export_load.png'), QtGui.QIcon.Normal, QtGui.QIcon.Off) + icon1.addPixmap(QtGui.QPixmap(u':/general/general_load.png'), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.ExportFileSelectPushButton.setIcon(icon1) self.ExportFileSelectPushButton.setObjectName(u'ExportFileSelectPushButton') self.horizontalLayout.addWidget(self.ExportFileSelectPushButton) diff --git a/openlp/plugins/songs/forms/openlpexportform.py b/openlp/plugins/songs/forms/openlpexportform.py index 474034e33..f0f98ad05 100644 --- a/openlp/plugins/songs/forms/openlpexportform.py +++ b/openlp/plugins/songs/forms/openlpexportform.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/plugins/songs/forms/openlpimportdialog.py b/openlp/plugins/songs/forms/openlpimportdialog.py index 4746c57d2..61732d978 100644 --- a/openlp/plugins/songs/forms/openlpimportdialog.py +++ b/openlp/plugins/songs/forms/openlpimportdialog.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/plugins/songs/forms/openlpimportform.py b/openlp/plugins/songs/forms/openlpimportform.py index 192ca0a81..e30d13466 100644 --- a/openlp/plugins/songs/forms/openlpimportform.py +++ b/openlp/plugins/songs/forms/openlpimportform.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -30,4 +30,4 @@ class OpenLPImportForm(QtGui.QDialog, Ui_OpenLPImportDialog): def __init__(self, parent=None): QtGui.QDialog.__init__(self, parent) - self.setupUi(self) \ No newline at end of file + self.setupUi(self) diff --git a/openlp/plugins/songs/forms/opensongexportdialog.py b/openlp/plugins/songs/forms/opensongexportdialog.py index 967e8110f..c40800dfa 100644 --- a/openlp/plugins/songs/forms/opensongexportdialog.py +++ b/openlp/plugins/songs/forms/opensongexportdialog.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/plugins/songs/forms/opensongexportform.py b/openlp/plugins/songs/forms/opensongexportform.py index 6d47f360d..75a732bd5 100644 --- a/openlp/plugins/songs/forms/opensongexportform.py +++ b/openlp/plugins/songs/forms/opensongexportform.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/plugins/songs/forms/opensongimportdialog.py b/openlp/plugins/songs/forms/opensongimportdialog.py index 075110220..e0fd23821 100644 --- a/openlp/plugins/songs/forms/opensongimportdialog.py +++ b/openlp/plugins/songs/forms/opensongimportdialog.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/plugins/songs/forms/opensongimportform.py b/openlp/plugins/songs/forms/opensongimportform.py index 3c8672c7f..6161e4d61 100644 --- a/openlp/plugins/songs/forms/opensongimportform.py +++ b/openlp/plugins/songs/forms/opensongimportform.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/plugins/songs/forms/songbookdialog.py b/openlp/plugins/songs/forms/songbookdialog.py index 6897287e5..823e20eba 100644 --- a/openlp/plugins/songs/forms/songbookdialog.py +++ b/openlp/plugins/songs/forms/songbookdialog.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -67,4 +67,4 @@ class Ui_SongBookDialog(object): def retranslateUi(self, SongBookDialog): SongBookDialog.setWindowTitle(self.trUtf8('Edit Book')) self.NameLabel.setText(self.trUtf8('Name:')) - self.PublisherLabel.setText(self.trUtf8('Publisher:')) \ No newline at end of file + self.PublisherLabel.setText(self.trUtf8('Publisher:')) diff --git a/openlp/plugins/songs/forms/songbookform.py b/openlp/plugins/songs/forms/songbookform.py index 93a746620..d345a82d7 100644 --- a/openlp/plugins/songs/forms/songbookform.py +++ b/openlp/plugins/songs/forms/songbookform.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/plugins/songs/forms/songmaintenancedialog.py b/openlp/plugins/songs/forms/songmaintenancedialog.py index 643676ff6..cbd08f34d 100644 --- a/openlp/plugins/songs/forms/songmaintenancedialog.py +++ b/openlp/plugins/songs/forms/songmaintenancedialog.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/plugins/songs/forms/songmaintenanceform.py b/openlp/plugins/songs/forms/songmaintenanceform.py index d8d6bb5b2..44ad517e1 100644 --- a/openlp/plugins/songs/forms/songmaintenanceform.py +++ b/openlp/plugins/songs/forms/songmaintenanceform.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/plugins/songs/forms/topicsdialog.py b/openlp/plugins/songs/forms/topicsdialog.py index 777db5a52..122af0455 100644 --- a/openlp/plugins/songs/forms/topicsdialog.py +++ b/openlp/plugins/songs/forms/topicsdialog.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/plugins/songs/forms/topicsform.py b/openlp/plugins/songs/forms/topicsform.py index 7d2881479..42ef220f4 100644 --- a/openlp/plugins/songs/forms/topicsform.py +++ b/openlp/plugins/songs/forms/topicsform.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/plugins/songs/lib/__init__.py b/openlp/plugins/songs/lib/__init__.py index 98dbccae4..3825a4abf 100644 --- a/openlp/plugins/songs/lib/__init__.py +++ b/openlp/plugins/songs/lib/__init__.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -25,4 +25,7 @@ from manager import SongManager from songstab import SongsTab -from mediaitem import SongMediaItem \ No newline at end of file +from mediaitem import SongMediaItem +from sofimport import SofImport +from oooimport import OooImport +from songimport import SongImport diff --git a/openlp/plugins/songs/lib/classes.py b/openlp/plugins/songs/lib/classes.py index 95e444a62..171bbdc48 100644 --- a/openlp/plugins/songs/lib/classes.py +++ b/openlp/plugins/songs/lib/classes.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -62,4 +62,4 @@ class Topic(BaseModel): """ Topic model """ - pass \ No newline at end of file + pass diff --git a/openlp/plugins/songs/lib/manager.py b/openlp/plugins/songs/lib/manager.py index 0e662dcbc..dcb49bfcd 100644 --- a/openlp/plugins/songs/lib/manager.py +++ b/openlp/plugins/songs/lib/manager.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -133,6 +133,12 @@ class SongManager(): """ 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 @@ -172,6 +178,12 @@ class SongManager(): """ 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 @@ -211,6 +223,12 @@ class SongManager(): """ 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 diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index cd440e54f..9b81540e6 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -28,7 +28,7 @@ import logging from PyQt4 import QtCore, QtGui from openlp.core.lib import MediaManagerItem, SongXMLParser, \ - BaseListWithDnD, Receiver, str_to_bool + BaseListWithDnD, Receiver, str_to_bool, ItemCapabilities from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm log = logging.getLogger(__name__) @@ -49,8 +49,8 @@ class SongMediaItem(MediaManagerItem): self.ConfigSection = title self.IconPath = u'songs/song' self.ListViewWithDnD_class = SongListView - self.servicePath = None MediaManagerItem.__init__(self, parent, icon, title) + self.singleServiceItem = False self.edit_song_form = EditSongForm(self.parent.songmanager, self) self.song_maintenance_form = SongMaintenanceForm( self.parent.songmanager, self) @@ -271,29 +271,44 @@ class SongMediaItem(MediaManagerItem): self.edit_song_form.exec_() def onDeleteClick(self): - item = self.ListView.currentItem() - if item: - item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] - self.parent.songmanager.delete_song(item_id) - row = self.ListView.row(item) - self.ListView.takeItem(row) + items = self.ListView.selectedIndexes() + if items: + if len(items) == 1: + del_message = self.trUtf8('Delete song?') + else: + del_message = unicode(self.trUtf8('Delete %d songs?')) % len(items) + ans = QtGui.QMessageBox.question(self, + self.trUtf8('Delete Confirmation'), del_message, + QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok| + QtGui.QMessageBox.Cancel), + QtGui.QMessageBox.Ok) + if ans == QtGui.QMessageBox.Cancel: + return + for item in items: + item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] + self.parent.songmanager.delete_song(item_id) + self.onSearchTextButtonClick() - def generateSlideData(self, service_item): + def generateSlideData(self, service_item, item=None): raw_footer = [] author_list = u'' author_audit = [] - ccl = u'' - if self.remoteTriggered is None: - item = self.ListView.currentItem() - if item is None: - return False - item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] + ccli = u'' + if item is None: + if self.remoteTriggered is None: + item = self.ListView.currentItem() + if item is None: + return False + item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] + else: + item_id = self.remoteSong else: - item_id = self.remoteSong - service_item.autoPreviewAllowed = True + item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] + service_item.add_capability(ItemCapabilities.AllowsEdit) + service_item.add_capability(ItemCapabilities.AllowsPreview) + service_item.add_capability(ItemCapabilities.AllowsLoop) song = self.parent.songmanager.get_song(item_id) service_item.theme = song.theme_name - service_item.edit_enabled = True service_item.editId = item_id if song.lyrics.startswith(u' 2: + self.new_song() + + def process_paragraph_line(self, text): + """ + Process a single line. Throw away that text which isn't relevant, i.e. + stuff that appears at the end of the song. + Anything that is OK, append to the current verse + """ + text = text.strip() + if text == u'': + self.blanklines += 1 + if self.blanklines > 1: + return + if self.song.get_title() != u'': + self.finish_verse() + return + self.blanklines = 0 + if self.skip_to_close_bracket: + if text.endswith(u')'): + self.skip_to_close_bracket = False + return + if text.startswith(u'CCL Licence'): + self.italics = False + return + if text == u'A Songs of Fellowship Worship Resource': + return + if text.startswith(u'(NB.') or text.startswith(u'(Regrettably') \ + or text.startswith(u'(From'): + self.skip_to_close_bracket = True + return + if text.startswith(u'Copyright'): + self.song.add_copyright(text) + return + if text == u'(Repeat)': + self.finish_verse() + self.song.repeat_verse() + return + if self.song.get_title() == u'': + if self.song.get_copyright() == u'': + self.add_author(text) + else: + self.song.add_copyright(text) + return + self.add_verse_line(text) + + def process_textportion(self, textportion): + """ + Process a text portion. Here we just get the text and detect if + it's bold or italics. If it's bold then its a song number or song title. + Song titles are in all capitals, so we must bring the capitalization + into line + """ + text = textportion.getString() + text = SongImport.tidy_text(text) + if text.strip() == u'': + return text + if textportion.CharWeight == BOLD: + boldtext = text.strip() + if boldtext.isdigit() and self.song.get_song_number() == '': + self.add_songnumber(boldtext) + return u'' + if self.song.get_title() == u'': + text = self.uncap_text(text) + self.add_title(text) + return text + if text.strip().startswith(u'('): + return text + self.italics = (textportion.CharPosture == ITALIC) + return text + + def new_song(self): + """ + A change of song. Store the old, create a new + ... but only if the last song was complete. If not, stick with it + """ + if self.song: + self.finish_verse() + if not self.song.check_complete(): + return + self.song.finish() + self.song = SongImport(self.manager) + self.skip_to_close_bracket = False + self.is_chorus = False + self.italics = False + self.currentverse = u'' + + def add_songnumber(self, song_no): + """ + Add a song number, store as alternate title. Also use the song + number to work out which songbook we're in + """ + self.song.set_song_number(song_no) + self.song.set_alternate_title(song_no + u'.') + if int(song_no) <= 640: + self.song.set_song_book(u'Songs of Fellowship 1', + u'Kingsway Publications') + elif int(song_no) <= 1150: + self.song.set_song_book(u'Songs of Fellowship 2', + u'Kingsway Publications') + elif int(song_no) <= 1690: + self.song.set_song_book(u'Songs of Fellowship 3', + u'Kingsway Publications') + else: + self.song.set_song_book(u'Songs of Fellowship 4', + u'Kingsway Publications') + + def add_title(self, text): + """ + Add the title to the song. Strip some leading/trailing punctuation that + we don't want in a title + """ + title = text.strip() + if title.startswith(u'\''): + title = title[1:] + if title.endswith(u','): + title = title[:-1] + self.song.set_title(title) + + def add_author(self, text): + """ + Add the author. OpenLP stores them individually so split by 'and', '&' + and comma. + However need to check for "Mr and Mrs Smith" and turn it to + "Mr Smith" and "Mrs Smith". + """ + text = text.replace(u' and ', u' & ') + self.song.parse_author(text) + + def add_verse_line(self, text): + """ + Add a line to the current verse. If the formatting has changed and + we're beyond the second line of first verse, then this indicates + a change of verse. Italics are a chorus + """ + if self.italics != self.is_chorus and ((len(self.song.verses) > 0) or + (self.currentverse.count(u'\n') > 1)): + self.finish_verse() + if self.italics: + self.is_chorus = True + self.currentverse += text + u'\n' + + def finish_verse(self): + """ + Verse is finished, store it. Note in book 1+2, some songs are formatted + incorrectly. Here we try and split songs with missing line breaks into + the correct number of verses. + """ + if self.currentverse.strip() == u'': + return + if self.is_chorus: + versetag = u'C' + splitat = None + else: + versetag = u'V' + splitat = self.verse_splits(self.song.get_song_number()) + if splitat: + ln = 0 + verse = u'' + for line in self.currentverse.split(u'\n'): + ln += 1 + if line == u'' or ln > splitat: + self.song.add_verse(verse, versetag) + ln = 0 + if line: + verse = line + u'\n' + else: + verse = u'' + else: + verse += line + u'\n' + if verse: + self.song.add_verse(verse, versetag) + else: + self.song.add_verse(self.currentverse, versetag) + self.currentverse = u'' + self.is_chorus = False + + + def uncap_text(self, text): + """ + Words in the title are in all capitals, so we lowercase them. + However some of these words, e.g. referring to God need a leading + capital letter. + + There is a complicated word "One", which is sometimes lower and + sometimes upper depending on context. Never mind, keep it lower. + """ + textarr = re.split(u'(\W+)', text) + textarr[0] = textarr[0].capitalize() + for i in range(1, len(textarr)): + # Do not translate these. Fixed strings in SOF song file + if textarr[i] in (u'JESUS', u'CHRIST', u'KING', u'ALMIGHTY', + u'REDEEMER', u'SHEPHERD', u'SON', u'GOD', u'LORD', u'FATHER', + u'HOLY', u'SPIRIT', u'LAMB', u'YOU', u'YOUR', u'I', u'I\'VE', + u'I\'M', u'I\'LL', u'SAVIOUR', u'O', u'YOU\'RE', u'HE', u'HIS', + u'HIM', u'ZION', u'EMMANUEL', u'MAJESTY', u'JESUS\'', u'JIREH', + u'JUDAH', u'LION', u'LORD\'S', u'ABRAHAM', u'GOD\'S', + u'FATHER\'S', u'ELIJAH'): + textarr[i] = textarr[i].capitalize() + else: + textarr[i] = textarr[i].lower() + text = u''.join(textarr) + return text + + def verse_splits(self, song_number): + """ + Because someone at Kingsway forgot to check the 1+2 RTF file, + some verses were not formatted correctly. + """ + if song_number == 11: return 8 + if song_number == 18: return 5 + if song_number == 21: return 6 + if song_number == 23: return 4 + if song_number == 24: return 7 + if song_number == 27: return 4 + if song_number == 31: return 6 + if song_number == 49: return 4 + if song_number == 50: return 8 + if song_number == 70: return 4 + if song_number == 75: return 8 + if song_number == 79: return 6 + if song_number == 97: return 7 + if song_number == 107: return 4 + if song_number == 109: return 4 + if song_number == 133: return 4 + if song_number == 155: return 10 + if song_number == 156: return 8 + if song_number == 171: return 4 + if song_number == 188: return 7 + if song_number == 192: return 4 + if song_number == 208: return 8 + if song_number == 215: return 8 + if song_number == 220: return 4 + if song_number == 247: return 6 + if song_number == 248: return 6 + if song_number == 251: return 8 + if song_number == 295: return 8 + if song_number == 307: return 5 + if song_number == 314: return 6 + if song_number == 325: return 8 + if song_number == 386: return 6 + if song_number == 415: return 4 + if song_number == 426: return 4 + if song_number == 434: return 5 + if song_number == 437: return 4 + if song_number == 438: return 6 + if song_number == 456: return 8 + if song_number == 461: return 4 + if song_number == 469: return 4 + if song_number == 470: return 5 + if song_number == 476: return 6 + if song_number == 477: return 7 + if song_number == 480: return 8 + if song_number == 482: return 4 + if song_number == 512: return 4 + if song_number == 513: return 8 + if song_number == 518: return 5 + if song_number == 520: return 4 + if song_number == 523: return 6 + if song_number == 526: return 8 + if song_number == 527: return 4 + if song_number == 529: return 4 + if song_number == 537: return 4 + if song_number == 555: return 6 + if song_number == 581: return 4 + if song_number == 589: return 6 + if song_number == 590: return 4 + if song_number == 593: return 8 + if song_number == 596: return 4 + if song_number == 610: return 6 + if song_number == 611: return 6 + if song_number == 619: return 8 + if song_number == 645: return 5 + if song_number == 653: return 6 + if song_number == 683: return 7 + if song_number == 686: return 4 + if song_number == 697: return 8 + if song_number == 698: return 4 + if song_number == 704: return 6 + if song_number == 716: return 4 + if song_number == 717: return 6 + if song_number == 730: return 4 + if song_number == 731: return 8 + if song_number == 732: return 8 + if song_number == 738: return 4 + if song_number == 756: return 9 + if song_number == 815: return 6 + if song_number == 830: return 8 + if song_number == 831: return 4 + if song_number == 876: return 6 + if song_number == 877: return 6 + if song_number == 892: return 4 + if song_number == 894: return 6 + if song_number == 902: return 8 + if song_number == 905: return 8 + if song_number == 921: return 6 + if song_number == 940: return 7 + if song_number == 955: return 9 + if song_number == 968: return 8 + if song_number == 972: return 7 + if song_number == 974: return 4 + if song_number == 988: return 6 + if song_number == 991: return 5 + if song_number == 1002: return 8 + if song_number == 1024: return 8 + if song_number == 1044: return 9 + if song_number == 1088: return 6 + if song_number == 1117: return 6 + if song_number == 1119: return 7 + return None + diff --git a/openlp/plugins/songs/lib/songimport.py b/openlp/plugins/songs/lib/songimport.py new file mode 100644 index 000000000..cb780f987 --- /dev/null +++ b/openlp/plugins/songs/lib/songimport.py @@ -0,0 +1,370 @@ +# -*- 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 string +from PyQt4 import QtGui, QtCore +from openlp.core.lib import SongXMLBuilder +from openlp.plugins.songs.lib.models import Song, Author, Topic, Book + +class SongImport(object): + """ + Helper class for import a song from a third party source into OpenLP + + This class just takes the raw strings, and will work out for itself + whether the authors etc already exist and add them or refer to them + as necessary + """ + + def __init__(self, song_manager): + """ + Initialise and create defaults for properties + + song_manager is an instance of a SongManager, through which all + database access is performed + """ + self.manager = song_manager + self.title = u'' + self.song_number = u'' + self.alternate_title = u'' + self.copyright = u'' + self.comment = u'' + self.theme_name = u'' + self.ccli_number = u'' + self.authors = [] + self.topics = [] + self.song_book_name = u'' + self.song_book_pub = u'' + self.verse_order_list = [] + self.verses = [] + self.versecount = 0 + self.choruscount = 0 + self.copyright_string = unicode(QtGui.QApplication.translate( \ + u'SongImport', u'copyright')) + self.copyright_symbol = unicode(QtGui.QApplication.translate( \ + u'SongImport', u'©')) + + @staticmethod + def process_songs_text(manager, text): + songs = [] + songtexts = SongImport.tidy_text(text).split(u'\f') + song = SongImport(manager) + for songtext in songtexts: + if songtext.strip(): + song.process_song_text(songtext.strip()) + if song.check_complete(): + songs.append(song) + song = SongImport(manager) + if song.check_complete(): + songs.append(song) + return songs + + @staticmethod + def tidy_text(text): + """ + Get rid of some dodgy unicode and formatting characters we're not + interested in. Some can be converted to ascii. + """ + text = text.replace(u'\t', u' ') + text = text.replace(u'\r\n', u'\n') + text = text.replace(u'\r', u'\n') + text = text.replace(u'\u2018', u'\'') + text = text.replace(u'\u2019', u'\'') + text = text.replace(u'\u201c', u'"') + text = text.replace(u'\u201d', u'"') + text = text.replace(u'\u2026', u'...') + text = text.replace(u'\u2013', u'-') + text = text.replace(u'\u2014', u'-') + # Remove surplus blank lines, spaces, trailing/leading spaces + while text.find(u' ') >= 0: + text = text.replace(u' ', u' ') + text = text.replace(u'\n ', u'\n') + text = text.replace(u' \n', u'\n') + text = text.replace(u'\n\n\n\n\n', u'\f') + text = text.replace(u'\f ', u'\f') + text = text.replace(u' \f', u'\f') + while text.find(u'\f\f') >= 0: + text = text.replace(u'\f\f', u'\f') + return text + + def process_song_text(self, text): + versetexts = text.split(u'\n\n') + for versetext in versetexts: + if versetext.strip() != u'': + self.process_verse_text(versetext.strip()) + + def process_verse_text(self, text): + lines = text.split(u'\n') + if text.lower().find(self.copyright_string) >= 0 \ + or text.lower().find(self.copyright_symbol) >= 0: + copyright_found = False + for line in lines: + if copyright_found or line.lower().find(self.copyright_string) >= 0\ + or line.lower().find(self.copyright_symbol) >= 0: + copyright_found = True + self.add_copyright(line) + else: + self.parse_author(line) + return + if len(lines) == 1: + self.parse_author(lines[0]) + return + if not self.get_title(): + self.set_title(lines[0]) + self.add_verse(text) + + def get_title(self): + """ + Return the title + """ + return self.title + + def get_copyright(self): + """ + Return the copyright + """ + return self.copyright + + def get_song_number(self): + """ + Return the song number + """ + return self.song_number + + def set_title(self, title): + """ + Set the title + """ + self.title = title + + def set_alternate_title(self, title): + """ + Set the alternate title + """ + self.alternate_title = title + + def set_song_number(self, song_number): + """ + Set the song number + """ + self.song_number = song_number + + def set_song_book(self, song_book, publisher): + """ + Set the song book name and publisher + """ + self.song_book_name = song_book + self.song_book_pub = publisher + + def add_copyright(self, copyright): + """ + Build the copyright field + """ + if self.copyright.find(copyright) >= 0: + return + if self.copyright != u'': + self.copyright += ' ' + self.copyright += copyright + + def parse_author(self, text): + """ + Add the author. OpenLP stores them individually so split by 'and', '&' + and comma. + However need to check for "Mr and Mrs Smith" and turn it to + "Mr Smith" and "Mrs Smith". + """ + for author in text.split(u','): + authors = author.split(u'&') + for i in range(len(authors)): + author2 = authors[i].strip() + if author2.find(u' ') == -1 and i < len(authors) - 1: + author2 = author2 + u' ' \ + + authors[i + 1].strip().split(u' ')[-1] + if author2.endswith(u'.'): + author2 = author2[:-1] + if author2: + self.add_author(author2) + + def add_author(self, author): + """ + Add an author to the list + """ + if author in self.authors: + return + self.authors.append(author) + + def add_verse(self, verse, versetag=None): + """ + Add a verse. This is the whole verse, lines split by \n + Verse tag can be V1/C1/B etc, or 'V' and 'C' (will count the verses/ + choruses itself) or None, where it will assume verse + It will also attempt to detect duplicates. In this case it will just + add to the verse order + """ + for (oldversetag, oldverse) in self.verses: + if oldverse.strip() == verse.strip(): + self.verse_order_list.append(oldversetag) + return + if versetag == u'V' or not versetag: + self.versecount += 1 + versetag = u'V' + unicode(self.versecount) + if versetag.startswith(u'C'): + self.choruscount += 1 + if versetag == u'C': + versetag += unicode(self.choruscount) + self.verses.append([versetag, verse.rstrip()]) + self.verse_order_list.append(versetag) + if versetag.startswith(u'V') and self.contains_verse(u'C1'): + self.verse_order_list.append(u'C1') + + def repeat_verse(self): + """ + Repeat the previous verse in the verse order + """ + self.verse_order_list.append(self.verse_order_list[-1]) + + def contains_verse(self, versetag): + return versetag in self.verse_order_list + + def check_complete(self): + """ + Check the mandatory fields are entered (i.e. title and a verse) + Author not checked here, if no author then "Author unknown" is + automatically added + """ + if self.title == u'' or len(self.verses) == 0: + return False + else: + return True + + def remove_punctuation(self, text): + """ + Remove punctuation from the string for searchable fields + """ + for c in string.punctuation: + text = text.replace(c, u'') + return text + + def finish(self): + """ + All fields have been set to this song. Write it away + """ + if len(self.authors) == 0: + self.authors.append(u'Author unknown') + self.commit_song() + #self.print_song() + + def commit_song(self): + """ + Write the song and it's fields to disk + """ + song = Song() + song.title = self.title + song.search_title = self.remove_punctuation(self.title) \ + + '@' + self.alternate_title + song.song_number = self.song_number + song.search_lyrics = u'' + sxml = SongXMLBuilder() + sxml.new_document() + sxml.add_lyrics_to_song() + for (versetag, versetext) in self.verses: + if versetag[0] == u'C': + versetype = u'Chorus' + elif versetag[0] == u'V': + versetype = u'Verse' + elif versetag[0] == u'B': + versetype = u'Bridge' + elif versetag[0] == u'I': + versetype = u'Intro' + elif versetag[0] == u'P': + versetype = u'Prechorus' + elif versetag[0] == u'E': + versetype = u'Ending' + else: + versetype = u'Other' + sxml.add_verse_to_lyrics(versetype, versetag[1:], versetext) + song.search_lyrics += u' ' + self.remove_punctuation(versetext) + song.lyrics = unicode(sxml.extract_xml(), u'utf-8') + song.verse_order = u' '.join(self.verse_order_list) + song.copyright = self.copyright + song.comment = self.comment + 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) + if author is None: + author = Author() + author.display_name = authortext + author.last_name = authortext.split(u' ')[-1] + author.first_name = u' '.join(authortext.split(u' ')[:-1]) + self.manager.save_author(author) + song.authors.append(author) + if self.song_book_name: + song_book = self.manager.get_book_by_name(self.song_book_name) + if song_book is None: + song_book = Book() + song_book.name = self.song_book_name + song_book.publisher = self.song_book_pub + self.manager.save_book(song_book) + song.song_book_id = song_book.id + for topictext in self.topics: + topic = self.manager.get_topic_by_name(topictext) + if topic is None: + topic = Topic() + topic.name = topictext + self.manager.save_topic(topic) + song.topics.append(topictext) + self.manager.save_song(song) + + def print_song(self): + """ + For debugging + """ + print u'========================================' \ + + u'========================================' + print u'TITLE: ' + self.title + print u'ALT TITLE: ' + self.alternate_title + for (versetag, versetext) in self.verses: + print u'VERSE ' + versetag + u': ' + versetext + print u'ORDER: ' + u' '.join(self.verse_order_list) + for author in self.authors: + print u'AUTHOR: ' + author + if self.copyright: + print u'COPYRIGHT: ' + self.copyright + if self.song_book_name: + print u'BOOK: ' + self.song_book_name + if self.song_book_pub: + print u'BOOK PUBLISHER: ' + self.song_book_pub + if self.song_number: + print u'NUMBER: ' + self.song_number + for topictext in self.topics: + print u'TOPIC: ' + topictext + if self.comment: + print u'COMMENT: ' + self.comment + if self.theme_name: + print u'THEME: ' + self.theme_name + if self.ccli_number: + print u'CCLI: ' + self.ccli_number + + diff --git a/openlp/plugins/songs/lib/songstab.py b/openlp/plugins/songs/lib/songstab.py index 7a4feb449..392b15691 100644 --- a/openlp/plugins/songs/lib/songstab.py +++ b/openlp/plugins/songs/lib/songstab.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -89,4 +89,4 @@ class SongsTab(SettingsTab): def save(self): self.config.set_config(u'search as type', unicode(self.song_search)) - self.config.set_config(u'display songbar', unicode(self.song_bar)) \ No newline at end of file + self.config.set_config(u'display songbar', unicode(self.song_bar)) diff --git a/openlp/plugins/songs/lib/songxml.py b/openlp/plugins/songs/lib/songxml.py index f9cef7fce..71506ff2d 100644 --- a/openlp/plugins/songs/lib/songxml.py +++ b/openlp/plugins/songs/lib/songxml.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -669,4 +669,4 @@ class Song(object): return res __all__ = ['SongException', 'SongTitleError', 'SongSlideError', 'SongTypeError', - 'SongFeatureError', 'Song'] \ No newline at end of file + 'SongFeatureError', 'Song'] diff --git a/openlp/plugins/songs/lib/tables.py b/openlp/plugins/songs/lib/tables.py index 817d4c296..24137d7b1 100644 --- a/openlp/plugins/songs/lib/tables.py +++ b/openlp/plugins/songs/lib/tables.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -96,4 +96,4 @@ Index(u'authors_songs_song', authors_songs_table.c.song_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) \ No newline at end of file + songs_topics_table.c.topic_id) diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py index 9ebaa99b2..cd3470e86 100644 --- a/openlp/plugins/songs/songsplugin.py +++ b/openlp/plugins/songs/songsplugin.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -27,8 +27,9 @@ import logging from PyQt4 import QtCore, QtGui -from openlp.core.lib import Plugin, build_icon, PluginStatus -from openlp.plugins.songs.lib import SongManager, SongMediaItem, SongsTab +from openlp.core.lib import Plugin, build_icon, PluginStatus, Receiver +from openlp.plugins.songs.lib import SongManager, SongMediaItem, SongsTab, \ + SofImport, OooImport from openlp.plugins.songs.forms import OpenLPImportForm, OpenSongExportForm, \ OpenSongImportForm, OpenLPExportForm @@ -102,24 +103,44 @@ class SongsPlugin(Plugin): self.ImportOpenlp1Item.setObjectName(u'ImportOpenlp1Item') self.ImportOpenlp2Item = QtGui.QAction(import_menu) self.ImportOpenlp2Item.setObjectName(u'ImportOpenlp2Item') + self.ImportSofItem = QtGui.QAction(import_menu) + self.ImportSofItem.setObjectName(u'ImportSofItem') + self.ImportOooItem = QtGui.QAction(import_menu) + self.ImportOooItem.setObjectName(u'ImportOooItem') # Add to menus self.ImportSongMenu.addAction(self.ImportOpenlp1Item) self.ImportSongMenu.addAction(self.ImportOpenlp2Item) self.ImportSongMenu.addAction(self.ImportOpenSongItem) + self.ImportSongMenu.addAction(self.ImportSofItem) + self.ImportSongMenu.addAction(self.ImportOooItem) import_menu.addAction(self.ImportSongMenu.menuAction()) # Translations... self.ImportSongMenu.setTitle(import_menu.trUtf8('&Song')) self.ImportOpenSongItem.setText(import_menu.trUtf8('OpenSong')) self.ImportOpenlp1Item.setText(import_menu.trUtf8('openlp.org 1.0')) self.ImportOpenlp1Item.setToolTip( - import_menu.trUtf8('Export songs in openlp.org 1.0 format')) + import_menu.trUtf8('Import songs in openlp.org 1.0 format')) self.ImportOpenlp1Item.setStatusTip( - import_menu.trUtf8('Export songs in openlp.org 1.0 format')) + import_menu.trUtf8('Import songs in openlp.org 1.0 format')) self.ImportOpenlp2Item.setText(import_menu.trUtf8('OpenLP 2.0')) self.ImportOpenlp2Item.setToolTip( - import_menu.trUtf8('Export songs in OpenLP 2.0 format')) + import_menu.trUtf8('Import songs in OpenLP 2.0 format')) self.ImportOpenlp2Item.setStatusTip( - import_menu.trUtf8('Export songs in OpenLP 2.0 format')) + import_menu.trUtf8('Import songs in OpenLP 2.0 format')) + self.ImportSofItem.setText( + import_menu.trUtf8('Songs of Fellowship')) + self.ImportSofItem.setToolTip( + import_menu.trUtf8('Import songs from the VOLS1_2.RTF, sof3words' \ + + '.rtf and sof4words.rtf supplied with the music books')) + self.ImportSofItem.setStatusTip( + import_menu.trUtf8('Import songs from the VOLS1_2.RTF, sof3words' \ + + '.rtf and sof4words.rtf supplied with the music books')) + self.ImportOooItem.setText( + import_menu.trUtf8('Generic Document/Presentation Import')) + self.ImportOooItem.setToolTip( + import_menu.trUtf8('Import songs from Word/Writer/Powerpoint/Impress')) + self.ImportOooItem.setStatusTip( + import_menu.trUtf8('Import songs from Word/Writer/Powerpoint/Impress')) # Signals and slots QtCore.QObject.connect(self.ImportOpenlp1Item, QtCore.SIGNAL(u'triggered()'), self.onImportOpenlp1ItemClick) @@ -127,6 +148,10 @@ class SongsPlugin(Plugin): QtCore.SIGNAL(u'triggered()'), self.onImportOpenlp1ItemClick) QtCore.QObject.connect(self.ImportOpenSongItem, QtCore.SIGNAL(u'triggered()'), self.onImportOpenSongItemClick) + QtCore.QObject.connect(self.ImportSofItem, + QtCore.SIGNAL(u'triggered()'), self.onImportSofItemClick) + QtCore.QObject.connect(self.ImportOooItem, + QtCore.SIGNAL(u'triggered()'), self.onImportOooItemClick) self.ImportSongMenu.menuAction().setVisible(False) def add_export_menu_item(self, export_menu): @@ -169,6 +194,34 @@ class SongsPlugin(Plugin): def onImportOpenSongItemClick(self): self.opensong_import_form.show() + def onImportSofItemClick(self): + filenames = QtGui.QFileDialog.getOpenFileNames( + None, self.trUtf8('Open Songs of Fellowship file'), + u'', u'Songs of Fellowship file (*.rtf *.RTF)') + try: + for filename in filenames: + sofimport = SofImport(self.songmanager) + sofimport.import_sof(unicode(filename)) + except: + log.exception('Could not import SoF file') + QtGui.QMessageBox.critical(None, + self.ImportSongMenu.trUtf8('Import Error'), + self.ImportSongMenu.trUtf8('Error importing Songs of ' + + 'Fellowship file.\nOpenOffice.org must be installed' + + ' and you must be using an unedited copy of the RTF' + + ' included with the Songs of Fellowship Music Editions'), + QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok), + QtGui.QMessageBox.Ok) + Receiver.send_message(u'load_song_list') + + def onImportOooItemClick(self): + filenames = QtGui.QFileDialog.getOpenFileNames( + None, self.trUtf8('Open documents or presentations'), + u'', u'All Files(*.*)') + oooimport = OooImport(self.songmanager) + oooimport.import_docs(filenames) + Receiver.send_message(u'load_song_list') + def onExportOpenlp1ItemClicked(self): self.openlp_export_form.show() diff --git a/openlp/plugins/songs/test/data_openlp1/amazing.olp b/openlp/plugins/songs/test/data_openlp1/amazing.olp deleted file mode 100644 index ef65237bc..000000000 Binary files a/openlp/plugins/songs/test/data_openlp1/amazing.olp and /dev/null differ diff --git a/openlp/plugins/songs/test/data_openlp1/sample3.olp b/openlp/plugins/songs/test/data_openlp1/sample3.olp deleted file mode 100644 index f29419894..000000000 Binary files a/openlp/plugins/songs/test/data_openlp1/sample3.olp and /dev/null differ diff --git a/openlp/plugins/songs/test/data_opensong/Amazing Grace b/openlp/plugins/songs/test/data_opensong/Amazing Grace deleted file mode 100644 index 06f3edd92..000000000 --- a/openlp/plugins/songs/test/data_opensong/Amazing Grace +++ /dev/null @@ -1,38 +0,0 @@ - - - Amazing Grace - John Newton - 1982 Jubilate Hymns Limited - - - - - 1037882 - God: Attributes - - - - - [V1] -. D D7 G D Bm E A A7 - Amazing grace how sweet the sound that saved a wretch like me; -. D D7 G D Bm A G D - I once was lost but now I'm found, was blind but now I see. - -[V2] -. D D7 G D Bm E A A7 - Twas grace that taught my heart to fear, and grace my fears relieved; -. D D7 G D Bm A G D - How precious did that grace appear the hour I first believed! - -[V3] -. D D7 G D Bm E A A7 - Through many dangers, toils, and snares I have already come; -. D D7 G D Bm A G D - 'Tis grace that brought me safe thus far and grace will lead me home. - -[V4] -. D D7 G D Bm E A A7 - When we've been there ten thousand years bright shining as the sun; -. D D7 G D Bm A G D - We've no less days to sing God's praise than when we'd first begun! \ No newline at end of file diff --git a/openlp/plugins/songs/test/data_opensong/PÃ¥ en fjern ensom høj b/openlp/plugins/songs/test/data_opensong/PÃ¥ en fjern ensom høj deleted file mode 100644 index 6023414ca..000000000 --- a/openlp/plugins/songs/test/data_opensong/PÃ¥ en fjern ensom høj +++ /dev/null @@ -1,56 +0,0 @@ -PÃ¥ en fjern ensom høj[V1] - PÃ¥ en fjern ensom høj, - Jesu kors dyrest stod, - symbolet pÃ¥ smerte og skam. - O, jeg elsker det kors, - hvor Guds søn gjorde bod, - da forbandelsen blev lagt pÃ¥ ham. - -[C1] - Jeg vil elske det urgamle kors, - i det kraft er der sejer og sang. - Lad mig favne det hellige kors, - det med kronen ombyttes engang. - -[V2] - O, det urgamle kors, - med sin hvile og fred, - tilhyllet i verdens foragt. - Se, det hellige lam, - som pÃ¥ Golgatha stred, - og til jorden Guds nÃ¥de har bragt. - -[C2] - Jeg vil elske det urgamle kors, - i det kraft er der sejer og sang. - Lad mig favne det hellige kors, - det med kronen ombyttes engang. - -[V3] - I det urgamle kors, - i hans blod farvet rødt, - en underfuld skønhed jeg ser. - Ja, det var pÃ¥ det kors, - at han selv blev forstødt, - nu skal aldrig for dommen jeg mer. - -[C3] - Jeg vil elske det urgamle kors, - i det kraft er der sejer og sang. - Lad mig favne det hellige kors, - det med kronen ombyttes engang. - -[V4] - For det urgamle kors, - stÃ¥r mit hjerte i brand, - min plads jeg nu har ved dets fod. - Til han kalder en dag, - mig til himmelens land, - og til hvilen hos Faderen god. - -[C4] - Jeg vil elske det urgamle kors, - i det kraft er der sejer og sang. - Lad mig favne det hellige kors, - det med kronen ombyttes engang. -V1 C1 V2 C2 V3 C3 V4 C4 \ No newline at end of file diff --git a/openlp/plugins/songs/test/data_opensong/The Solid Rock b/openlp/plugins/songs/test/data_opensong/The Solid Rock deleted file mode 100644 index bb1eecc97..000000000 --- a/openlp/plugins/songs/test/data_opensong/The Solid Rock +++ /dev/null @@ -1,28 +0,0 @@ - - - The Solid Rock - Edward Mote and John B. Dykes - Public Domain - V1 C V2 C V3 C V4 C - 101740 - Christ: Victory - Fruit: Peace/Comfort - [V] -. E B A B E -1My hope is built on nothing less than Jesus' blood and righteousness; -2When darkness veils His lovely face, I rest on His un___changing grace. -3His oath, His cove_____nant, His blood|support me in the whelming flood; -4When He shall come with trumpet sound, O may I then in Him be found; -. E B A B E -1I dare not trust the sweetest frame, but wholly lean on Jesus' name. -2In every high and stormy gale, my anchor holds within the veil. -3When all around my soul gives way, He then is all my hope and stay. -4Dressed in His righteous___ness alone, fault___less to stand be_fore the throne. - -[C] -. E A - On Christ, the solid rock I stand; -. E B - All other ground is sinking sand, -. A B E - All other ground is sinking sand. \ No newline at end of file diff --git a/openlp/plugins/songs/test/data_text/CCLI example.txt b/openlp/plugins/songs/test/data_text/CCLI example.txt deleted file mode 100644 index 6a5c23222..000000000 --- a/openlp/plugins/songs/test/data_text/CCLI example.txt +++ /dev/null @@ -1,36 +0,0 @@ -Song Title Here - - -Chorus 1 -Lyrics -Lyrics -Lyrics -Lyrics - - -Verse 1 -Lyrics -Lyrics -Lyrics - - -Verse 2 -Lyrics -Lyrics -Lyrics - - -Misc 1 -(BRIDGE) -Lyrics -Lyrics -Lyrics -Lyrics - - - -CCLI Song No. 1234567 -© 1996 Publisher Info -Author/artist name -For use solely in accordance with the SongSelect Advanced Terms of Agreement. All rights Reserved. -CCLI License No. 1234567 \ No newline at end of file diff --git a/openlp/plugins/songs/test/data_text/PÃ¥EnFjern.txt b/openlp/plugins/songs/test/data_text/PÃ¥EnFjern.txt deleted file mode 100644 index 34a6da1ce..000000000 --- a/openlp/plugins/songs/test/data_text/PÃ¥EnFjern.txt +++ /dev/null @@ -1,61 +0,0 @@ -På en fjern ensom høj - -Verse 1 -På en fjern ensom høj, -Jesu kors dyrest stod, -symbolet på smerte og skam. -O, jeg elsker det kors, -hvor Guds søn gjorde bod, -da forbandelsen blev lagt på ham. - -Chorus 1 -Jeg vil elske det urgamle kors, -i det kraft er der sejer og sang. -Lad mig favne det hellige kors, -det med kronen ombyttes engang. - -Verse 2 -O, det urgamle kors, -med sin hvile og fred, -tilhyllet i verdens foragt. -Se, det hellige lam, -som på Golgatha stred, -og til jorden Guds nåde har bragt. - -Chorus 2 -Jeg vil elske det urgamle kors, -i det kraft er der sejer og sang. -Lad mig favne det hellige kors, -det med kronen ombyttes engang. - -Verse 3 -I det urgamle kors, -i hans blod farvet rødt, -en underfuld skønhed jeg ser. -Ja, det var på det kors, -at han selv blev forstødt, -nu skal aldrig for dommen jeg mer. - -Chorus 3 -Jeg vil elske det urgamle kors, -i det kraft er der sejer og sang. -Lad mig favne det hellige kors, -det med kronen ombyttes engang. - -Verse 4 -For det urgamle kors, -står mit hjerte i brand, -min plads jeg nu har ved dets fod. -Til han kalder en dag, -mig til himmelens land, -og til hvilen hos Faderen god. - -Chorus 4 -Jeg vil elske det urgamle kors, -i det kraft er der sejer og sang. -Lad mig favne det hellige kors, -det med kronen ombyttes engang. - -CCLI Song No. -© -Georg Bennard diff --git a/openlp/plugins/songs/test/data_xml/amazing1.xml b/openlp/plugins/songs/test/data_xml/amazing1.xml deleted file mode 100644 index 9cc7e1b97..000000000 --- a/openlp/plugins/songs/test/data_xml/amazing1.xml +++ /dev/null @@ -1,22 +0,0 @@ - - -Amazing Grace - - -Amazing grace how sweet the sound that saved a wretch like me; -I once was lost but now I'm found, was blind but now I see. - - -Twas grace that taught my heart to fear, and grace my fears relieved; -How precious did that grace appear the hour I first believed! - - -Through many dangers, toils, and snares I have already come; -'Tis grace that brought me safe thus far and grace will lead me home. - - -When we've been there ten thousand years bright shining as the sun; -We've no less days to sing God's praise than when we'd first begun! - - - \ No newline at end of file diff --git a/openlp/plugins/songs/test/data_xml/amazing2.xml b/openlp/plugins/songs/test/data_xml/amazing2.xml deleted file mode 100644 index 8ea0666ef..000000000 --- a/openlp/plugins/songs/test/data_xml/amazing2.xml +++ /dev/null @@ -1,22 +0,0 @@ - - -Amazing Grace - - -Amazing grace how sweet the sound that saved a wretch like me; -I once was lost but now I'm found, was blind but now I see. - - -Twas grace that taught my heart to fear, and grace my fears relieved; -How precious did that grace appear the hour I first believed! - - -Through many dangers, toils, and snares I have already come; -'Tis grace that brought me safe thus far and grace will lead me home. - - -When we've been there ten thousand years bright shining as the sun; -We've no less days to sing God's praise than when we'd first begun! - - - \ No newline at end of file diff --git a/openlp/plugins/songs/test/data_xml/danish1.xml b/openlp/plugins/songs/test/data_xml/danish1.xml deleted file mode 100644 index ec53ac150..000000000 --- a/openlp/plugins/songs/test/data_xml/danish1.xml +++ /dev/null @@ -1,62 +0,0 @@ - - -PÃ¥ en fjern ensom høj - - -PÃ¥ en fjern ensom høj, -Jesu kors dyrest stod, -symbolet pÃ¥ smerte og skam. -O, jeg elsker det kors, -hvor Guds søn gjorde bod, -da forbandelsen blev lagt pÃ¥ ham. - - -Jeg vil elske det urgamle kors, -i det kraft er der sejer og sang. -Lad mig favne det hellige kors, -det med kronen ombyttes engang. - - -O, det urgamle kors, -med sin hvile og fred, -tilhyllet i verdens foragt. -Se, det hellige lam, -som pÃ¥ Golgatha stred, -og til jorden Guds nÃ¥de har bragt. - - -Jeg vil elske det urgamle kors, -i det kraft er der sejer og sang. -Lad mig favne det hellige kors, -det med kronen ombyttes engang. - - -I det urgamle kors, -i hans blod farvet rødt, -en underfuld skønhed jeg ser. -Ja, det var pÃ¥ det kors, -at han selv blev forstødt, -nu skal aldrig for dommen jeg mer. - - -Jeg vil elske det urgamle kors, -i det kraft er der sejer og sang. -Lad mig favne det hellige kors, -det med kronen ombyttes engang. - - -For det urgamle kors, -stÃ¥r mit hjerte i brand, -min plads jeg nu har ved dets fod. -Til han kalder en dag, -mig til himmelens land, -og til hvilen hos Faderen god. - - -Jeg vil elske det urgamle kors, -i det kraft er der sejer og sang. -Lad mig favne det hellige kors, -det med kronen ombyttes engang. - - - diff --git a/openlp/plugins/songs/test/data_xml/danish2.xml b/openlp/plugins/songs/test/data_xml/danish2.xml deleted file mode 100644 index e7edb5bf5..000000000 --- a/openlp/plugins/songs/test/data_xml/danish2.xml +++ /dev/null @@ -1,62 +0,0 @@ - - -På en fjern ensom høj - - -På en fjern ensom høj, -Jesu kors dyrest stod, -symbolet på smerte og skam. -O, jeg elsker det kors, -hvor Guds søn gjorde bod, -da forbandelsen blev lagt på ham. - - -Jeg vil elske det urgamle kors, -i det kraft er der sejer og sang. -Lad mig favne det hellige kors, -det med kronen ombyttes engang. - - -O, det urgamle kors, -med sin hvile og fred, -tilhyllet i verdens foragt. -Se, det hellige lam, -som på Golgatha stred, -og til jorden Guds nåde har bragt. - - -Jeg vil elske det urgamle kors, -i det kraft er der sejer og sang. -Lad mig favne det hellige kors, -det med kronen ombyttes engang. - - -I det urgamle kors, -i hans blod farvet rødt, -en underfuld skønhed jeg ser. -Ja, det var på det kors, -at han selv blev forstødt, -nu skal aldrig for dommen jeg mer. - - -Jeg vil elske det urgamle kors, -i det kraft er der sejer og sang. -Lad mig favne det hellige kors, -det med kronen ombyttes engang. - - -For det urgamle kors, -står mit hjerte i brand, -min plads jeg nu har ved dets fod. -Til han kalder en dag, -mig til himmelens land, -og til hvilen hos Faderen god. - - -Jeg vil elske det urgamle kors, -i det kraft er der sejer og sang. -Lad mig favne det hellige kors, -det med kronen ombyttes engang. - - - diff --git a/openlp/plugins/songs/test/data_xml/format1.xml b/openlp/plugins/songs/test/data_xml/format1.xml deleted file mode 100644 index f80ea8704..000000000 --- a/openlp/plugins/songs/test/data_xml/format1.xml +++ /dev/null @@ -1,22 +0,0 @@ - - -Amazing Grace - - -Amazing grace how sweet the sound that saved a wretch like me; -I once was lost but now I'm found, was blind but now I see. - - -Twas grace that taught my heart to fear, and grace my fears relieved; -How precious did that grace appear the hour I first believed! - - -Through many dangers, toils, and snares I have already come; -'Tis grace that brought me safe thus far and grace will lead me home. - - -When we've been there ten thousand years bright shining as the sun; -We've no less days to sing God's praise than when we'd first begun! - - - \ No newline at end of file diff --git a/openlp/plugins/songs/test/data_xml/sample1.xml b/openlp/plugins/songs/test/data_xml/sample1.xml deleted file mode 100644 index 11a8576ad..000000000 --- a/openlp/plugins/songs/test/data_xml/sample1.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - Amazing Grace - - name of verse specific theme - any text - - Amazing grace, how ... - - - A b c - D e f - - ... - - - any text - ... - - - - Erstaunliche Anmut - - Erstaunliche Anmut, wie - ... - - - ... - - - diff --git a/openlp/plugins/songs/test/test_song_basic.py b/openlp/plugins/songs/test/test_song_basic.py deleted file mode 100644 index 4e134cea8..000000000 --- a/openlp/plugins/songs/test/test_song_basic.py +++ /dev/null @@ -1,177 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 -""" -OpenLP - Open Source Lyrics Projection -Copyright (c) 2008 Raoul Snyman -Portions copyright (c) 2008 Martin Thompson, Tim Bentley, 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 py.test -import os -import sys - -__ThisDir__ = os.path.dirname(__file__) -if "" == __ThisDir__ : - __ThisDir__ = os.path.abspath(u'.') - -sys.path.append(os.path.abspath(u'%s/../../../..'%__ThisDir__)) - -from openlp.plugins.songs.lib.songxml import * - -class Test_Basic(object): - """Class for first initialization check - set-get functions - """ - - def test_Creation(self): - """Init: Create as empty""" - s = Song() - assert(True) - - def test_Title1(self): - """Set an empty title - raises an exception""" - s = Song() - py.test.raises(SongTitleError, s.set_title, '') - - def test_Title2(self): - """Set a normal title""" - s = Song() - t = "A normal title" - s.set_title(t) - assert(s.get_title() == t) - assert(s.get_search_title() == t) - - def test_Title3(self): - """Set a titel with punctuation 1""" - s = Song() - t1 = "Hey! Come on, ya programmers*" - t2 = "Hey Come on ya programmers" - s.set_title(t1) - assert(s.get_title() == t1) - assert(s.get_search_title() == t2) - - def test_Title4(self): - """Set a titel with punctuation 2""" - s = Song() - t1 = "??#Hey! Come on, ya programmers*" - t2 = "Hey Come on ya programmers" - s.set_title(t1) - assert(s.get_title() == t1) - assert(s.get_search_title() == t2) - - def test_Title5(self): - """ - Set a title - Where searchable title becomes empty raises an exception - """ - s = Song() - py.test.raises(SongTitleError, s.set_title, ',*') - - def test_Copyright(self): - """Set a copyright string""" - s = Song() - assert(s.get_copyright() == '') - s.set_copyright(u'A B Car') - assert(s.get_copyright() == 'A B Car') - - def test_SongCclino(self): - """Set a SongCcliNo""" - s = Song() - assert(s.get_song_cclino() == '') - s.set_song_cclino(12345) - assert(s.get_song_cclino() == '12345') - - def test_SongBook(self): - """Set a songbook value""" - s = Song() - assert(s.get_song_book() == '') - s.set_song_book(u'Hymns') - assert(s.get_song_book() == u'Hymns') - - def test_SongNumber(self): - """Set a song number""" - s = Song() - assert(s.get_song_number() == '') - s.set_song_number(278) - assert(s.get_song_number() == '278') - - def test_Theme(self): - """Set a theme name""" - s = Song() - assert(s.get_theme() == '') - s.set_theme(u'Red') - assert(s.get_theme() == 'Red') - - def test_VerseOrder(self): - """Set a verse order""" - s = Song() - assert(s.get_verse_order() == '') - s.set_verse_order(u'V1 C V2') - assert(s.get_verse_order() == 'V1 C V2') - - def test_Comments(self): - """Set a comment""" - s = Song() - assert(s.get_comments() == '') - s.set_comments(u'a comment') - assert(s.get_comments() == 'a comment') - - def test_AuthorList(self): - """Set author lists""" - s = Song() - assert(s.get_author_list(True) == '') - assert(s.get_author_list(False) == []) - t1 = "John Newton" - s.set_author_list(t1) - assert(s.get_author_list(True) == t1) - assert(s.get_author_list(False) == [t1]) - s.set_author_list(u' Peter Done , John Newton') - assert(s.get_author_list(True)== 'Peter Done, John Newton') - assert(s.get_author_list(False) == ["Peter Done", u'John Newton']) - s.set_author_list(None) - assert(s.get_author_list(True) == '') - assert(s.get_author_list(False) == []) - s.set_author_list(u'') - assert(s.get_author_list(True) == '') - assert(s.get_author_list(False) == [""]) - s.set_author_list([]) - assert(s.get_author_list(True) == '') - assert(s.get_author_list(False) == [""]) - - def test_CategoryArray(self): - """Set categories""" - s = Song() - assert(s.get_category_array(True) == '') - assert(s.get_category_array(False) == []) - t1 = "Gospel" - s.set_category_array(t1) - assert(s.get_category_array(True) == t1) - assert(s.get_category_array(False) == [t1]) - s.set_category_array(u' Gospel, Hymns ') - assert(s.get_category_array(True) == 'Gospel, Hymns') - assert(s.get_category_array(False) == ["Gospel", u'Hymns']) - s.set_category_array(None) - assert(s.get_category_array(True) == '') - assert(s.get_category_array(False) == []) - s.set_category_array(u'') - assert(s.get_category_array(True) == '') - assert(s.get_category_array(False) == [""]) - s.set_category_array([]) - assert(s.get_category_array(True) == '') - assert(s.get_category_array(False) == [""]) - -if '__main__' == __name__: - r = Test_Basic() - r.test_asString() diff --git a/openlp/plugins/songs/test/test_song_opensong.py b/openlp/plugins/songs/test/test_song_opensong.py deleted file mode 100644 index 8b46b1df9..000000000 --- a/openlp/plugins/songs/test/test_song_opensong.py +++ /dev/null @@ -1,186 +0,0 @@ -# -*- coding:iso-8859-1 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 -""" -OpenLP - Open Source Lyrics Projection -Copyright (c) 2008 Raoul Snyman -Portions copyright (c) 2008 Martin Thompson, Tim Bentley, 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 os -import sys - -__ThisDir__ = os.path.dirname(__file__) -if "" == __ThisDir__ : - __ThisDir__ = os.path.abspath(u'.') - -sys.path.append(os.path.abspath(u'%s/../../../..'%__ThisDir__)) - -from openlp.plugins.songs.lib.songxml import * - - -_sample1 = \ -''' - - - - - - - - [V1] -. chord line 1 - verse 1 line 1 -. chord line 2 - verse 1 line 2 - -[V2] - verse 2 line 1 - verse 2 line 2 - -[V3] - verse 3 line 1 - verse 3 line 2 - -[C] -. chorus chord line 1 - chorus line 1 -. chorus chord line 2 - chorus line 2 - -''' - -_sample2 = \ -''' - - - - - - - - [V] -1verse 1 line 1 -2verse 2 line 1 -3verse 3 line 1 -1verse 1 line 2 -2verse 2 line 2 -3verse 3 line 2 - -[C] - chorus line 1 - chorus line 2 - -''' - -_sample3 = \ -''' - - - - - - - - [V] -1verse 1 line 1 -2verse 2 line 1 -3verse 3 line 1 -1verse 1 line 2 -2verse 2 line 2 -3verse 3 line 2 - -[C] - chorus line 1 - chorus line 2 - -[P] - pre-chorus line 1 - pre-chorus line 2 - pre-chorus line 3 - -[B] - bridge line 1 - bridge line 2 - - -''' - -class Test_OpenSong(object): - """Test cases for converting from OpenSong xml format to Song""" - - def test_sample1(self): - """OpenSong: handwritten sample1""" - s = Song() - s.from_opensong_buffer(_sample1) - l = s.get_lyrics() - assert(len(l) == (4*3+3)) - assert(s.get_number_of_slides() == 4) - - def test_sample2(self): - """OpenSong: handwritten sample2 - with verses and chorus""" - s = Song() - s.from_opensong_buffer(_sample2) - l = s.get_lyrics() - assert(len(l) == (4*3+3)) - assert(s.get_number_of_slides() == 4) - - def test_sample3(self): - """OpenSong: handwritten sample3 - with verses, chorus, bridge and pre-chorus""" - s = Song() - s.from_opensong_buffer(_sample3) - l = s.get_lyrics() - assert(len(l) == (4*3+4+5+4)) - assert(s.get_number_of_slides() == 6) - - def test_file1(self): - """OpenSong: parse Amazing Grace""" - global __ThisDir__ - s = Song() - s.from_opensong_file(u'%s/data_opensong/Amazing Grace'%(__ThisDir__)) - assert(s.get_title() == 'Amazing Grace') - assert(s.get_copyright() == '1982 Jubilate Hymns Limited') - assert(s.get_song_cclino() == '1037882') - assert(s.get_category_array(True) == 'God: Attributes') - assert(s.get_author_list(True) == 'John Newton') - assert(s.get_verse_order() == '') - assert(s.get_number_of_slides() == 4) - - def test_file2(self): - """OpenSong: parse The Solid Rock""" - s = Song() - s.from_opensong_file(u'%s/data_opensong/The Solid Rock'%(__ThisDir__)) - assert(s.get_title() == 'The Solid Rock') - assert(s.get_copyright() == 'Public Domain') - assert(s.get_song_cclino() == '101740') - assert(s.get_category_array(True) == 'Christ: Victory, Fruit: Peace/Comfort') - assert(s.get_author_list(True) == 'Edward Mote, John B. Dykes') - assert(s.get_verse_order() == 'V1 C V2 C V3 C V4 C') - assert(s.get_number_of_slides() == 5) - - def test_file3(self): - """OpenSong: parse 'På en fjern ensom høj' (danish)""" - #FIXME: problem with XML convert and danish characters - s = Song() - s.from_opensong_file(u'%s/data_opensong/På en fjern ensom høj'%(__ThisDir__)) - assert(s.get_title() == u'På en fjern ensom høj') - assert(s.get_copyright() == '') - assert(s.get_song_cclino() == '') - assert(s.get_category_array(True) == '') - assert(s.get_author_list(True) == '') - assert(s.get_verse_order() == 'V1 C1 V2 C2 V3 C3 V4 C4') - assert(s.get_number_of_slides() == 8) - -if '__main__' == __name__: - r = Test_OpenSong() - r.test_file3() diff --git a/openlp/plugins/songs/test/test_song_text.py b/openlp/plugins/songs/test/test_song_text.py deleted file mode 100644 index 852626592..000000000 --- a/openlp/plugins/songs/test/test_song_text.py +++ /dev/null @@ -1,60 +0,0 @@ -# -*- coding:iso-8859-1 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 -""" -OpenLP - Open Source Lyrics Projection -Copyright (c) 2008 Raoul Snyman -Portions copyright (c) 2008 Martin Thompson, Tim Bentley, 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 os -import sys - -__ThisDir__ = os.path.dirname(__file__) -if "" == __ThisDir__ : - __ThisDir__ = os.path.abspath(u'.') - -sys.path.append(os.path.abspath(u'%s/../../../..'%__ThisDir__)) - -from openlp.plugins.songs.lib.songxml import * - -class Test_Text(object): - """Test cases for converting from text format to Song""" - - def test_file1(self): - """OpenSong: parse CCLI example""" - global __ThisDir__ - s = Song() - s.from_ccli_text_file(u'%s/data_text/CCLI example.txt'%(__ThisDir__)) - assert(s.get_title() == 'Song Title Here') - assert(s.get_author_list(True) == 'Author, artist name') - assert(s.get_copyright() == '1996 Publisher Info') - assert(s.get_song_cclino() == '1234567') - assert(s.get_number_of_slides() == 4) - - def test_file2(self): - """OpenSong: parse PåEnFjern (danish)""" - global __ThisDir__ - s = Song() - s.from_ccli_text_file(u'%s/data_text/PåEnFjern.txt'%(__ThisDir__)) - assert(s.get_title() == 'På en fjern ensom høj') - assert(s.get_author_list(True) == 'Georg Bennard') - assert(s.get_copyright() == '') - assert(s.get_song_cclino() == '') - assert(s.get_number_of_slides() == 8) - -if '__main__' == __name__: - # for local debugging - r = Test_Text() - r.test_file1() - r.test_file2() diff --git a/openlp/plugins/songs/test/test_song_verse.py b/openlp/plugins/songs/test/test_song_verse.py deleted file mode 100644 index 0eb235076..000000000 --- a/openlp/plugins/songs/test/test_song_verse.py +++ /dev/null @@ -1,151 +0,0 @@ -# -*- coding:iso-8859-1 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 -""" -OpenLP - Open Source Lyrics Projection -Copyright (c) 2008 Raoul Snyman -Portions copyright (c) 2008 Martin Thompson, Tim Bentley, 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 os -import sys - -__ThisDir__ = os.path.dirname(__file__) -if "" == __ThisDir__ : - __ThisDir__ = os.path.abspath(u'.') - -sys.path.append(os.path.abspath(u'%s/../../../..'%__ThisDir__)) - -from openlp.plugins.songs.lib.songxml import * - -class Test_Verse(object): - """Class for testing verses for preview and review""" - - def stdSong(self): - """Definition of a standard song""" - s = Song() - self.title = "A song" - self.author = "John Newton" - self.copyright = "Peter Hamil" - self.ccli = "123456" - s.set_lyrics(["# verse","a single line"]) - s.set_title(self.title) - s.set_copyright(self.copyright) - s.set_author_list(self.author) - s.set_song_cclino(self.ccli) - return s - - def check_allfields(self, r, isblank = 0): - #[theme, title, author, cpright, ccli, lyrics] - if isblank == 1 : - assert(r[1] == '') - else : - assert(r[1] == self.title) - if isblank == 2 : - assert(r[2] == '') - else : - assert(r[2] == self.author) - if isblank == 3 : - assert(r[3] == '') - else : - assert(r[3] == self.copyright) - if isblank == 4 : - assert(r[4] == '') - else : - assert(r[4] == self.ccli) - - - def test_title_show_noshow(self): - """Test the show title flag""" - s = self.stdSong() - r = s.get_render_slide(1) - self.check_allfields(r) - s.set_show_title(False) - r = s.get_render_slide(1) - self.check_allfields(r, 1) - s.set_show_title(True) - r = s.get_render_slide(1) - self.check_allfields(r) - - def test_author_show_noshow(self): - """Test the show author flag""" - s = self.stdSong() - r = s.get_render_slide(1) - self.check_allfields(r) - s.set_show_author_list(False) - r = s.get_render_slide(1) - self.check_allfields(r, 2) - s.set_show_author_list(True) - r = s.get_render_slide(1) - self.check_allfields(r) - - def test_copyright_show_noshow(self): - """Test the show copyright flag""" - s = self.stdSong() - r = s.get_render_slide(1) - self.check_allfields(r) - s.set_show_copyright(False) - r = s.get_render_slide(1) - self.check_allfields(r, 3) - s.set_show_copyright(True) - r = s.get_render_slide(1) - self.check_allfields(r) - - def test_ccli_show_noshow(self): - """Test the show copyright flag""" - s = self.stdSong() - r = s.get_render_slide(1) - self.check_allfields(r) - s.set_show_song_cclino(False) - r = s.get_render_slide(1) - self.check_allfields(r, 4) - s.set_show_song_cclino(True) - r = s.get_render_slide(1) - self.check_allfields(r) - - def test_verse1(self): - """Test an empty verse list""" - s = Song() - s.set_lyrics([]) - assert(s.get_number_of_slides() == 0) - - def test_verse2(self): - """Test a list with an empty string""" - s = Song() - s.set_lyrics([""]) - assert(s.get_number_of_slides() == 0) - - def test_verse3a(self): - """Test a one liner song""" - s = Song() - s.set_lyrics(["Single verse"]) - assert(s.get_number_of_slides() == 1) - - def test_verse3b(self): - """Test a one liner song""" - s = Song() - s.set_lyrics(["", u'Single verse']) - assert(s.get_number_of_slides() == 1) - - def test_verse3c(self): - """Test a one liner song""" - s = Song() - s.set_lyrics(["", u'Single verse', u'', u'']) - assert(s.get_number_of_slides() == 1) - - def test_verse3d(self): - """Test a one liner song""" - s = Song() - s.set_lyrics(["", u'# Verse', u'', u'']) - assert(s.get_number_of_slides() == 1) diff --git a/openlp/plugins/songusage/__init__.py b/openlp/plugins/songusage/__init__.py index bc50edda3..1a348a0df 100644 --- a/openlp/plugins/songusage/__init__.py +++ b/openlp/plugins/songusage/__init__.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -21,4 +21,4 @@ # 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 # -############################################################################### \ No newline at end of file +############################################################################### diff --git a/openlp/plugins/songusage/forms/__init__.py b/openlp/plugins/songusage/forms/__init__.py index 68c125317..162d64a14 100644 --- a/openlp/plugins/songusage/forms/__init__.py +++ b/openlp/plugins/songusage/forms/__init__.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -24,4 +24,4 @@ ############################################################################### from songusagedeleteform import SongUsageDeleteForm -from songusagedetailform import SongUsageDetailForm \ No newline at end of file +from songusagedetailform import SongUsageDetailForm diff --git a/openlp/plugins/songusage/forms/songusagedeletedialog.py b/openlp/plugins/songusage/forms/songusagedeletedialog.py index e9a9a8603..2cb19f4f5 100644 --- a/openlp/plugins/songusage/forms/songusagedeletedialog.py +++ b/openlp/plugins/songusage/forms/songusagedeletedialog.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/plugins/songusage/forms/songusagedeleteform.py b/openlp/plugins/songusage/forms/songusagedeleteform.py index 56eb1954a..207670709 100644 --- a/openlp/plugins/songusage/forms/songusagedeleteform.py +++ b/openlp/plugins/songusage/forms/songusagedeleteform.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -41,8 +41,8 @@ class SongUsageDeleteForm(QtGui.QDialog, Ui_SongUsageDeleteDialog): def accept(self): ret = QtGui.QMessageBox.question(self, - self.trUtf8('Delete Selected Audit Events?'), - self.trUtf8('Are you sure you want to delete selected Audit Data?'), + self.trUtf8('Delete Selected Song Usage Events?'), + self.trUtf8('Are you sure you want to delete selected Song Usage data?'), QtGui.QMessageBox.StandardButtons( QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel), diff --git a/openlp/plugins/songusage/forms/songusagedetaildialog.py b/openlp/plugins/songusage/forms/songusagedetaildialog.py index 411187086..13b4fe18d 100644 --- a/openlp/plugins/songusage/forms/songusagedetaildialog.py +++ b/openlp/plugins/songusage/forms/songusagedetaildialog.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -60,7 +60,8 @@ class Ui_SongUsageDetailDialog(object): self.horizontalLayout.addWidget(self.FileLineEdit) self.SaveFilePushButton = QtGui.QPushButton(self.FileGroupBox) icon = QtGui.QIcon() - icon.addPixmap(QtGui.QPixmap(u':/exports/export_load.png'), QtGui.QIcon.Normal, QtGui.QIcon.Off) + icon.addPixmap(QtGui.QPixmap(u':/general/general_load.png'), + QtGui.QIcon.Normal, QtGui.QIcon.Off) self.SaveFilePushButton.setIcon(icon) self.SaveFilePushButton.setObjectName(u'SaveFilePushButton') self.horizontalLayout.addWidget(self.SaveFilePushButton) diff --git a/openlp/plugins/songusage/forms/songusagedetailform.py b/openlp/plugins/songusage/forms/songusagedetailform.py index be548ac35..4e4f9bb55 100644 --- a/openlp/plugins/songusage/forms/songusagedetailform.py +++ b/openlp/plugins/songusage/forms/songusagedetailform.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -22,6 +22,7 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### + import os from PyQt4 import QtCore, QtGui @@ -81,7 +82,7 @@ class SongUsageDetailForm(QtGui.QDialog, Ui_SongUsageDetailDialog): instance.copyright, instance.ccl_number , instance.authors) file.write(record) except: - log.exception(u'Failed to write out audit records') + log.exception(u'Failed to write out song usage records') finally: if file: file.close() diff --git a/openlp/plugins/songusage/lib/__init__.py b/openlp/plugins/songusage/lib/__init__.py index 9a4d81c56..50bba3ddc 100644 --- a/openlp/plugins/songusage/lib/__init__.py +++ b/openlp/plugins/songusage/lib/__init__.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -23,4 +23,4 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from manager import SongUsageManager \ No newline at end of file +from manager import SongUsageManager diff --git a/openlp/plugins/songusage/lib/classes.py b/openlp/plugins/songusage/lib/classes.py index 63ffd3e80..a780b57ac 100644 --- a/openlp/plugins/songusage/lib/classes.py +++ b/openlp/plugins/songusage/lib/classes.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -43,4 +43,4 @@ class SongUsageItem(BaseModel): """ Audit model """ - pass \ No newline at end of file + pass diff --git a/openlp/plugins/songusage/lib/manager.py b/openlp/plugins/songusage/lib/manager.py index d9f7feb6f..2802570ab 100644 --- a/openlp/plugins/songusage/lib/manager.py +++ b/openlp/plugins/songusage/lib/manager.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlp/plugins/songusage/lib/meta.py b/openlp/plugins/songusage/lib/meta.py index 38b0f7206..affa31969 100644 --- a/openlp/plugins/songusage/lib/meta.py +++ b/openlp/plugins/songusage/lib/meta.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -35,4 +35,4 @@ session = None # Global metadata. If you have multiple databases with overlapping table # names, you'll need a metadata for each database -metadata = MetaData() \ No newline at end of file +metadata = MetaData() diff --git a/openlp/plugins/songusage/lib/models.py b/openlp/plugins/songusage/lib/models.py index b2794b5d5..a053ffc34 100644 --- a/openlp/plugins/songusage/lib/models.py +++ b/openlp/plugins/songusage/lib/models.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -36,4 +36,4 @@ def init_models(url): session = scoped_session(sessionmaker(autoflush=True, autocommit=False, bind=engine)) mapper(SongUsageItem, songusage_table) - return session \ No newline at end of file + return session diff --git a/openlp/plugins/songusage/lib/tables.py b/openlp/plugins/songusage/lib/tables.py index e32b1b245..008c722b1 100644 --- a/openlp/plugins/songusage/lib/tables.py +++ b/openlp/plugins/songusage/lib/tables.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -36,4 +36,4 @@ songusage_table = Table(u'songusage_data', metadata, Column(u'authors', types.Unicode(255), nullable=False), Column(u'copyright', types.Unicode(255)), Column(u'ccl_number', types.Unicode(65)) -) \ No newline at end of file +) diff --git a/openlp/plugins/songusage/songusageplugin.py b/openlp/plugins/songusage/songusageplugin.py index d30bd4bea..0763e0675 100644 --- a/openlp/plugins/songusage/songusageplugin.py +++ b/openlp/plugins/songusage/songusageplugin.py @@ -6,8 +6,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # diff --git a/openlpcnv.pyw b/openlpcnv.pyw index 8c3a8bcf5..5d0ff62d0 100755 --- a/openlpcnv.pyw +++ b/openlpcnv.pyw @@ -7,8 +7,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -70,7 +70,7 @@ class Migration(object): """ #MigrateFiles(self.display).process() MigrateSongs(self.display).process() - #MigrateBibles(self.display).process() + MigrateBibles(self.display).process() def move_log_file(self): """ @@ -101,6 +101,7 @@ class Migration(object): writefile.close() def convert_sqlite2_to_3(self, olddb, newdb): + print u'Converting sqlite2 ' + olddb + ' to sqlite3 ' + newdb if os.name == u'nt': # we can't make this a raw unicode string as the \U within it causes much confusion hKey = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, u'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\SQLite ODBC Driver') @@ -132,19 +133,30 @@ class Migration(object): if __name__ == u'__main__': mig = Migration() - config = PluginConfig(u'Songs') - newpath = config.get_data_path() + songconfig = PluginConfig(u'Songs') + newsongpath = songconfig.get_data_path() + bibleconfig = PluginConfig(u'Bibles') + newbiblepath = bibleconfig.get_data_path() if os.name == u'nt': - if not os.path.isdir(newpath): - os.makedirs(newpath) + if not os.path.isdir(newsongpath): + os.makedirs(newsongpath) + if not os.path.isdir(newbiblepath): + os.makedirs(newbiblepath) ALL_USERS_APPLICATION_DATA = 35 shell = Dispatch(u'Shell.Application') folder = shell.Namespace(ALL_USERS_APPLICATION_DATA) folderitem = folder.Self - olddb = os.path.join(folderitem.path, u'openlp.org', u'Data', u'songs.olp') + oldsongdb = os.path.join(folderitem.path, u'openlp.org', u'Data', u'songs.olp') + oldbiblepath = os.path.join(folderitem.path, u'openlp.org', u'Data', u'Bibles') else: - olddb = os.path.join(newpath, u'songs.olp') - newdb = os.path.join(newpath, u'songs.sqlite') - mig.convert_sqlite2_to_3(olddb, newdb) + oldsongdb = os.path.join(newsongpath, u'songs.olp') + newsongdb = os.path.join(newsongpath, u'songs.sqlite') + mig.convert_sqlite2_to_3(oldsongdb, newsongdb) + files = os.listdir(oldbiblepath) + for file in files: + f = os.path.splitext(os.path.basename(file))[0] + if f != 'kjv': #kjv bible has an autoincrement key not supported in sqlite3 + mig.convert_sqlite2_to_3(os.path.join(oldbiblepath, file), + os.path.join(newbiblepath, f + u'.sqlite')) mig.process() #mig.move_log_file() diff --git a/resources/forms/alertdialog.ui b/resources/forms/alertdialog.ui index da56f3847..fd4cee5fc 100644 --- a/resources/forms/alertdialog.ui +++ b/resources/forms/alertdialog.ui @@ -1,13 +1,13 @@ - AlertForm - + AlertDialog + 0 0 - 430 - 320 + 567 + 440 @@ -25,85 +25,212 @@ 8 - - - - 0 - 0 - + + + 8 - - - - - - - - 0 - 0 - - - - Alert Text: - - - - - - - - - - true - - - - - - - - - - - Qt::Horizontal - - - - 181 - 38 - - - - - - - - Display - - - - - - - Cancel - - - - - - - + + 8 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + Alert &text: + + + AlertTextEdit + + + + + + + &Parameter(s): + + + ParameterEdit + + + + + + + + + + + + + + + 8 + + + 0 + + + + + true + + + + + + + 8 + + + + + &New + + + + :/general/general_new.png:/general/general_new.png + + + + + + + false + + + &Save + + + + :/general/general_save.png:/general/general_save.png + + + + + + + &Edit + + + + :/general/general_edit.png:/general/general_edit.png + + + + + + + &Delete + + + + :/general/general_delete.png:/general/general_delete.png + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + 8 + + + + + Qt::Horizontal + + + + 181 + 0 + + + + + + + + Displ&ay + + + + :/general/general_live.png:/general/general_live.png + + + + + + + Display && Cl&ose + + + + :/general/general_live.png:/general/general_live.png + + + + + + + &Close + + + + :/system/system_close.png:/system/system_close.png + + + + + + AlertTextEdit + ParameterEdit + AlertListWidget + NewButton + SaveButton + EditButton + DeleteButton + DisplayButton + DisplayCloseButton + CloseButton + - + - CancelButton + CloseButton clicked() - AlertForm + AlertDialog close() diff --git a/resources/forms/alerteditdialog.ui b/resources/forms/alerteditdialog.ui deleted file mode 100644 index 352e3d7b1..000000000 --- a/resources/forms/alerteditdialog.ui +++ /dev/null @@ -1,101 +0,0 @@ - - - AlertEditDialog - - - - 0 - 0 - 400 - 300 - - - - Maintain Alerts - - - - - 220 - 270 - 173 - 27 - - - - QDialogButtonBox::Cancel - - - - - - 20 - 10 - 361 - 251 - - - - - - - - - - - - - - - - true - - - - - - - - - Save - - - - - - - Clear - - - - - - - Add - - - - - - - Edit - - - - - - - Delete - - - - - - - - - - - - - diff --git a/resources/forms/editcustomdialog.ui b/resources/forms/editcustomdialog.ui index 98bc1abb0..44ce46ca7 100644 --- a/resources/forms/editcustomdialog.ui +++ b/resources/forms/editcustomdialog.ui @@ -46,7 +46,7 @@ - + @@ -73,7 +73,7 @@ - + @@ -106,7 +106,7 @@ - + Add New @@ -136,7 +136,7 @@ - + Save @@ -163,6 +163,16 @@ + + + + + + + Split Slide + + + @@ -216,8 +226,11 @@ + + + - QDialogButtonBox::Cancel|QDialogButtonBox::Ok + QDialogButtonBox::Cancel|QDialogButtonBox::Save @@ -236,12 +249,44 @@ UpButton DownButton ThemeComboBox - buttonBox - + + + buttonBox + accepted() + customEditDialog + accept() + + + 294 + 524 + + + 294 + 270 + + + + + buttonBox + rejected() + customEditDialog + close() + + + 294 + 524 + + + 294 + 270 + + + + accept() rejected() diff --git a/resources/forms/serviceitemeditdialog.ui b/resources/forms/serviceitemeditdialog.ui new file mode 100644 index 000000000..24c86b966 --- /dev/null +++ b/resources/forms/serviceitemeditdialog.ui @@ -0,0 +1,87 @@ + + + ServiceItemEditDialog + + + + 0 + 0 + 386 + 272 + + + + Service Item Maintenance + + + + + 20 + 20 + 351 + 241 + + + + + + + + + true + + + + + + + + + Up + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Delete + + + + + + + Down + + + + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Save + + + + + + + + + diff --git a/resources/forms/serviceitemdialog.ui b/resources/forms/servicenotedialog.ui similarity index 100% rename from resources/forms/serviceitemdialog.ui rename to resources/forms/servicenotedialog.ui diff --git a/resources/i18n/openlp_en.ts b/resources/i18n/openlp_en.ts index 6f9d4a26a..1660428e2 100644 --- a/resources/i18n/openlp_en.ts +++ b/resources/i18n/openlp_en.ts @@ -4,7 +4,7 @@ BibleMediaItem - + Quick @@ -34,10 +34,10 @@ - ServiceManager + Ui_EditSongDialog - - Save Service + + &Remove @@ -74,10 +74,10 @@ - ImportWizardForm + SongMaintenanceForm - - Bible Exists + + Are you sure you want to delete the selected book? @@ -92,7 +92,7 @@ BibleMediaItem - + Bible @@ -100,7 +100,7 @@ ServiceManager - + Save Changes to Service? @@ -137,22 +137,6 @@ - - Ui_SongUsageDeleteDialog - - - Audit Delete - - - - - BibleMediaItem - - - Clear - - - Ui_BibleImportWizard @@ -169,6 +153,14 @@ + + SongMaintenanceForm + + + Couldn't save your author. + + + Ui_ServiceNoteEdit @@ -178,15 +170,12 @@ - SongMaintenanceForm + Ui_customEditDialog - - Couldn't save your author! + + Add new slide at bottom - - - Ui_customEditDialog Clear @@ -201,6 +190,14 @@ + + PresentationPlugin + + + <b>Presentation Plugin</b> <br> Delivers the ability to show presentations using a number of different programs. The choice of available presentation programs is available to the user in a drop down box. + + + SongUsagePlugin @@ -212,7 +209,7 @@ MainWindow - + The Main Display has been blanked out @@ -233,6 +230,14 @@ + + SongMaintenanceForm + + + This author can't be deleted, they are currently assigned to at least one song. + + + Ui_customEditDialog @@ -242,10 +247,18 @@ - SongMaintenanceForm + Ui_EditVerseDialog - - This author can't be deleted, they are currently assigned to at least one song! + + Verse + + + + + Ui_OpenSongImportDialog + + + OpenSong Folder: @@ -260,7 +273,7 @@ Ui_MainWindow - + Open an existing service @@ -268,13 +281,16 @@ SlideController - + Move to previous + + + SongsPlugin - - Edit and re-preview Song + + &Song @@ -287,12 +303,15 @@ - AlertsTab + ImportWizardForm - - pt + + You need to specify a file with books of the Bible to use in the import. + + + AlertsTab Edit History: @@ -300,18 +319,10 @@ - SlideController + Ui_MainWindow - - Delay between slides in seconds - - - - - SongMaintenanceForm - - - Couldn't add your book! + + &File @@ -333,6 +344,11 @@ SongMaintenanceForm + + + Couldn't add your book. + + Error @@ -347,14 +363,6 @@ - - ImportWizardForm - - - You need to specify a file with books of the Bible to use in the import! - - - ThemeManager @@ -379,14 +387,6 @@ - - SongUsageDeleteForm - - - Delete Selected Audit Events? - - - Ui_OpenSongExportDialog @@ -396,17 +396,17 @@ - BibleMediaItem + Ui_AmendThemeDialog - - Search + + Bottom Ui_MainWindow - + List the Plugins @@ -419,6 +419,14 @@ + + SongUsageDeleteForm + + + Delete Selected Song Usage Events? + + + SongUsagePlugin @@ -462,7 +470,7 @@ ServiceManager - + Open Service @@ -486,7 +494,7 @@ EditSongForm - + You need to enter a song title. @@ -499,19 +507,27 @@ + + Ui_SongUsageDeleteDialog + + + Song Usage Delete + + + ImportWizardForm - + Invalid Bible Location - ThemesTab + BibleMediaItem - - Global level + + Book: @@ -526,7 +542,7 @@ Ui_MainWindow - + &Service Manager @@ -547,14 +563,6 @@ - - Ui_BibleImportWizard - - - Books Location: - - - ThemeManager @@ -587,6 +595,14 @@ + + ThemesTab + + + Use the global theme, overriding any themes associated with either the service or the songs. + + + Ui_customEditDialog @@ -598,7 +614,7 @@ ImportWizardForm - + You need to set a copyright for your Bible! Bibles in the Public Domain need to be marked as such. @@ -627,14 +643,6 @@ - - BibleMediaItem - - - To: - - - Ui_AmendThemeDialog @@ -646,16 +654,16 @@ BibleMediaItem - + Text Search - Ui_OpenLPExportDialog + Ui_BibleImportWizard - - openlp.org Song Exporter + + CSV @@ -686,16 +694,16 @@ Ui_MainWindow - + Open Service - SongMediaItem + BibleMediaItem - - Titles + + Find: @@ -710,7 +718,7 @@ BibleMediaItem - + Search Type: @@ -718,23 +726,12 @@ Ui_MainWindow - + Media Manager - - - ImageMediaItem - - Images (*.jpg *jpeg *.gif *.png *.bmp);; All files (*) - - - - - Ui_MainWindow - - + Alt+F4 @@ -754,48 +751,51 @@ CCLI Details + + + BibleMediaItem - - SongSelect Password: + + Bible not fully loaded Ui_MainWindow - + Toggle the visibility of the Preview Panel - SongMaintenanceForm + ImportWizardForm - - Are you sure you want to delete the selected book? + + Bible Exists Ui_MainWindow - + &User Guide - SongUsageDeleteForm + AlertsTab - - Are you sure you want to delete selected Audit Data? + + pt Ui_MainWindow - + Set the interface language to English @@ -811,19 +811,11 @@ ImportWizardForm - + Empty Copyright - - CustomPlugin - - - <b>Custom Plugin</b><br>This plugin allows slides to be displayed on the screen in the same way songs are. This plugin provides greater freedom over the songs plugin.<br> - - - AuthorsForm @@ -883,7 +875,7 @@ PresentationMediaItem - + Presentation @@ -915,7 +907,7 @@ MainWindow - + OpenLP version %s has been updated to version %s You can obtain the latest version from http://openlp.org @@ -933,20 +925,28 @@ You can obtain the latest version from http://openlp.org SlideController - + Go to Verse + + SongMaintenanceForm + + + Couldn't add your topic. + + + Ui_MainWindow - + &Import - + Quit OpenLP @@ -970,7 +970,7 @@ You can obtain the latest version from http://openlp.org ImportWizardForm - + Empty Version Name @@ -978,7 +978,7 @@ You can obtain the latest version from http://openlp.org Ui_MainWindow - + &Preview Panel @@ -986,19 +986,11 @@ You can obtain the latest version from http://openlp.org SlideController - + Start continuous loop - - Ui_AboutDialog - - - License - - - GeneralTab @@ -1018,7 +1010,7 @@ You can obtain the latest version from http://openlp.org Ui_MainWindow - + &New @@ -1031,19 +1023,27 @@ You can obtain the latest version from http://openlp.org + + Ui_EditSongDialog + + + R&emove + + + SlideController - + Live - ImportWizardForm + Ui_AmendThemeDialog - - You need to specify a file of Bible verses to import! + + Font Main @@ -1056,10 +1056,10 @@ You can obtain the latest version from http://openlp.org - Ui_EditVerseDialog + ThemeManager - - Number + + File is not a valid theme. @@ -1088,10 +1088,10 @@ You can obtain the latest version from http://openlp.org - Ui_MainWindow + Ui_AmendThemeDialog - - Ctrl+N + + Other Options @@ -1103,23 +1103,15 @@ You can obtain the latest version from http://openlp.org - - Ui_SongUsageDetailDialog - - - ASelect Date Range - - - Ui_MainWindow - + Default Theme: - + Toggle Preview Panel @@ -1156,6 +1148,22 @@ You can obtain the latest version from http://openlp.org + + Ui_MainWindow + + + &Settings + + + + + EditSongForm + + + Invalid verse entry - values must be Numeric, I,B,C,T,P,E,O + + + Ui_AmendThemeDialog @@ -1213,10 +1221,10 @@ You can obtain the latest version from http://openlp.org - Ui_customEditDialog + Ui_BibleImportWizard - - Save + + Verse Location: @@ -1247,7 +1255,7 @@ You can obtain the latest version from http://openlp.org ImportWizardForm - + Open Books CSV file @@ -1271,7 +1279,7 @@ You can obtain the latest version from http://openlp.org BibleMediaItem - + No matching book could be found in this Bible. @@ -1283,16 +1291,27 @@ You can obtain the latest version from http://openlp.org Server: + + + Ui_EditVerseDialog - - Download Options + + Ending + + + + + CustomTab + + + Display Footer: ImportWizardForm - + Invalid OpenSong Bible @@ -1321,26 +1340,34 @@ You can obtain the latest version from http://openlp.org + + AlertEditForm + + + Please save or clear selected item + + + Ui_MainWindow - + &Live - SongMaintenanceForm + Ui_AmendThemeDialog - - Delete Topic + + <Color2> Ui_MainWindow - + English @@ -1361,6 +1388,14 @@ You can obtain the latest version from http://openlp.org + + Ui_OpenLPExportDialog + + + Select openlp.org export filename: + + + Ui_BibleImportWizard @@ -1378,18 +1413,18 @@ You can obtain the latest version from http://openlp.org - Ui_AmendThemeDialog + Ui_SongUsageDetailDialog - - Opaque + + Song Usage Extraction - SongMaintenanceForm + Ui_AmendThemeDialog - - This book can't be deleted, it is currently assigned to at least one song! + + Opaque @@ -1404,7 +1439,7 @@ You can obtain the latest version from http://openlp.org SlideController - + Start playing media @@ -1417,6 +1452,14 @@ You can obtain the latest version from http://openlp.org + + SongMaintenanceForm + + + This book can't be deleted, it is currently assigned to at least one song. + + + Ui_AboutDialog @@ -1444,7 +1487,7 @@ You can obtain the latest version from http://openlp.org BibleMediaItem - + Dual: @@ -1508,12 +1551,12 @@ You can obtain the latest version from http://openlp.org Ui_MainWindow - + F9 - + F8 @@ -1521,7 +1564,7 @@ You can obtain the latest version from http://openlp.org ServiceManager - + &Change Item Theme @@ -1550,14 +1593,6 @@ You can obtain the latest version from http://openlp.org - - Ui_EditSongDialog - - - &Remove - - - Ui_BibleImportWizard @@ -1566,6 +1601,14 @@ You can obtain the latest version from http://openlp.org + + Ui_EditVerseDialog + + + Number + + + Ui_AmendThemeDialog @@ -1625,7 +1668,7 @@ You can obtain the latest version from http://openlp.org SlideController - + Move to live @@ -1647,17 +1690,25 @@ You can obtain the latest version from http://openlp.org - Ui_EditVerseDialog + ServiceManager - - Verse + + Save Service + + + + + Ui_SongUsageDetailDialog + + + Select Date Range Ui_MainWindow - + Save the current service to disk @@ -1665,16 +1716,13 @@ You can obtain the latest version from http://openlp.org BibleMediaItem - + Chapter: - - - Ui_AmendThemeDialog - - Bottom + + Search @@ -1687,10 +1735,10 @@ You can obtain the latest version from http://openlp.org - ImportWizardForm + Ui_MainWindow - - Open Verses CSV file + + Add &Tool... @@ -1713,7 +1761,7 @@ You can obtain the latest version from http://openlp.org Ui_MainWindow - + &View @@ -1751,10 +1799,10 @@ You can obtain the latest version from http://openlp.org - ServiceManager + SlideController - - &Preview Verse + + Preview @@ -1782,6 +1830,14 @@ You can obtain the latest version from http://openlp.org + + ImportWizardForm + + + You need to specify a file of Bible verses to import. + + + AlertsTab @@ -1801,24 +1857,16 @@ You can obtain the latest version from http://openlp.org EditSongForm - + You need to enter some verses. - BibleMediaItem + Ui_BibleImportWizard - - Bible not fully loaded - - - - - CustomTab - - - Display Footer: + + Download Options @@ -1841,7 +1889,7 @@ You can obtain the latest version from http://openlp.org Ui_MainWindow - + &Export @@ -1897,16 +1945,24 @@ You can obtain the latest version from http://openlp.org EditSongForm - + Invalid verse entry - vX - BibleMediaItem + ServiceManager - - No Book Found + + OpenLP Service Files (*.osz) + + + + + MediaManagerItem + + + Delete the selected item @@ -1929,7 +1985,7 @@ You can obtain the latest version from http://openlp.org BibleMediaItem - + Keep @@ -1953,32 +2009,24 @@ You can obtain the latest version from http://openlp.org Ui_MainWindow - + &Open - PresentationMediaItem + AuthorsForm - - Present using: + + You haven't set a display name for the author, would you like me to combine the first and last names for you? - ServiceManager + AmendThemeForm - - &Live Verse - - - - - Ui_EditVerseDialog - - - Pre-Chorus + + Slide Height is %s rows @@ -2013,6 +2061,14 @@ Testers + + SongMediaItem + + + Titles + + + Ui_OpenLPExportDialog @@ -2022,10 +2078,10 @@ Testers - AuthorsForm + PresentationMediaItem - - You haven't set a display name for the author, would you like me to combine the first and last names for you? + + Present using: @@ -2038,10 +2094,10 @@ Testers - AmendThemeForm + ServiceManager - - Slide Height is %s rows + + &Live Verse @@ -2056,7 +2112,7 @@ Testers Ui_MainWindow - + Toggle Theme Manager @@ -2166,14 +2222,17 @@ Testers - Ui_MainWindow + BiblesTab - - &Settings + + Verse Display + + + Ui_MainWindow - + &Options @@ -2181,7 +2240,7 @@ Testers BibleMediaItem - + Results: @@ -2195,17 +2254,17 @@ Testers - Ui_OpenSongImportDialog + ServiceManager - - OpenSong Folder: + + Move to &top SlideController - + Move to last @@ -2245,7 +2304,7 @@ Testers BibleMediaItem - + Verse Search @@ -2261,7 +2320,7 @@ Testers EditSongForm - + Save && Preview @@ -2339,18 +2398,18 @@ Testers - MediaMediaItem + SongsTab - - Select Media + + Enable search as you type: - PresentationMediaItem + Ui_MainWindow - - Select Presentation(s) + + Ctrl+S @@ -2370,32 +2429,24 @@ Testers - - Ui_MainWindow - - - Save the current service under a new name - - - - - Ctrl+O - - - - - Ui_AmendThemeDialog - - - Other Options - - - SongMaintenanceForm - Couldn't add your author! + Couldn't add your author. + + + + + Ui_MainWindow + + + Ctrl+O + + + + + Ctrl+N @@ -2424,18 +2475,15 @@ Testers - SongsPlugin + SlideController - - &Song + + Edit and re-preview Song - - - Ui_MainWindow - - &File + + Delay between slides in seconds @@ -2461,25 +2509,25 @@ Testers - ThemeManager + ThemesTab - - You are unable to delete the default theme! + + Global level - ThemesTab + ThemeManager - - Use the global theme, overriding any themes associated with either the service or the songs. + + You are unable to delete the default theme. BibleMediaItem - + Version: @@ -2522,14 +2570,6 @@ OpenLP is written and maintained by volunteers. If you would like to see more fr - - ThemeManager - - - File is not a valid theme! - - - Ui_BibleImportWizard @@ -2539,18 +2579,18 @@ OpenLP is written and maintained by volunteers. If you would like to see more fr - ServiceManager + Ui_AboutDialog - - Move down + + License - Ui_EditSongDialog + OpenSongBible - - R&emove + + Importing @@ -2563,10 +2603,10 @@ OpenLP is written and maintained by volunteers. If you would like to see more fr - Ui_BibleImportWizard + Ui_customEditDialog - - Verse Location: + + Save @@ -2581,7 +2621,7 @@ OpenLP is written and maintained by volunteers. If you would like to see more fr BibleMediaItem - + From: @@ -2597,7 +2637,7 @@ OpenLP is written and maintained by volunteers. If you would like to see more fr ServiceManager - + &Notes @@ -2605,7 +2645,7 @@ OpenLP is written and maintained by volunteers. If you would like to see more fr Ui_MainWindow - + E&xit @@ -2621,7 +2661,7 @@ OpenLP is written and maintained by volunteers. If you would like to see more fr MainWindow - + OpenLP Version Updated @@ -2633,11 +2673,6 @@ OpenLP is written and maintained by volunteers. If you would like to see more fr Replace edited slide - - - Add new slide at bottom - - EditCustomForm @@ -2658,11 +2693,19 @@ OpenLP is written and maintained by volunteers. If you would like to see more fr Ui_MainWindow - + &Help + + Ui_EditVerseDialog + + + Bridge + + + Ui_OpenSongExportDialog @@ -2680,15 +2723,10 @@ OpenLP is written and maintained by volunteers. If you would like to see more fr - TestMediaManager + Ui_EditVerseDialog - - Item2 - - - - - Item1 + + Pre-Chorus @@ -2711,11 +2749,19 @@ OpenLP is written and maintained by volunteers. If you would like to see more fr Ui_MainWindow - + Toggle Service Manager + + Ui_EditSongDialog + + + Delete + + + MediaManagerItem @@ -2751,7 +2797,7 @@ OpenLP is written and maintained by volunteers. If you would like to see more fr Ui_MainWindow - + Ctrl+F1 @@ -2760,7 +2806,15 @@ OpenLP is written and maintained by volunteers. If you would like to see more fr SongMaintenanceForm - Couldn't save your topic! + Couldn't save your topic. + + + + + Ui_MainWindow + + + Save the current service under a new name @@ -2796,14 +2850,6 @@ OpenLP is written and maintained by volunteers. If you would like to see more fr - - BiblesTab - - - Bibles - - - SongUsagePlugin @@ -2823,7 +2869,7 @@ OpenLP is written and maintained by volunteers. If you would like to see more fr Ui_MainWindow - + &Web Site @@ -2839,17 +2885,17 @@ OpenLP is written and maintained by volunteers. If you would like to see more fr Ui_MainWindow - + M&ode - + Translate the interface to your language - + Service Manager @@ -2881,7 +2927,7 @@ OpenLP is written and maintained by volunteers. If you would like to see more fr Ui_MainWindow - + &Theme @@ -2897,31 +2943,20 @@ OpenLP is written and maintained by volunteers. If you would like to see more fr Ui_MainWindow - + &Language - - SlideController - - - Verse - - - - - ImportWizardForm - - - You need to specify an OpenSong Bible file to import! - - - ServiceManager - + + Move to end + + + + Your service is unsaved, do you want to save those changes before creating a new one ? @@ -2945,21 +2980,21 @@ OpenLP is written and maintained by volunteers. If you would like to see more fr MainWindow - + Save Changes to Service? - + Your service has changed, do you want to save those changes? - EditSongForm + ServiceManager - - Invalid verse entry - values must be Numeric, I,B,C,T,P,E,O + + &Delete From Service @@ -2974,11 +3009,19 @@ OpenLP is written and maintained by volunteers. If you would like to see more fr Ui_MainWindow - + &About + + ImportWizardForm + + + You need to specify a version name for your Bible. + + + BiblesTab @@ -2987,14 +3030,6 @@ OpenLP is written and maintained by volunteers. If you would like to see more fr - - ImportWizardForm - - - You need to specify a version name for your Bible! - - - Ui_AlertEditDialog @@ -3012,26 +3047,10 @@ OpenLP is written and maintained by volunteers. If you would like to see more fr - RemotesPlugin + ThemesTab - - <b>Remote Plugin</b><br>This plugin provides the ability to send messages to a running version of openlp on a different computer.<br>The Primary use for this would be to send alerts from a creche - - - - - SongMaintenanceForm - - - This topic can't be deleted, it is currently assigned to at least one song! - - - - - BibleMediaItem - - - Find: + + Use the theme from the service, overriding any of the individual songs' themes. If the service doesn't have a theme, then use the global theme. @@ -3059,14 +3078,6 @@ OpenLP is written and maintained by volunteers. If you would like to see more fr - - ImageMediaItem - - - Allow background of live slide to be overridden - - - MediaManagerItem @@ -3083,14 +3094,6 @@ OpenLP is written and maintained by volunteers. If you would like to see more fr - - BibleMediaItem - - - Book: - - - Ui_AmendThemeDialog @@ -3100,10 +3103,10 @@ OpenLP is written and maintained by volunteers. If you would like to see more fr - Ui_OpenLPExportDialog + Ui_OpenLPImportDialog - - Select openlp.org export filename: + + Select openlp.org songfile to import: @@ -3118,8 +3121,8 @@ OpenLP is written and maintained by volunteers. If you would like to see more fr BiblesTab - - Verse Display + + Layout Style: @@ -3134,7 +3137,7 @@ OpenLP is written and maintained by volunteers. If you would like to see more fr SlideController - + Move to next @@ -3142,7 +3145,7 @@ OpenLP is written and maintained by volunteers. If you would like to see more fr Ui_MainWindow - + &Plugin List @@ -3174,21 +3177,32 @@ OpenLP is written and maintained by volunteers. If you would like to see more fr ImportWizardForm - + Open OSIS file + + Ui_AmendThemeDialog + + + Circular + + + + + PresentationMediaItem + + + Automatic + + + SongMaintenanceForm - Couldn't save your book! - - - - - Couldn't add your topic! + Couldn't save your book. @@ -3201,26 +3215,10 @@ OpenLP is written and maintained by volunteers. If you would like to see more fr - Ui_MainWindow + SongMaintenanceForm - - &Add Tool... - - - - - Ui_AmendThemeDialog - - - <Color2> - - - - - ServiceManager - - - Move up + + Delete Topic @@ -3272,14 +3270,6 @@ OpenLP is written and maintained by volunteers. If you would like to see more fr - - ServiceManager - - - Move to bottom - - - Ui_PluginViewDialog @@ -3299,7 +3289,7 @@ OpenLP is written and maintained by volunteers. If you would like to see more fr ImportWizardForm - + This Bible already exists! Please import a different Bible or first delete the existing one. @@ -3307,24 +3297,16 @@ OpenLP is written and maintained by volunteers. If you would like to see more fr Ui_MainWindow - + &Translate - AlertEditForm + BiblesTab - - Please Save or Clear seletced item - - - - - Ui_MainWindow - - - Save Service As + + Bibles @@ -3473,14 +3455,6 @@ Changes don't affect verses already in the service - - Ui_BibleImportWizard - - - Welcome to the Bible Import Wizard - - - Ui_AmendThemeDialog @@ -3516,7 +3490,7 @@ Changes don't affect verses already in the service Ui_MainWindow - + New Service @@ -3524,7 +3498,7 @@ Changes don't affect verses already in the service SlideController - + Move to first @@ -3532,7 +3506,7 @@ Changes don't affect verses already in the service Ui_MainWindow - + &Online Help @@ -3540,7 +3514,7 @@ Changes don't affect verses already in the service SlideController - + Blank Screen @@ -3548,26 +3522,26 @@ Changes don't affect verses already in the service Ui_MainWindow - + Save Service - + Save &As... - + Toggle the visibility of the Media Manager - MediaManagerItem + BibleMediaItem - - Delete the selected item + + No Book Found @@ -3590,7 +3564,7 @@ Changes don't affect verses already in the service BibleMediaItem - + Advanced @@ -3606,38 +3580,38 @@ Changes don't affect verses already in the service Ui_MainWindow - + F11 - + F10 - + F12 - Ui_BibleImportWizard + CustomPlugin - - Select the import format, and where to import from. + + <b>Custom Plugin</b><br>This plugin allows slides to be displayed on the screen in the same way songs are. This plugin provides greater freedom over the songs plugin.<br> Ui_MainWindow - + Alt+F7 - + Add an application to the list of tools @@ -3650,6 +3624,14 @@ Changes don't affect verses already in the service + + ServiceManager + + + Move &down + + + BiblesTab @@ -3669,7 +3651,7 @@ Changes don't affect verses already in the service Ui_MainWindow - + Theme Manager @@ -3709,7 +3691,7 @@ Changes don't affect verses already in the service Ui_MainWindow - + Toggle the visibility of the Theme Manager @@ -3739,10 +3721,10 @@ Changes don't affect verses already in the service - ServiceManager + SlideController - - Move to end + + Verse @@ -3757,7 +3739,7 @@ Changes don't affect verses already in the service Ui_MainWindow - + &Preview Pane @@ -3792,15 +3774,12 @@ Changes don't affect verses already in the service - Ui_BibleImportWizard + Ui_AmendThemeDialog - - Password: + + Preview - - - Ui_AmendThemeDialog Outline Size: @@ -3832,18 +3811,18 @@ Changes don't affect verses already in the service - Ui_MainWindow + Ui_AboutDialog - - &Theme Manager + + Credits - Ui_OpenLPImportDialog + BibleMediaItem - - Select openlp.org songfile to import: + + To: @@ -3855,14 +3834,6 @@ Changes don't affect verses already in the service - - alertsPlugin - - - F7 - - - Ui_OpenLPExportDialog @@ -3887,14 +3858,6 @@ Changes don't affect verses already in the service - - PresentationPlugin - - - <b>Presentation Plugin</b> <br> Delivers the ability to show presentations using a number of different programs. The choice of available presentation programs is available to the user in a drop down box. - - - ImageMediaItem @@ -3904,10 +3867,18 @@ Changes don't affect verses already in the service - SongsTab + BibleMediaItem - - Enable search as you type: + + Clear + + + + + Ui_MainWindow + + + Save Service As @@ -3968,10 +3939,10 @@ Changes don't affect verses already in the service - ThemesTab + RemotesPlugin - - Use the theme from the service, overriding any of the individual songs' themes. If the service doesn't have a theme, then use the global theme. + + <b>Remote Plugin</b><br>This plugin provides the ability to send messages to a running version of openlp on a different computer.<br>The Primary use for this would be to send alerts from a creche @@ -3986,21 +3957,18 @@ Changes don't affect verses already in the service BibleMediaItem - + Verse: - Ui_BibleImportWizard + Ui_OpenLPExportDialog - - CSV + + openlp.org Song Exporter - - - Ui_OpenLPExportDialog Song Export List @@ -4042,7 +4010,7 @@ Changes don't affect verses already in the service Ui_MainWindow - + Toggle the visibility of the Service Manager @@ -4050,11 +4018,27 @@ Changes don't affect verses already in the service PresentationMediaItem - + A presentation with that filename already exists. + + ImageMediaItem + + + Allow the background of live slide to be overridden + + + + + SongUsageDeleteForm + + + Are you sure you want to delete selected Song Usage data? + + + AlertsTab @@ -4066,7 +4050,7 @@ Changes don't affect verses already in the service ImportWizardForm - + Invalid Books File @@ -4103,6 +4087,14 @@ Changes don't affect verses already in the service + + ImportWizardForm + + + Open Verses CSV file + + + Ui_customEditDialog @@ -4114,7 +4106,7 @@ Changes don't affect verses already in the service Ui_MainWindow - + More information about OpenLP @@ -4138,12 +4130,12 @@ Changes don't affect verses already in the service Ui_MainWindow - + &Media Manager - + &Tools @@ -4178,18 +4170,18 @@ Changes don't affect verses already in the service - AlertsTab + SongMaintenanceForm - - s + + This topic can't be deleted, it is currently assigned to at least one song. - ImagePlugin + AlertsTab - - <b>Image Plugin</b><br>Allows images of all types to be displayed. If a number of images are selected together and presented on the live controller it is possible to turn them into a timed loop.<br<br>From the plugin if the <i>Override background</i> is chosen and an image is selected any somgs which are rendered will use the selected image from the background instead of the one provied by the theme.<br> + + s @@ -4226,10 +4218,10 @@ Changes don't affect verses already in the service - Ui_AmendThemeDialog + Ui_BibleImportWizard - - Font Main + + Select the import format, and where to import from. @@ -4252,7 +4244,7 @@ Changes don't affect verses already in the service Ui_MainWindow - + Toggle Media Manager @@ -4282,10 +4274,10 @@ Changes don't affect verses already in the service - ImportWizardForm + ThemeManager - - You need to specify a file to import your Bible from! + + You have not selected a theme. @@ -4298,10 +4290,10 @@ Changes don't affect verses already in the service - ThemeManager + ImportWizardForm - - You have not selected a theme! + + You need to specify a file to import your Bible from. @@ -4324,7 +4316,7 @@ Changes don't affect verses already in the service Ui_MainWindow - + Create a new Service @@ -4338,10 +4330,10 @@ Changes don't affect verses already in the service - SlideController + ServiceManager - - Preview + + &Preview Verse @@ -4352,6 +4344,17 @@ Changes don't affect verses already in the service TextLabel + + + AlertsTab + + + Font Size: + + + + + Ui_PluginViewDialog About: @@ -4408,14 +4411,6 @@ Changes don't affect verses already in the service - - Ui_SongUsageDetailDialog - - - Audit Detail Extraction - - - Ui_OpenLPExportDialog @@ -4424,6 +4419,14 @@ Changes don't affect verses already in the service + + ImageMediaItem + + + Images (*.jpg *.jpeg *.gif *.png *.bmp);; All files (*) + + + EditCustomForm @@ -4459,7 +4462,7 @@ Changes don't affect verses already in the service MainWindow - + OpenLP Main Display Blanked @@ -4473,33 +4476,30 @@ Changes don't affect verses already in the service - OpenSongBible + ServiceManager - - Importing + + Move &up - Ui_EditSongDialog + ImportWizardForm - - Delete - - - - - Ui_MainWindow - - - Ctrl+S + + You need to specify an OpenSong Bible file to import. PresentationMediaItem - + + Select Presentation(s) + + + + File exists @@ -4515,16 +4515,24 @@ Changes don't affect verses already in the service SlideController - + Stop continuous loop - + s + + ImagePlugin + + + <b>Image Plugin</b><br>Allows images of all types to be displayed. If a number of images are selected together and presented on the live controller it is possible to turn them into a timed loop.<br<br>From the plugin if the <i>Override background</i> is chosen and 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.<br> + + + SongMediaItem @@ -4549,18 +4557,10 @@ Changes don't affect verses already in the service - - BiblesTab - - - Layout Style: - - - ImportWizardForm - + Invalid Verse File @@ -4568,7 +4568,7 @@ Changes don't affect verses already in the service EditSongForm - + Error @@ -4614,10 +4614,10 @@ Changes don't affect verses already in the service - Ui_EditVerseDialog + Ui_BibleImportWizard - - Bridge + + Welcome to the Bible Import Wizard @@ -4630,18 +4630,18 @@ Changes don't affect verses already in the service - Ui_AmendThemeDialog + Ui_BibleImportWizard - - Preview + + Password: - Ui_AboutDialog + Ui_MainWindow - - Credits + + &Theme Manager @@ -4670,10 +4670,10 @@ Changes don't affect verses already in the service - Ui_EditVerseDialog + MediaMediaItem - - Ending + + Select Media @@ -4688,7 +4688,7 @@ Changes don't affect verses already in the service ServiceManager - + &Edit Item @@ -4704,12 +4704,12 @@ Changes don't affect verses already in the service Ui_MainWindow - + &Save - + OpenLP 2.0 @@ -4758,6 +4758,11 @@ Changes don't affect verses already in the service Show Outline: + + + Gradient + + SongBookForm @@ -4770,7 +4775,7 @@ Changes don't affect verses already in the service ImportWizardForm - + Open OpenSong Bible @@ -4778,7 +4783,7 @@ Changes don't affect verses already in the service Ui_MainWindow - + Look && &Feel @@ -4808,18 +4813,18 @@ Changes don't affect verses already in the service - Ui_AmendThemeDialog + ServiceManager - - Gradient + + Move to &bottom - AlertsTab + Ui_BibleImportWizard - - Font Size: + + Books Location: @@ -4832,10 +4837,10 @@ Changes don't affect verses already in the service - Ui_AmendThemeDialog + GeneralTab - - Circular + + SongSelect Password: diff --git a/resources/images/general_add.png b/resources/images/general_add.png new file mode 100644 index 000000000..7bb9b1be8 Binary files /dev/null and b/resources/images/general_add.png differ diff --git a/resources/images/general_delete.png b/resources/images/general_delete.png new file mode 100644 index 000000000..ef8e685e2 Binary files /dev/null and b/resources/images/general_delete.png differ diff --git a/resources/images/general_edit.png b/resources/images/general_edit.png new file mode 100644 index 000000000..84e345d22 Binary files /dev/null and b/resources/images/general_edit.png differ diff --git a/resources/images/general_export.png b/resources/images/general_export.png new file mode 100644 index 000000000..d26519b7f Binary files /dev/null and b/resources/images/general_export.png differ diff --git a/resources/images/general_import.png b/resources/images/general_import.png new file mode 100644 index 000000000..0ee789269 Binary files /dev/null and b/resources/images/general_import.png differ diff --git a/resources/images/general_live.png b/resources/images/general_live.png new file mode 100644 index 000000000..cb2be2258 Binary files /dev/null and b/resources/images/general_live.png differ diff --git a/resources/images/general_new.png b/resources/images/general_new.png new file mode 100644 index 000000000..8431237bd Binary files /dev/null and b/resources/images/general_new.png differ diff --git a/resources/images/general_open.png b/resources/images/general_open.png new file mode 100644 index 000000000..eb211e233 Binary files /dev/null and b/resources/images/general_open.png differ diff --git a/resources/images/general_preview.png b/resources/images/general_preview.png new file mode 100644 index 000000000..d196792bb Binary files /dev/null and b/resources/images/general_preview.png differ diff --git a/resources/images/general_save.png b/resources/images/general_save.png new file mode 100644 index 000000000..8072aea32 Binary files /dev/null and b/resources/images/general_save.png differ diff --git a/resources/images/openlp-2.qrc b/resources/images/openlp-2.qrc index 28af4c31a..98de90f09 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 @@ -13,25 +13,36 @@ book_maintenance.png author_maintenance.png topic_maintenance.png - song_delete.png - song_edit.png - song_export.png - song_new.png song_author_edit.png song_topic_edit.png song_book_edit.png - + + general_preview.png + general_live.png + general_add.png + general_delete.png + general_edit.png + general_export.png + general_import.png + general_new.png + general_open.png + general_save.png + + slide_close.png slide_first.png slide_last.png slide_next.png + slide_blank.png + slide_desktop.png + slide_theme.png slide_previous.png media_playback_start.png media_playback_stop.png media_playback_pause.png - + openlp-logo-16x16.png openlp-logo-32x32.png openlp-logo-48x48.png @@ -39,62 +50,37 @@ 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 - - custom_new.png - custom_edit.png - custom_delete.png - - + wizard_importbible.bmp - - presentation_delete.png - presentation_load.png - - - video_delete.png - video_load.png - - - image_delete.png - image_load.png - - - service_edit.png + service_notes.png service_item_notes.png service_bottom.png service_down.png service_top.png service_up.png - service_delete.png - service_new.png - service_open.png - service_save.png - + system_close.png system_about.png system_help_contents.png - system_add.png - system_live.png - system_preview.png system_mediamanager.png system_contribute.png system_servicemanager.png @@ -102,7 +88,7 @@ system_exit.png system_settings.png - + media_custom.png media_presentation.png media_image.png @@ -113,20 +99,18 @@ 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 - theme_export.png - theme_import.png diff --git a/resources/images/slide_blank.png b/resources/images/slide_blank.png new file mode 100644 index 000000000..a878468c6 Binary files /dev/null and b/resources/images/slide_blank.png differ diff --git a/resources/images/slide_desktop.png b/resources/images/slide_desktop.png new file mode 100644 index 000000000..e5655f523 Binary files /dev/null and b/resources/images/slide_desktop.png differ diff --git a/resources/images/slide_theme.png b/resources/images/slide_theme.png new file mode 100644 index 000000000..d196792bb Binary files /dev/null and b/resources/images/slide_theme.png differ diff --git a/resources/images/system_live.png b/resources/images/system_live.png index 17fd3ca9d..cb2be2258 100644 Binary files a/resources/images/system_live.png and b/resources/images/system_live.png differ diff --git a/resources/images/system_preview.png b/resources/images/system_preview.png index a8a4adfc0..d196792bb 100644 Binary files a/resources/images/system_preview.png and b/resources/images/system_preview.png differ diff --git a/resources/innosetup/OpenLP-2.0.iss b/resources/innosetup/OpenLP-2.0.iss index 4b25d6a28..b826fa76f 100644 --- a/resources/innosetup/OpenLP-2.0.iss +++ b/resources/innosetup/OpenLP-2.0.iss @@ -5,7 +5,7 @@ #define MyAppVerName "OpenLP 2.0" #define MyAppPublisher "OpenLP Developers" #define MyAppURL "http://openlp.org/" -#define MyAppExeName "openlp.exe" +#define MyAppExeName "OpenLP.exe" [Setup] ; NOTE: The value of AppId uniquely identifies this application. @@ -20,12 +20,14 @@ AppSupportURL={#MyAppURL} AppUpdatesURL={#MyAppURL} DefaultDirName={pf}\{#MyAppName} DefaultGroupName=OpenLP 2.0 -AllowNoIcons=yes +AllowNoIcons=true LicenseFile=LICENSE.txt -OutputBaseFilename=OpenLP-2.0-setup +OutputBaseFilename=OpenLP-1.9.0-bzr739-setup Compression=lzma SolidCompression=true -SetupIconFile=OpenLP.ico +SetupIconFile=C:\Program Files\Inno Setup 5\Examples\Setup.ico +WizardImageFile=C:\Program Files\Inno Setup 5\WizModernImage-IS.bmp +WizardSmallImageFile=C:\Program Files\Inno Setup 5\WizModernSmallImage-IS.bmp [Languages] Name: english; MessagesFile: compiler:Default.isl @@ -51,14 +53,16 @@ Name: slovenian; MessagesFile: compiler:Languages\Slovenian.isl Name: spanish; MessagesFile: compiler:Languages\Spanish.isl [Tasks] -Name: desktopicon; Description: {cm:CreateDesktopIcon}; GroupDescription: {cm:AdditionalIcons}; Flags: unchecked -Name: quicklaunchicon; Description: {cm:CreateQuickLaunchIcon}; GroupDescription: {cm:AdditionalIcons}; Flags: unchecked +Name: desktopicon; Description: {cm:CreateDesktopIcon}; GroupDescription: {cm:AdditionalIcons} +Name: quicklaunchicon; Description: {cm:CreateQuickLaunchIcon}; GroupDescription: {cm:AdditionalIcons} [Files] -Source: C:\Documents and Settings\raoul\My Documents\My Projects\openlp\pyinstaller\dist\openlp\*; DestDir: {app}; Flags: ignoreversion -Source: C:\Documents and Settings\raoul\My Documents\My Projects\openlp\pyinstaller\dist\openlp\plugins\*; DestDir: {app}\plugins; Flags: ignoreversion recursesubdirs createallsubdirs -Source: C:\Documents and Settings\raoul\My Documents\My Projects\openlp\pyinstaller\dist\openlp\Microsoft.VC90.CRT\*; DestDir: {app}\Microsoft.VC90.CRT; Flags: ignoreversion recursesubdirs createallsubdirs -Source: C:\Documents and Settings\raoul\My Documents\My Projects\openlp\pyinstaller\dist\openlp\qt4_plugins\*; DestDir: {app}\qt4_plugins; Flags: ignoreversion recursesubdirs createallsubdirs +Source: ..\..\dist\OpenLP\*; DestDir: {app}; Flags: ignoreversion +Source: ..\..\dist\OpenLP\plugins\*; DestDir: {app}\plugins; Flags: ignoreversion recursesubdirs createallsubdirs +Source: ..\..\dist\OpenLP\Microsoft.VC90.CRT\*; DestDir: {app}\Microsoft.VC90.CRT; Flags: ignoreversion recursesubdirs createallsubdirs +Source: ..\..\dist\OpenLP\qt4_plugins\*; DestDir: {app}\qt4_plugins; Flags: ignoreversion recursesubdirs createallsubdirs +Source: ..\..\dist\OpenLP\eggs\*; DestDir: {app}\eggs; Flags: ignoreversion recursesubdirs createallsubdirs +Source: openlp.conf; DestDir: {userappdata}\openlp; Flags: ignoreversion onlyifdoesntexist ; NOTE: Don't use "Flags: ignoreversion" on any shared system files [Icons] diff --git a/resources/innosetup/openlp.conf b/resources/innosetup/openlp.conf new file mode 100644 index 000000000..aab3b2260 --- /dev/null +++ b/resources/innosetup/openlp.conf @@ -0,0 +1,26 @@ +[bibles] +status = 1 + +[media] +status = 1 + +[alerts] +status = 1 + +[presentations] +status = 1 + +[custom] +status = 1 + +[remotes] +status = 0 + +[images] +status = 1 + +[songusage] +status = 1 + +[songs] +status = 1 diff --git a/resources/openlp.desktop b/resources/openlp.desktop index 8791c2d8f..0c843bd69 100644 --- a/resources/openlp.desktop +++ b/resources/openlp.desktop @@ -5,6 +5,6 @@ GenericName=Church lyrics projection Exec=openlp Icon=openlp StartupNotify=true -Terminal=False +Terminal=false Type=Application -Categories=AudioVideo +Categories=AudioVideo; diff --git a/resources/pyinstaller/hook-lxml.objectify.py b/resources/pyinstaller/hook-lxml.objectify.py new file mode 100644 index 000000000..071a0dca4 --- /dev/null +++ b/resources/pyinstaller/hook-lxml.objectify.py @@ -0,0 +1 @@ +hiddenimports = ['lxml.etree'] diff --git a/resources/pyinstaller/hook-openlp.plugins.presentations.presentationplugin.py b/resources/pyinstaller/hook-openlp.plugins.presentations.presentationplugin.py index 8b7d6b8a2..74a0869be 100644 --- a/resources/pyinstaller/hook-openlp.plugins.presentations.presentationplugin.py +++ b/resources/pyinstaller/hook-openlp.plugins.presentations.presentationplugin.py @@ -1,3 +1,28 @@ -hiddenimports = ['openlp.plugins.presentations.lib.impresscontroller', +# -*- 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 # +############################################################################### + +hiddenimports = ['openlp.plugins.presentations.lib.impresscontroller', 'openlp.plugins.presentations.lib.powerpointcontroller', - 'openlp.plugins.presentations.lib.pptviewcontroller'] \ No newline at end of file + 'openlp.plugins.presentations.lib.pptviewcontroller'] diff --git a/resources/pyinstaller/hook-openlp.py b/resources/pyinstaller/hook-openlp.py index bd97e4aec..b788749af 100644 --- a/resources/pyinstaller/hook-openlp.py +++ b/resources/pyinstaller/hook-openlp.py @@ -1,9 +1,34 @@ -hiddenimports = ['plugins.songs.songsplugin', - 'plugins.bibles.bibleplugin', - 'plugins.presentations.presentationplugin', - 'plugins.media.mediaplugin', - 'plugins.images.imageplugin', - 'plugins.custom.customplugin', - 'plugins.songusage.songusageplugin', - 'plugins.remotes.remoteplugin', - 'plugins.alerts.alertsplugin'] \ No newline at end of file +# -*- 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 # +############################################################################### + +hiddenimports = ['plugins.songs.songsplugin', + 'plugins.bibles.bibleplugin', + 'plugins.presentations.presentationplugin', + 'plugins.media.mediaplugin', + 'plugins.images.imageplugin', + 'plugins.custom.customplugin', + 'plugins.songusage.songusageplugin', + 'plugins.remotes.remoteplugin', + 'plugins.alerts.alertsplugin'] diff --git a/resources/songs/songs.sqlite b/resources/songs/songs.sqlite index 20af728aa..1cafe2d59 100644 Binary files a/resources/songs/songs.sqlite and b/resources/songs/songs.sqlite differ diff --git a/scripts/bible-1to2-converter.py b/scripts/bible-1to2-converter.py index b1e9b6897..6fe1f1df4 100755 --- a/scripts/bible-1to2-converter.py +++ b/scripts/bible-1to2-converter.py @@ -7,8 +7,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -206,7 +206,6 @@ def import_bible(): rows = old_cursor.fetchall() if debug or verbose: print 'done.' - song_map = {} for row in rows: book_id = int(row[1]) chapter = int(row[2]) diff --git a/scripts/get-strings.py b/scripts/get-strings.py index ed3cdcb41..5fa42a1fc 100755 --- a/scripts/get-strings.py +++ b/scripts/get-strings.py @@ -6,8 +6,9 @@ # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Martin Thompson, Tim Bentley, Carsten # -# Tinggaard, Jon Tibble, Jonathan Corwin, Maikel Stuivenberg, Scott Guerrieri # +# 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 # @@ -99,6 +100,8 @@ def main(): start_dir = os.path.abspath(u'..') for root, dirs, files in os.walk(start_dir): for file in files: + if file.startswith(u'hook-') or file.startswith(u'test_'): + continue if file.endswith(u'.py'): print u'Parsing "%s"' % file parse_file(start_dir, os.path.join(root, file), strings) diff --git a/scripts/openlp-1to2-converter.py b/scripts/openlp-1to2-converter.py index ba6a7d7d1..8645fc2a4 100755 --- a/scripts/openlp-1to2-converter.py +++ b/scripts/openlp-1to2-converter.py @@ -7,8 +7,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -58,6 +58,7 @@ create_statements = [ id INTEGER NOT NULL, song_book_id INTEGER, title VARCHAR(255) NOT NULL, + alternate_title VARCHAR(255), lyrics TEXT NOT NULL, verse_order VARCHAR(128), copyright VARCHAR(255), @@ -183,16 +184,18 @@ def import_songs(): xml_verse_template = u'' for row in rows: clean_title = unicode(row[1], u'cp1252') - clean_lyrics = unicode(row[2], u'cp1252') + clean_lyrics = unicode(row[2], u'cp1252').replace(u'\r\n', u'\n') clean_copyright = unicode(row[3], u'cp1252') verse_order = u'' text_lyrics = clean_lyrics.split(u'\n\n') xml_verse = u'' + verses = [] for line, verse in enumerate(text_lyrics): if not verse: continue xml_verse += (xml_verse_template % (line + 1, verse)) - verse_order += '%d ' % (line + 1) + verses.append(u'V%d' % (line + 1)) + verse_order = u' '.join(verses) xml_lyrics = xml_lyrics_template % xml_verse search_title = prepare_string(clean_title) search_lyrics = prepare_string(clean_lyrics) @@ -316,4 +319,4 @@ if __name__ == u'__main__': os.unlink(new_db) verbose = options.verbose debug = options.debug - main(old_db, new_db) \ No newline at end of file + main(old_db, new_db) diff --git a/openlp/plugins/remotes/remoteclient.py b/scripts/openlp-remoteclient.py similarity index 93% rename from openlp/plugins/remotes/remoteclient.py rename to scripts/openlp-remoteclient.py index 857a7fc7e..de3099920 100755 --- a/openlp/plugins/remotes/remoteclient.py +++ b/scripts/openlp-remoteclient.py @@ -7,8 +7,8 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2010 Raoul Snyman # # Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard # +# 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 # @@ -38,7 +38,7 @@ def sendData(options, message): print u'Errow thrown ', sys.exc_info()[1] def format_message(options): - return u'%s:%s' % (options.event, options.message) + return u'%s:%s' % (u'alert', options.message) def main(): usage = "usage: %prog [options] arg1 arg2" diff --git a/setup.py b/setup.py index d6f4b7503..f2e6911fa 100755 --- a/setup.py +++ b/setup.py @@ -1,4 +1,28 @@ #!/usr/bin/env python +# -*- 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 setuptools import setup, find_packages @@ -44,7 +68,8 @@ OpenLP (previously openlp.org) is free church presentation software, or lyrics p url='http://openlp.org/', license='GNU General Public License', packages=find_packages(exclude=['ez_setup', 'examples', 'tests']), - scripts=['openlp.pyw', 'scripts/openlp-1to2-converter.py', 'scripts/bible-1to2-converter.py'], + scripts=['openlp.pyw', 'scripts/openlp-1to2-converter.py', + 'scripts/bible-1to2-converter.py','scripts/openlp-remoteclient.py'], include_package_data=True, zip_safe=False, install_requires=[