This commit is contained in:
Tim Bentley 2009-09-20 07:11:26 +01:00
commit c191a7b232
5 changed files with 138 additions and 109 deletions

View File

@ -174,12 +174,12 @@ class ServiceItem(object):
self.service_item_path = path
self.service_frames.append({u'title': frame_title, u'command': None})
def get_oos_repr(self):
def get_service_repr(self):
"""
This method returns some text which can be saved into the OOS
This method returns some text which can be saved into the service
file to represent this item.
"""
oos_header = {
service_header = {
u'name': self.name.lower(),
u'plugin': self.shortname,
u'theme':self.theme,
@ -189,19 +189,19 @@ class ServiceItem(object):
u'type':self.service_item_type,
u'audit':self.audit
}
oos_data = []
service_data = []
if self.service_item_type == ServiceType.Text:
for slide in self.service_frames:
oos_data.append(slide)
service_data.append(slide)
elif self.service_item_type == ServiceType.Image:
for slide in self.service_frames:
oos_data.append(slide[u'title'])
service_data.append(slide[u'title'])
elif self.service_item_type == ServiceType.Command:
for slide in self.service_frames:
oos_data.append(slide[u'title'])
return {u'header': oos_header, u'data': oos_data}
service_data.append(slide[u'title'])
return {u'header': service_header, u'data': service_data}
def set_from_oos(self, serviceitem, path=None):
def set_from_service(self, serviceitem, path=None):
"""
This method takes a service item from a saved service file (passed
from the ServiceManager) and extracts the data actually required.

View File

@ -453,7 +453,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
QtGui.QMainWindow.__init__(self)
self.closeEvent = self.onCloseEvent
self.screenList = screens
self.oosNotSaved = False
self.serviceNotSaved = False
self.settingsmanager = SettingsManager(screens)
self.mainDisplay = MainDisplay(self, screens)
self.generalConfig = PluginConfig(u'General')
@ -535,8 +535,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
self.plugin_helpers[u'service'] = self.ServiceManagerContents
self.plugin_helpers[u'settings'] = self.settingsForm
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
# hook methods have to happen after find_plugins. Find plugins needs
# the controllers hence the hooks have moved from setupUI() to here
# Find and insert settings tabs
log.info(u'hook settings')
self.plugin_manager.hook_settings_tabs(self.settingsForm)
@ -617,10 +617,10 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
"""
Hook to close the main window and display windows on exit
"""
if self.oosNotSaved == True:
if self.serviceNotSaved == True:
ret = QtGui.QMessageBox.question(None,
translate(u'mainWindow', u'Save Changes to Service?'),
translate(u'mainWindow', u'Your service has been changed, do you want to save those changes?'),
translate(u'mainWindow', u'Your service has changed, do you want to save those changes?'),
QtGui.QMessageBox.StandardButtons(
QtGui.QMessageBox.Cancel |
QtGui.QMessageBox.Discard |
@ -629,16 +629,19 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
if ret == QtGui.QMessageBox.Save:
self.ServiceManagerContents.onSaveService()
self.mainDisplay.close()
self.ServiceManagerContents.cleanUp()
self.cleanUp()
event.accept()
elif ret == QtGui.QMessageBox.Discard:
self.mainDisplay.close()
self.ServiceManagerContents.cleanUp()
self.cleanUp()
event.accept()
else:
event.ignore()
else:
self.mainDisplay.close()
self.ServiceManagerContents.cleanUp()
self.cleanUp()
event.accept()
@ -647,21 +650,25 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
log.info(u'cleanup plugins')
self.plugin_manager.finalise_plugins()
def OosChanged(self, reset=False, oosName=None):
def serviceChanged(self, reset=False, serviceName=None):
"""
Hook to change the title if the OOS has been changed
reset - tells if the OOS has been cleared or saved
oosName - is the name of the OOS (if it has one)
Hook to change the main window title when the service changes
``reset``
Shows if the service has been cleared or saved
``serviceName``
The name of the service (if it has one)
"""
if not oosName:
if not serviceName:
service_name = u'(unsaved service)'
else:
service_name = oosName
service_name = serviceName
if reset == True:
self.oosNotSaved = False
self.serviceNotSaved = False
title = u'%s - %s' % (self.mainTitle, service_name)
else:
self.oosNotSaved = True
self.serviceNotSaved = True
title = u'%s - %s*' % (self.mainTitle, service_name)
self.setWindowTitle(title)

View File

@ -24,6 +24,7 @@
import os
import sys
import string
import logging
import cPickle
import zipfile
@ -83,10 +84,9 @@ class Iter(QtGui.QTreeWidgetItemIterator):
class ServiceManager(QtGui.QWidget):
"""
Manages the orders of service. Currently this involves taking
text strings from plugins and adding them to an OOS file. In
future, it will also handle zipping up all the resources used into
one lump.
Manages the services. This involves taking text strings from plugins and
adding them to the service. This service can then be zipped up with all
the resources used into one OSZ file for use on any OpenLP v2 installation.
Also handles the UI tasks of moving things up and down etc.
"""
global log
@ -273,7 +273,7 @@ class ServiceManager(QtGui.QWidget):
self.serviceItems.remove(self.serviceItems[item])
self.serviceItems.insert(0, temp)
self.repaintServiceList(0, count)
self.parent.OosChanged(False, self.serviceName)
self.parent.serviceChanged(False, self.serviceName)
def onServiceUp(self):
"""
@ -286,7 +286,7 @@ class ServiceManager(QtGui.QWidget):
self.serviceItems.remove(self.serviceItems[item])
self.serviceItems.insert(item - 1, temp)
self.repaintServiceList(item - 1, count)
self.parent.OosChanged(False, self.serviceName)
self.parent.serviceChanged(False, self.serviceName)
def onServiceDown(self):
"""
@ -299,7 +299,7 @@ class ServiceManager(QtGui.QWidget):
self.serviceItems.remove(self.serviceItems[item])
self.serviceItems.insert(item + 1, temp)
self.repaintServiceList(item + 1, count)
self.parent.OosChanged(False, self.serviceName)
self.parent.serviceChanged(False, self.serviceName)
def onServiceEnd(self):
"""
@ -311,7 +311,7 @@ class ServiceManager(QtGui.QWidget):
self.serviceItems.remove(self.serviceItems[item])
self.serviceItems.insert(len(self.serviceItems), temp)
self.repaintServiceList(len(self.serviceItems) - 1, count)
self.parent.OosChanged(False, self.serviceName)
self.parent.serviceChanged(False, self.serviceName)
def onNewService(self):
"""
@ -321,7 +321,7 @@ class ServiceManager(QtGui.QWidget):
self.serviceItems = []
self.serviceName = u''
self.isNew = True
self.parent.OosChanged(True, self.serviceName)
self.parent.serviceChanged(True, self.serviceName)
def onDeleteFromService(self):
"""
@ -331,9 +331,9 @@ class ServiceManager(QtGui.QWidget):
if item is not -1:
self.serviceItems.remove(self.serviceItems[item])
self.repaintServiceList(0, 0)
self.parent.OosChanged(False, self.serviceName)
self.parent.serviceChanged(False, self.serviceName)
def repaintServiceList(self, serviceItem, serviceItemCount):
def repaintServiceList(self, serviceItem, serviceItemCount):
"""
Clear the existing service list and prepaint all the items
Used when moving items as the move takes place in supporting array,
@ -365,28 +365,29 @@ class ServiceManager(QtGui.QWidget):
def onSaveService(self, quick=False):
"""
Save the current service in a zip file
Save the current service in a zip (OSZ) file
This file contains
* An ood which is a pickle of the service items
* An osd which is a pickle of the service items
* All image, presentation and video files needed to run the service.
"""
if not quick or self.isNew:
filename = QtGui.QFileDialog.getSaveFileName(self,
u'Save Order of Service',self.config.get_last_dir() )
u'Save Service', self.config.get_last_dir())
else:
filename = self.config.get_last_dir()
if filename != u'':
splittedFile = filename.split(u'.')
if splittedFile[-1] != u'oos':
filename = filename + u'.oos'
if splittedFile[-1] != u'osz':
filename = filename + u'.osz'
filename = unicode(filename)
self.isNew = False
self.config.set_last_dir(filename)
service = []
servicefile= filename + u'.ood'
servicefile = filename + u'.osd'
zip = zipfile.ZipFile(unicode(filename), 'w')
for item in self.serviceItems:
service.append({u'serviceitem':item[u'data'].get_oos_repr()})
service.append(
{u'serviceitem':item[u'data'].get_service_repr()})
if item[u'data'].service_item_type == ServiceType.Image or \
item[u'data'].service_item_type == ServiceType.Command:
for frame in item[u'data'].frames:
@ -404,20 +405,19 @@ class ServiceManager(QtGui.QWidget):
pass #if not present do not worry
name = filename.split(os.path.sep)
self.serviceName = name[-1]
self.parent.OosChanged(True, self.serviceName)
self.parent.serviceChanged(True, self.serviceName)
def onQuickSaveService(self):
self.onSaveService(True)
def onLoadService(self):
"""
Load an existing service from disk and rebuilds the serviceitems
All files retrieved from the zip file are placed in a temporary
directory and will only be used for this service.
Load an existing service from disk and rebuild the serviceitems. All
files retrieved from the zip file are placed in a temporary directory
and will only be used for this service.
"""
filename = QtGui.QFileDialog.getOpenFileName(self,
u'Open Order of Service',self.config.get_last_dir(),
u'Services (*.oos)')
filename = QtGui.QFileDialog.getOpenFileName(self, u'Open Service',
self.config.get_last_dir(), u'Services (*.osz)')
filename = unicode(filename)
name = filename.split(os.path.sep)
if filename != u'':
@ -426,16 +426,19 @@ class ServiceManager(QtGui.QWidget):
zip = zipfile.ZipFile(unicode(filename))
filexml = None
themename = None
for file in zip.namelist():
names = file.split(os.path.sep)
if os.name == u'nt':
winfile = string.replace(file, '/', os.path.sep)
names = winfile.split(os.path.sep)
else:
names = file.split(os.path.sep)
file_to = os.path.join(self.servicePath,
names[len(names) - 1])
file_data = zip.read(file)
f = open(file_to, u'w')
f.write(file_data)
f = open(file_to, u'wb')
f.write(zip.read(file))
f.flush()
f.close()
if file_to.endswith(u'ood'):
if file_to.endswith(u'osd'):
p_file = file_to
f = open(p_file, u'r')
items = cPickle.load(f)
@ -444,19 +447,30 @@ class ServiceManager(QtGui.QWidget):
for item in items:
serviceitem = ServiceItem()
serviceitem.RenderManager = self.parent.RenderManager
serviceitem.set_from_oos(item, self.servicePath )
serviceitem.set_from_service(item, self.servicePath )
self.addServiceItem(serviceitem)
try:
os.remove(p_file)
if os.path.isfile(p_file):
os.remove(p_file)
except:
#if not present do not worry
pass
log.exception(u'Failed to remove osd file')
except:
log.exception(u'Problem loading a service file')
pass
self.isNew = False
self.serviceName = name[len(name) - 1]
self.parent.OosChanged(True, self.serviceName)
self.parent.serviceChanged(True, self.serviceName)
def cleanUp(self):
"""
Empties the servicePath of temporary files
"""
for file in os.listdir(self.servicePath):
file_path = os.path.join(self.servicePath, file)
try:
if os.path.isfile(file_path):
os.remove(file_path)
except:
log.exception(u'Failed to clean up servicePath')
def onThemeComboBoxSelected(self, currentIndex):
"""
@ -499,7 +513,7 @@ class ServiceManager(QtGui.QWidget):
treewidgetitem1.setData(0, QtCore.Qt.UserRole,
QtCore.QVariant(count))
count = count + 1
self.parent.OosChanged(False, self.serviceName)
self.parent.serviceChanged(False, self.serviceName)
def makePreview(self):
"""

View File

@ -19,15 +19,17 @@ Place, Suite 330, Boston, MA 02111-1307 USA
import time
import sys
import os, os.path
import logging
from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import *
from PyQt4.QtGui import *
mypath=os.path.split(os.path.abspath(__file__))[0]
sys.path.insert(0,(os.path.join(mypath, '..','..', '..','..')))
mypath = os.path.split(os.path.abspath(__file__))[0]
sys.path.insert(0, (os.path.join(mypath, '..', '..', '..', '..')))
from openlp.core.ui import ServiceManager
from openlp.plugins.images.lib import ImageServiceItem
import logging
logging.basicConfig(filename='test_service_manager.log', level=logging.INFO,
filemode='w')
@ -36,69 +38,72 @@ logging.basicConfig(filename='test_service_manager.log', level=logging.INFO,
# return sys._getframe(depth).f_code.co_name
global app
global log
log=logging.getLogger(u'TestServiceManager')
log = logging.getLogger(u'TestServiceManager')
class TestServiceManager_base:
def __init__(self):
pass
def setup_class(self):
log.info( "class setup"+unicode(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)
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
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))
i = QModelIndex(self.s.service_data.index(0,0))
# make a selection of it
self.sm=QItemSelectionModel(self.s.service_data)
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()))
log.info(u'Selected indexes = ' + unicode(
self.s.TreeView.selectedIndexes()))
def test_easy(self):
log.info(u'test_easy')
item=ImageServiceItem(None)
item = ImageServiceItem(None)
item.add(u'test.gif')
self.s.addServiceItem(item)
answer = self.s.oos_as_text()
answer = self.s.service_as_text()
log.info(u'Answer = ' + unicode(answer))
lines=answer.split(u'\n')
lines = answer.split(u'\n')
log.info(u'lines = ' + unicode(lines))
assert lines[0].startswith(u'# <openlp.plugins.images.imageserviceitem.ImageServiceItem object')
assert lines[1] == "test.gif"
log.info(u'done')
def test_2items_as_separate_items(self):
# If nothing is selected when item is added, a new base service item is added
# If nothing is selected when item is added, a new base service item
# is added
log.info(u'test_2items_as_separate_items')
item=ImageServiceItem(None)
item = ImageServiceItem(None)
item.add(u'test.gif')
self.s.addServiceItem(item)
item=ImageServiceItem(None)
item = ImageServiceItem(None)
item.add(u'test2.gif')
item.add(u'test3.gif')
self.s.addServiceItem(item)
answer = self.s.oos_as_text()
answer = self.s.service_as_text()
log.info(u'Answer = ' + unicode(answer))
lines=answer.split(u'\n')
lines = answer.split(u'\n')
log.info(u'lines = ' + unicode(lines))
assert lines[0].startswith(u'# <openlp.plugins.images.imageserviceitem.ImageServiceItem object')
assert lines[1] == "test.gif"
@ -108,20 +113,22 @@ class TestServiceManager_base:
log.info(u'done')
def test_2items_merged(self):
# If the first object is selected when item is added it should be extended
# If the first object is selected when item is added it should be
# extended
log.info(u'test_2items_merged')
item=ImageServiceItem(None)
item = ImageServiceItem(None)
item.add(u'test.gif')
self.s.addServiceItem(item)
self.select_row(0)
log.info(u'Selected indexes = ' + unicode(self.s.TreeView.selectedIndexes()))
item=ImageServiceItem(None)
log.info(u'Selected indexes = ' + unicode(
self.s.TreeView.selectedIndexes()))
item = ImageServiceItem(None)
item.add(u'test2.gif')
item.add(u'test3.gif')
self.s.addServiceItem(item)
answer = self.s.oos_as_text()
answer = self.s.service_as_text()
log.info(u'Answer = ' + unicode(answer))
lines=answer.split(u'\n')
lines = answer.split(u'\n')
log.info(u'lines = ' + unicode(lines))
assert lines[0].startswith(u'# <openlp.plugins.images.imageserviceitem.ImageServiceItem object')
assert lines[1] == "test.gif"
@ -138,7 +145,6 @@ class TestServiceManager_base:
if __name__ == "__main__":
t=TestServiceManager_base()
t.setup_class()
t.setup_method(None)

View File

@ -9,21 +9,23 @@ To allow easy development of new "things to display". Examples:
* Powerpoint/Openoffice Impress
* Lyrics :) (with chords, rich text, etc...)
* Musical score
* Midi files (hmmm, that's not a thing to display, but feels like it should be there...)
* Midi files (hmmm, that's not a thing to display, but feels like it should be
there...)
* Audio files, CDs (hmmm again)
* Collections of pictures
* Alerts to members of the congregation
... etc.
The scope of these plugins is "things for display purposes", so
each needs to be able to:
The scope of these plugins is "things for display purposes", so each needs to
be able to:
* Render their display (on the projection screen and in a "shrunken form"
for preview purposes)
These plugins need to be part of an OOS. This means they need to
* Be able to tell the OOS manager code what to put in the OOS for their "bit"
These plugins need to be part of an service. This means they need to
* Be able to tell the service manager code what to put in the service for their
"bit"
* Have a "tab" in the media manager, which they can render on request
to allow bits to be added to the OOS (or indeed shown live)
to allow bits to be added to the service (or indeed shown live)
In addition, some plugins need to be able to show
* How their multiple screens of data are split (eg verses)
@ -41,29 +43,29 @@ Other basic things all plugins will need:
* A version number
* Helpfile?
Funnily enough, the core lyrics engine fits those requirements, so
could actually form a plugin...
Funnily enough, the core lyrics engine fits those requirements, so could
actually form a plugin...
Each OOS entry may be made up of multiple plugins (to do text on
video), so each plugin that contributes to an OOS item will need a
"layering" priority.
Each service entry may be made up of multiple plugins (to do text on video), so
each plugin that contributes to an service item will need a "layering"
priority.
Plugin management
-----------------
Plugins will be packages within the plugins/ directory. The plugin
manager will scan this directory when openlp loads for any class which
is based on the base Plugin class (or should we call it the
DisplayPlugin class to allow for other sorts??)
Plugins will be packages within the plugins/ directory. The plugin manager
will scan this directory when openlp loads for any class which is based on the
base Plugin class (or should we call it the DisplayPlugin class to allow for
other sorts??)
These plugins are then queried for their capabilities/requirements and
spaces made in the prefs UI as required, and in the media manager.
The OOS manager can find out what plugins it has available (we need to
report missing plugins when an OOS is loaded).
The service manager can find out what plugins it has available (we need to
report missing plugins when an service is loaded).
The display manager will get a ref to a/some plugin(s) from the OOS
manager when each OOS item is made live, and can then call on each to
The display manager will get a ref to a/some plugin(s) from the service
manager when each service item is made live, and can then call on each to
render their display.
Each plugin will have basic attributes for
@ -78,8 +80,8 @@ Each plugin will have basic attributes for
and a set of API functions for
* media manager rendering and handling
* creating OOS data
* being told OOS data
* creating service data
* being told service data
* set paint context
* render
* selecting a screen to display